Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

Bardo Tools – Uniswap API tools [SPEC]

Version: 4.0.0 Last Updated: 2026-03-14

Crate: bardo-tools | Prerequisites: 01-architecture.md (ToolDef pattern, trust tiers, capability tokens, safety hooks, and profiles), 20-config.md (environment variables, TOML config schema, API key tiers)

Tools backed by the Uniswap Trading API. Category: trading (swap tools), lp (LP tools), data (reference tools). 21 tools. All require BARDO_UNISWAP_API_KEY.

Protocol framing note: This document covers Uniswap API integration in depth. Equivalent depth of specification exists or will exist for other major DeFi protocols: Aave/Morpho lending tools (07-tools-lending.md), Curve/Balancer AMM tools, Pendle yield tools (11-tools-yield.md), bridging aggregators (05-tools-bridge-aggregator.md). The Uniswap API is one integration among many — not the center of the tool library.


Reader orientation: This document specifies 21 tools backed by the Uniswap Trading API (trade-api.gateway.uniswap.org/v1). These tools provide limit orders, batch execution, EIP-7702 delegation, LP operations via API, and multi-step cross-chain plans. All require a BARDO_UNISWAP_API_KEY. You should be familiar with Uniswap’s swap routing, Permit2, and UniswapX order types. Bardo-specific terms are defined inline on first use; for a full glossary see prd2/shared/glossary.md.

Why the Uniswap API

The Uniswap Trading API is not a convenience wrapper around on-chain calls. It unlocks a different class of DeFi operation that is not achievable by reading chain state or calling smart contracts directly.

vs on-chain reads + direct contract calls

Direct on-chain routing requires implementing a routing algorithm across thousands of pools, with no access to off-chain or private liquidity. The practical gaps:

  • No private liquidity: UniswapX RFQ fillers hold significant off-chain inventory. A direct on-chain swap never touches this liquidity, always trading at worse prices.
  • No MEV protection: Submitting a signed transaction to the public mempool exposes the order to frontrunning and sandwich attacks. UniswapX intents go to a private filler network, bypassing the mempool entirely.
  • No Permit2 optimization: Permit2 batches token approval + transfer into a single signature, saving a full approval transaction. Constructing valid Permit2 calldata from scratch requires replicating protocol-specific logic that the API generates correctly.
  • No cross-chain orchestration: A bridge + swap flow requires coordinating separate protocols (bridge + DEX) with no shared state. The API generates sequenced calldata and tracks proof submission across steps.
  • No gas calibration: Estimating gas accurately requires simulating transactions against current chain state. The API does this server-side with live state, returning calibrated estimates. Client-side estimation is unreliable under congestion.

vs Uniswap SDK (@uniswap/v3-sdk, @uniswap/router-sdk, @uniswap/smart-order-router)

The SDK runs routing client-side using on-chain pool state fetched via RPC. This was the right approach before UniswapX. Now:

  • No RFQ access: The SDK cannot query UniswapX RFQ fillers. It routes through on-chain pools only.
  • No intent submission: There is no SDK path for submitting Dutch v2/v3 or Priority orders. These require the API.
  • No gasless execution: The SDK produces signed transactions. UniswapX gasless orders are a different primitive (signed intents) that only the API supports.
  • No LP migration: The SDK has no concept of migrating a position between protocol versions. /lp/migrate generates the calldata to atomically exit a V3 position and enter a V4 position.
  • No multi-step planning: The SDK does not track multi-step execution state.

vs other aggregators (0x, 1inch, Paraswap)

  • Exclusive RFQ access: UniswapX RFQ fillers are not accessible via other aggregators. Private liquidity from Uniswap’s filler network only routes through the Uniswap API.
  • V4 hooks support: No other aggregator routes through V4 pools with hooks. The hooksOptions parameter enables targeted routing exclusive to this API.
  • Deepest Permit2 integration: Permit2 is a Uniswap-built primitive. The API generates Permit2 calldata with full correctness guarantees.
  • EIP-5792/7702 support: Batch and delegated execution modes are specific to the Uniswap API.

Capabilities only available via API

CapabilityEndpointAlternative
Limit orders (off-chain, on-chain fill)/limit_order_quote + /orderNone
Gasless swaps (filler pays gas)/quote with UniswapX routing + /orderNone
LP migration (V2->V3->V4 calldata)/lp/migrateManual: 2 separate txs, no atomicity
LP rewards claiming/lp/claim_rewardsProtocol-specific, non-standard
EIP-5792 batch execution/swap_5792None (EOA cannot batch)
EIP-7702 smart delegation/swap_7702 + /wallet/encode_7702None (requires delegation setup)
Bridge token enumeration/swappable_tokensManual: query each bridge protocol separately

Paradigms enabled

Gasless agent operation

An agent can operate indefinitely without holding native tokens for gas. UniswapX Dutch v2/v3 orders are signed intents: the agent specifies what it wants, fillers compete to fill it, and the winning filler pays the gas. The agent’s gas cost is priced into the output amount.

Flow: uniswap_api_get_quote with routing_preference: "DUTCH_V2" -> sign the returned quote -> uniswap_api_submit_order. Monitor via uniswap_api_get_orders. No ETH required.

V4-hooks-targeted routing

V4 pools can have hooks – custom contract logic that executes before/after every swap or LP operation. An agent deploying a custom hook strategy needs liquidity to route through that hook’s pool.

uniswap_api_get_quote with hooks_options: "V4_HOOKS_ONLY" routes exclusively through V4 pools with hooks. V4_HOOKS_INCLUSIVE prefers them. V4_NO_HOOKS avoids them. No other way to enforce this constraint exists outside the API.

Limit order portfolios

An agent can maintain an active book of limit orders. Flow: uniswap_api_get_limit_order_quote -> sign -> uniswap_api_submit_order with routing LIMIT_ORDER -> monitor via uniswap_api_get_orders. Unfilled orders expire at order_deadline. Enables DCA, grid trading, and yield-seeking entries without on-chain interaction until fill.

Approval-first safety pipeline

Call uniswap_api_check_approval before any swap or LP operation. It returns whether approval exists and, if not, the approval transaction calldata. This converts on-chain reverts (gas spent, tx failed) into pre-flight errors (no gas spent, no tx submitted).

With EIP-5792, the approval calldata and the swap calldata can be submitted as a single atomic batch.


Configuration

Per-Golem (a mortal autonomous agent compiled as a single Rust binary on a micro-VM) config block

[uniswap_api]
api_key = "your-api-key-from-developers.uniswap.org"
base_url = "https://trade-api.gateway.uniswap.org/v1"
rate_limit = 3
quote_max_age_ms = 30000
gas_buffer_pct = 20
universal_router_version = "2.0"
permit2_enabled = true
enable_lp = true
enable_limit_orders = true
enable_smart_wallet = false
chain_ids = [1, 8453, 42161, 10, 137]

Config precedence: Golem config file > env vars > defaults.

API keys are obtained from developers.uniswap.org.

Environment variables

VariableDefaultDescription
BARDO_UNISWAP_API_KEYAPI key (required to activate API tools)
BARDO_UNISWAP_API_BASE_URLhttps://trade-api.gateway.uniswap.org/v1Base URL override
BARDO_UNISWAP_API_RATE_LIMIT3Requests per second
BARDO_UNISWAP_API_QUOTE_MAX_AGE_MS30000Quote cache TTL (ms)
BARDO_UNISWAP_API_GAS_BUFFER_PCT20Gas estimate buffer percent
BARDO_UNISWAP_ROUTER_VERSION2.0Universal Router version (1.2 or 2.0)

Feature flags

FlagEffect when false
enable_lpLP tools fall back to SDK; uniswap_api_migrate_liquidity, uniswap_api_get_lp_pool_info disabled
enable_limit_ordersuniswap_api_get_limit_order_quote disabled; uniswap_api_submit_order still works for Dutch/Priority orders
enable_smart_walletuniswap_api_batch_swap, uniswap_api_create_delegated_swap disabled

HTTP client

All API tools share a TradingApiClient built on reqwest:

#![allow(unused)]
fn main() {
pub struct TradingApiClient {
    client: reqwest::Client,
    base_url: String,
    api_key: TaintedString,
    rate_limiter: Arc<TokenBucket>,
}

impl TradingApiClient {
    pub async fn get<T: DeserializeOwned>(&self, path: &str, params: &impl Serialize) -> Result<T> {
        self.rate_limiter.acquire().await;
        let resp = self.client
            .get(format!("{}{}", self.base_url, path))
            .header("x-api-key", self.api_key.as_ref())
            .query(params)
            .send()
            .await?;
        Self::handle_response(resp).await
    }

    pub async fn post<T: DeserializeOwned>(&self, path: &str, body: &impl Serialize) -> Result<T> {
        self.rate_limiter.acquire().await;
        let resp = self.client
            .post(format!("{}{}", self.base_url, path))
            .header("x-api-key", self.api_key.as_ref())
            .json(body)
            .send()
            .await?;
        Self::handle_response(resp).await
    }

    fn is_fallback_eligible(status: reqwest::StatusCode) -> bool {
        matches!(status.as_u16(), 429 | 503 | 504)
    }
}
}

Rate limiting: token bucket (default 3 req/sec). The bucket is shared across all API tools within a Golem session.


Swap tools (category: trading)

uniswap_api_get_quote

Requests a quote for a swap, bridge, or wrap/unwrap. Routes across V2/V3/V4 and UniswapX.

ParameterTypeRequiredDescription
token_inStringYesInput token symbol or address
token_outStringYesOutput token symbol or address
token_in_chain_idu64YesChain ID for input token
token_out_chain_idOption<u64>NoChain ID for output token (cross-chain if different)
amountStringYesAmount in token base units
trade_typeStringYes"exactIn" or "exactOut"
swapperOption<String>NoWallet address (required for UniswapX routing)
routing_preferenceOption<String>No"AUTO", "CLASSIC", "DUTCH_V2", "DUTCH_V3", "PRIORITY", "FASTEST". Default: "AUTO"
protocolsOption<Vec<String>>NoRestrict to specific protocols (e.g., ["V4"])
slippage_toleranceOption<u32>NoSlippage in basis points (1-5000)
auto_slippageOption<bool>NoLet API compute optimal slippage
hooks_optionsOption<String>No"V4_HOOKS_INCLUSIVE", "V4_HOOKS_ONLY", "V4_NO_HOOKS"
spread_optimizationOption<bool>NoSpread execution to minimize price impact
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct QuoteResult {
    pub quote_id: String,
    pub token_in: String,
    pub token_out: String,
    pub token_in_chain_id: u64,
    pub token_out_chain_id: u64,
    pub amount_in: String,
    pub amount_out: String,
    pub price_impact: f64,
    pub gas_estimate: String,
    pub gas_estimate_usd: f64,
    pub routing_type: String,
    pub route: serde_json::Value,
    pub permit_data: Option<serde_json::Value>,
    pub valid_until: u64,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetMedium
progress_steps["Requesting quote", "Parsing route"]
sprite_triggerThinking
prompt_snippetGets a swap/bridge/wrap quote from the Uniswap Trading API. Routes across V2/V3/V4 and UniswapX. Prefer over manual routing – exclusive access to RFQ fillers and V4 hooks. Read-only.

promptGuidelines:

  • thriving: Use AUTO routing for most trades. Use DUTCH_V2 for gasless execution. Set hooks_options for hook-specific strategies.
  • cautious: Prefer DUTCH_V2 (gasless) to conserve ETH. Enable auto_slippage.
  • declining: Quote only settlement swaps. Use FASTEST routing.
  • terminal: Quote only final settlement. Use FASTEST with urgency “urgent”.

Event Fabric events: tool:start -> { token_in, token_out, amount, routing_preference } -> tool:end -> { quote_id, amount_out, routing_type, price_impact }


uniswap_api_check_approval

Checks if a wallet has required token spend approval for a swap or LP operation. Returns approval transaction calldata if needed. Consolidates the previously separate check_swap_approval and check_lp_approval into a single tool – the API endpoint is the same, the context (swap vs LP) determines which tokens to check.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address to check
tokensVec<String>YesToken addresses to check approval for
amountsVec<String>YesAmounts in token base units (parallel with tokens)
chain_idu64YesChain ID
permit2_enabledOption<bool>NoCheck Permit2 approval. Default: true
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct ApprovalCheckResult {
    pub all_approved: bool,
    pub token_approvals: Vec<TokenApproval>,
}

#[derive(Debug, Serialize)]
pub struct TokenApproval {
    pub token: String,
    pub approved: bool,
    pub approval_tx: Option<TransactionCalldata>,
    pub permit_data: Option<serde_json::Value>,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Checking approvals"]
sprite_triggerThinking
prompt_snippetChecks wallet token approvals for swap or LP operations. Returns approval tx calldata if needed. ALWAYS call before any write operation. Read-only.

promptGuidelines:

  • All phases: call before every swap or LP operation. Batch approval txs with EIP-5792 if smart wallet is available.

Event Fabric events: tool:start -> { wallet_address, token_count } -> tool:end -> { all_approved, needs_approval_count }


uniswap_api_create_swap_calldata

Converts a quote into executable swap transaction calldata. Call uniswap_api_get_quote first, then pass the quote object here.

ParameterTypeRequiredDescription
quoteserde_json::ValueYesQuote object from uniswap_api_get_quote
signatureOption<String>NoPermit2 signature
simulate_transactionOption<bool>NoSimulate and return gas info
safety_modeOption<bool>NoEnable additional on-chain safety checks
deadlineOption<u64>NoUnix timestamp deadline
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct SwapCalldataResult {
    pub calldata: String,
    pub to: String,
    pub value: String,
    pub chain_id: u64,
    pub gas_estimate: Option<String>,
    pub simulation_result: Option<serde_json::Value>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetMedium
progress_steps["Building calldata", "Simulating"]
sprite_triggerExecuting
prompt_snippetConverts a quote into executable swap transaction calldata. Call uniswap_api_get_quote first. Optional: simulate for gas accuracy and revert detection.

promptGuidelines:

  • thriving: Always set simulate_transaction: true for trades >$1000. Use safety_mode: true.
  • cautious: Always simulate. Always use safety_mode.
  • declining: Simulate and execute settlement trades only.
  • terminal: Simulate. Set urgency urgent.

Ground truth: expected_outcome = quote amount_out. actual_outcome = simulation output. ground_truth_source = "api_simulation".

Event Fabric events: tool:start -> { quote_id, simulate_transaction } -> tool:end -> { calldata_length, gas_estimate }


uniswap_api_batch_swap

Generates EIP-5792 wallet_sendCalls payload for a swap. Requires a smart wallet supporting EIP-5792. Bundles approval + swap into a single atomic batch.

ParameterTypeRequiredDescription
quoteserde_json::ValueYesQuote object from uniswap_api_get_quote
permit_dataOption<serde_json::Value>NoPermit data for approval batching
deadlineOption<u64>NoUnix timestamp deadline
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct BatchSwapResult {
    pub calls: Vec<TransactionCalldata>,
    pub chain_id: u64,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetMedium
progress_steps["Building batch"]
sprite_triggerExecuting
prompt_snippetGenerates EIP-5792 wallet_sendCalls payload for a swap. Requires smart wallet. Bundles approval + swap atomically.

Capability gate: enable_smart_wallet = true.

Event Fabric events: tool:start -> { quote_id } -> tool:end -> { call_count, chain_id }


uniswap_api_create_delegated_swap

Generates EIP-7702 calldata for smart contract wallet delegation execution.

ParameterTypeRequiredDescription
quoteserde_json::ValueYesQuote object from uniswap_api_get_quote
delegation_addressStringYesAddress of the delegation target contract
permit_dataOption<serde_json::Value>NoPermit data
simulate_transactionOption<bool>NoSimulate and return gas info
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct DelegatedSwapResult {
    pub calldata: String,
    pub to: String,
    pub value: String,
    pub chain_id: u64,
    pub gas_info: Option<serde_json::Value>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetMedium
progress_steps["Encoding delegation"]
sprite_triggerExecuting
prompt_snippetGenerates EIP-7702 calldata for smart contract wallet delegation execution. Requires delegation setup.

Capability gate: enable_smart_wallet = true.

Event Fabric events: tool:start -> { quote_id } -> tool:end -> { calldata_length, chain_id }


uniswap_api_submit_order

Submits a signed UniswapX intent or limit order to the filler network. Gasless – filler pays gas. Consolidates the previously separate submit_uniswapx_order naming.

ParameterTypeRequiredDescription
signatureStringYesEIP-712 signature of the quote
quoteserde_json::ValueYesThe signed quote object
routingStringYes"DUTCH_V2", "DUTCH_V3", "PRIORITY", "LIMIT_ORDER"
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct SubmitOrderResult {
    pub order_id: String,
    pub order_hash: String,
    pub status: String,
    pub created_at: u64,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetMedium
progress_steps["Validating signature", "Submitting to filler network"]
sprite_triggerExecuting
prompt_snippetSubmits a signed UniswapX intent to the filler network. Gasless – filler pays gas. Requires EIP-712 signature. Supports Dutch v2/v3, Priority, and Limit orders.

promptGuidelines:

  • thriving: Prefer for trades >$1000 (MEV protection + gasless). DUTCH_V2 for market orders, LIMIT_ORDER for DCA.
  • cautious: Prefer for all trades (gasless conserves ETH). Monitor fill via uniswap_api_get_orders.
  • declining: Use for settlement orders (gasless is critical when ETH is scarce).
  • terminal: Use for final settlement orders only.

Ground truth: expected_outcome = order submitted with status “open”. actual_outcome = API response status. ground_truth_source = "uniswapx_api".

Event Fabric events: tool:start -> { routing, order_hash } -> tool:end -> { order_id, status }


uniswap_api_get_orders

Retrieves and filters UniswapX orders. At least one filter parameter is required.

ParameterTypeRequiredDescription
swapperOption<String>NoFilter by swapper address
order_idsOption<Vec<String>>NoFilter by specific order IDs
order_statusOption<String>No"open", "expired", "error", "cancelled", "filled", "insufficient-funds"
order_typeOption<String>NoFilter by order type
limitOption<u32>NoMax results. Default: 10
cursorOption<String>NoPagination cursor
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct GetOrdersResult {
    pub orders: Vec<OrderEntry>,
    pub cursor: Option<String>,
}

#[derive(Debug, Serialize)]
pub struct OrderEntry {
    pub order_id: String,
    pub order_hash: String,
    pub status: String,
    pub swapper: String,
    pub input: TokenAmount,
    pub output: TokenAmount,
    pub deadline: u64,
    pub created_at: u64,
    pub filled_at: Option<u64>,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Fetching orders"]
sprite_triggerThinking
prompt_snippetRetrieves UniswapX orders. Filter by swapper, order ID, status. Use to monitor pending gasless orders. Read-only.

Event Fabric events: tool:start -> { filter_count } -> tool:end -> { order_count }


uniswap_api_check_swap_status

Gets the status of swap or bridge transactions by hash.

ParameterTypeRequiredDescription
transaction_hashesVec<String>YesTransaction hashes to check
chain_idu64YesChain ID where transactions were submitted
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct SwapStatusResult {
    pub swaps: Vec<SwapStatus>,
}

#[derive(Debug, Serialize)]
pub struct SwapStatus {
    pub tx_hash: String,
    pub status: String,   // "PENDING", "SUCCESS", "FAILED", "EXPIRED", "NOT_FOUND"
    pub details: Option<serde_json::Value>,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Checking status"]
sprite_triggerThinking
prompt_snippetGets status of swap or bridge transactions by hash. Supports batch checking. Read-only.

Event Fabric events: tool:start -> { hash_count } -> tool:end -> { statuses }


uniswap_api_get_limit_order_quote

Gets a quote for a limit order at a specified price.

ParameterTypeRequiredDescription
swapperStringYesWallet address placing the order
token_inStringYesInput token address
token_outStringYesOutput token address
chain_idu64YesChain ID
amountStringYesInput amount in token base units
limit_priceStringYesMinimum output amount (limit price as token ratio)
trade_typeStringYes"exactIn" or "exactOut"
order_deadlineu64YesUnix timestamp when order expires
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct LimitOrderQuoteResult {
    pub quote: serde_json::Value,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer2
tick_budgetMedium
progress_steps["Requesting limit quote"]
sprite_triggerThinking
prompt_snippetGets a quote for a limit order at a specified price. Sign the quote, then submit via uniswap_api_submit_order with routing LIMIT_ORDER. No gas until fill.

promptGuidelines:

  • thriving: Use for DCA strategies, grid trading, yield-seeking entries (e.g., limit buy 2% below market).
  • cautious: Conservative entries only. Set tight expiry.
  • declining: Not applicable for new orders.
  • terminal: Not applicable.

Capability gate: enable_limit_orders = true.

Event Fabric events: tool:start -> { token_in, token_out, limit_price } -> tool:end -> { quote_valid }


LP tools (category: lp)

LP tools follow the API-first / SDK-fallback pattern. When the API key is set and enable_lp is true, these tools route through the Uniswap API. If the API returns a fallback-eligible error (429, 503, 504, network timeout), they fall back to the TypeScript sidecar running the Uniswap SDK.

#![allow(unused)]
fn main() {
async fn api_first_with_fallback<T>(
    api: &TradingApiClient,
    sidecar: &SidecarClient,
    api_call: impl Future<Output = Result<T>>,
    sdk_call: impl Future<Output = Result<T>>,
) -> Result<T> {
    match api_call.await {
        Ok(result) => Ok(result),
        Err(e) if TradingApiClient::is_fallback_eligible_error(&e) => sdk_call.await,
        Err(e) => Err(e),
    }
}
}

uniswap_api_create_lp_position

Creates a new LP position.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address creating the position
token0StringYesToken 0 address or symbol
token1StringYesToken 1 address or symbol
chain_idu64YesChain ID
fee_tieru32YesFee tier in bps (100, 500, 3000, 10000)
amount0StringYesAmount of token0 in base units
amount1StringYesAmount of token1 in base units
tick_lowerOption<i32>NoLower tick (V3/V4 only)
tick_upperOption<i32>NoUpper tick (V3/V4 only)
protocolOption<String>No"V2", "V3", "V4". Default: "V4"
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct CreateLpResult {
    pub txs: Vec<TransactionCalldata>,
    pub position_id: Option<String>,
    pub pool_address: String,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetMedium
progress_steps["Checking approvals", "Building position calldata", "Simulating"]
sprite_triggerExecuting
prompt_snippetCreates a new LP position via the Uniswap API. API-first with SDK fallback. Supports V2, V3, V4. Default: V4.

promptGuidelines:

  • thriving: Create positions in V4 pools for best efficiency. Set tick ranges based on strategy.
  • cautious: No new LP positions.
  • declining: Blocked.
  • terminal: Blocked.

Ground truth: expected_outcome = position created at specified tick range. actual_outcome = simulation result. ground_truth_source = "api_simulation".

Event Fabric events: tool:start -> { token0, token1, protocol, fee_tier } -> tool:end -> { position_id, pool_address }


uniswap_api_increase_lp_position

Adds liquidity to an existing LP position.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address
position_idStringYesPosition token ID or NFT ID
chain_idu64YesChain ID
amount0Option<String>NoAdditional amount of token0
amount1Option<String>NoAdditional amount of token1
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct IncreaseLpResult {
    pub txs: Vec<TransactionCalldata>,
    pub new_liquidity: String,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer2
tick_budgetMedium
progress_steps["Building increase calldata"]
sprite_triggerExecuting
prompt_snippetAdds liquidity to an existing LP position. API-first with SDK fallback. Phase-gated: blocked in declining/terminal.

Event Fabric events: tool:start -> { position_id } -> tool:end -> { new_liquidity }


uniswap_api_decrease_lp_position

Removes liquidity from an existing LP position.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address
position_idStringYesPosition token ID or NFT ID
chain_idu64YesChain ID
liquidity_pctOption<u32>NoPercent of liquidity to remove (1-100). Default: 100
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct DecreaseLpResult {
    pub txs: Vec<TransactionCalldata>,
    pub amount0_out: String,
    pub amount1_out: String,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer2
tick_budgetMedium
progress_steps["Building decrease calldata"]
sprite_triggerExecuting
prompt_snippetRemoves liquidity from an LP position. Default: remove 100%. Allowed at any phase.

promptGuidelines:

  • thriving: Remove to rebalance or capture fees.
  • cautious: Remove from out-of-range positions.
  • declining: Remove all liquidity. Mandatory.
  • terminal: Remove any remaining.

Ground truth: expected_outcome = liquidity_pct% removed. actual_outcome = amounts returned. ground_truth_source = "api_simulation".

Event Fabric events: tool:start -> { position_id, liquidity_pct } -> tool:end -> { amount0_out, amount1_out }


uniswap_api_claim_lp_fees

Claims accrued trading fees from an LP position.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address
position_idStringYesPosition token ID or NFT ID
chain_idu64YesChain ID
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct ClaimFeesResult {
    pub txs: Vec<TransactionCalldata>,
    pub fee0_amount: String,
    pub fee1_amount: String,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer1
tick_budgetMedium
progress_steps["Building claim calldata"]
sprite_triggerExecuting
prompt_snippetClaims accrued trading fees from an LP position. API-first with SDK fallback. Allowed at any phase.

Event Fabric events: tool:start -> { position_id } -> tool:end -> { fee0_amount, fee1_amount }


uniswap_api_migrate_liquidity

Generates calldata to migrate an LP position between protocol versions. Supports V2->V3, V3->V4. The migration is atomic – single transaction, no position downtime.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address
position_idStringYesCurrent position ID
from_protocolStringYes"V2" or "V3"
to_protocolStringYes"V3" or "V4"
chain_idu64YesChain ID
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct MigrateLiquidityResult {
    pub txs: Vec<TransactionCalldata>,
    pub new_position_id: Option<String>,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetSlow
progress_steps["Checking migration path", "Building exit calldata", "Building enter calldata", "Simulating atomic migration"]
sprite_triggerExecuting
prompt_snippetAtomically migrates an LP position between protocol versions (V2->V3, V3->V4). Single transaction, no position downtime. Requires API.

promptGuidelines:

  • thriving: Migrate V3->V4 when V4 pool shows better fee yield. Use uniswap_api_get_lp_pool_info to compare.
  • cautious: Only migrate if V4 fee yield exceeds V3 by >20%.
  • declining: Do not migrate. Focus on removing liquidity.
  • terminal: Do not migrate.

Ground truth: expected_outcome = position migrated to target protocol. actual_outcome = new position ID. ground_truth_source = "api_simulation".

Event Fabric events: tool:start -> { position_id, from_protocol, to_protocol } -> tool:end -> { new_position_id }


uniswap_api_claim_rewards

Claims protocol incentive rewards for an LP position.

ParameterTypeRequiredDescription
wallet_addressStringYesWallet address
position_idStringYesPosition ID
chain_idu64YesChain ID
simulate_transactionOption<bool>NoSimulate and return gas estimate
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct ClaimRewardsResult {
    pub txs: Vec<TransactionCalldata>,
    pub reward_amounts: Vec<TokenAmount>,
    pub gas_estimate: Option<String>,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer1
tick_budgetMedium
progress_steps["Building claim calldata"]
sprite_triggerExecuting
prompt_snippetClaims protocol incentive rewards for an LP position. Allowed at any phase.

Event Fabric events: tool:start -> { position_id } -> tool:end -> { reward_amounts }


uniswap_api_get_lp_pool_info

Returns detailed pool information. More complete than uniswap_get_pool_info: includes fee income rates and reward program info.

ParameterTypeRequiredDescription
chain_idu64YesChain ID
pool_addressOption<String>NoPool contract address
pair_addressOption<String>NoV2 pair address
pool_idOption<String>NoV4 pool ID

At least one of pool_address, pair_address, or pool_id is required.

#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct LpPoolInfoResult {
    pub pool_id: String,
    pub token0: TokenMeta,
    pub token1: TokenMeta,
    pub fee_tier: u32,
    pub protocol: String,
    pub tvl: f64,
    pub volume_24h: f64,
    pub fees_24h: f64,
    pub current_tick: i32,
    pub sqrt_price_x96: String,
    pub liquidity: String,
    pub reward_programs: Option<Vec<serde_json::Value>>,
    pub hooks: Option<Vec<String>>,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Fetching pool info"]
sprite_triggerThinking
prompt_snippetReturns detailed pool info: TVL, volume, fee rates, current tick, reward programs, hooks. More complete than uniswap_get_pool_info. Read-only.

Event Fabric events: tool:start -> { pool_address } -> tool:end -> { tvl, fees_24h }


Reference tools (category: data)

uniswap_api_get_bridgeable_tokens

Returns all destination chains where a given token can be bridged, with bridge protocol for each route.

ParameterTypeRequiredDescription
token_inStringYesToken address on source chain
chain_idu64YesSource chain ID
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct BridgeableTokensResult {
    pub destinations: Vec<BridgeDestination>,
}

#[derive(Debug, Serialize)]
pub struct BridgeDestination {
    pub chain_id: u64,
    pub bridge_token: String,
    pub bridge_token_address: String,
    pub bridge_protocol: String,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Querying bridge routes"]
sprite_triggerThinking
prompt_snippetReturns all destination chains where a token can be bridged, with bridge protocol for each route. Use for cross-chain arbitrage discovery. Read-only.

Event Fabric events: tool:start -> { token_in, chain_id } -> tool:end -> { destination_count }


Wallet utility tools (category: wallet)

uniswap_api_create_token_transfer

Generates calldata for an ERC-20 token transfer with server-side gas estimation.

ParameterTypeRequiredDescription
senderStringYesSending wallet address
recipientStringYesRecipient address
tokenStringYesERC-20 token address
amountStringYesAmount in token base units
chain_idu64YesChain ID
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct TokenTransferResult {
    pub calldata: String,
    pub to: String,
    pub value: String,
    pub chain_id: u64,
    pub gas_estimate: String,
}
}

ToolDef:

FieldValue
capabilityWrite
risk_tierLayer3
tick_budgetFast
progress_steps["Building transfer calldata"]
sprite_triggerExecuting
prompt_snippetGenerates ERC-20 transfer calldata with server-side gas estimation. Does not execute – returns calldata for commit_action.

promptGuidelines:

  • thriving: Transfer as needed for strategy execution.
  • cautious: Transfer only for operating needs. Smaller amounts.
  • declining: Transfer only to owner wallet for settlement.
  • terminal: Transfer only for Death Protocol asset sweep.

Ground truth: expected_outcome = transfer of amount to recipient. actual_outcome = calldata generated. ground_truth_source = "api_gas_simulation".

Event Fabric events: tool:start -> { token, amount, recipient } -> tool:end -> { calldata_length, gas_estimate }


uniswap_api_check_wallet_delegation

Gets current EIP-7702 delegation status for a wallet across multiple chains.

ParameterTypeRequiredDescription
wallet_addressStringYesSmart wallet address to check
chain_idsVec<u64>YesChain IDs to check
#![allow(unused)]
fn main() {
#[derive(Debug, Serialize)]
pub struct DelegationStatusResult {
    pub delegations: Vec<DelegationEntry>,
}

#[derive(Debug, Serialize)]
pub struct DelegationEntry {
    pub chain_id: u64,
    pub delegated: bool,
    pub delegation_address: Option<String>,
    pub message: Option<String>,
}
}

ToolDef:

FieldValue
capabilityRead
risk_tierLayer1
tick_budgetFast
progress_steps["Checking delegations"]
sprite_triggerThinking
prompt_snippetGets EIP-7702 delegation status for a wallet across multiple chains. Returns re-delegation info if any chain is stale. Read-only.

Event Fabric events: tool:start -> { wallet_address, chain_count } -> tool:end -> { delegations }


Shared types

#![allow(unused)]
fn main() {
#[derive(Debug, Serialize, Deserialize)]
pub struct TransactionCalldata {
    pub to: String,
    pub data: String,
    pub value: String,
    pub chain_id: u64,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TokenAmount {
    pub token: String,
    pub amount: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TokenMeta {
    pub address: String,
    pub symbol: String,
    pub decimals: u8,
}
}

Custody implications (API write tools)

Write tools that submit orders or execute transactions via the Uniswap Trading API:

  • Delegation: Session key signs Permit2 messages or order structs. The API handles routing and gas. CaveatEnforcer must whitelist the Permit2 contract and Universal Router. Spending limits apply to order amounts.
  • Embedded: Privy server wallet signs. PolicyCage validates order parameters and spending limits.
  • Local Key: Local keypair signs. On-chain delegation bounds constrain Permit2 allowances and router targets.

Read-only API tools (quotes, order status, pool queries) require no signing — only the BARDO_UNISWAP_API_KEY environment variable.


Capability gates

CapabilityTools gatedConfig flag
uniswap_apiAll 21 tools in this fileapi_key present
smart_walletuniswap_api_batch_swap, uniswap_api_create_delegated_swapenable_smart_wallet = true
walletuniswap_api_submit_order, uniswap_api_migrate_liquidityWallet configured
limit_ordersuniswap_api_get_limit_order_quoteenable_limit_orders = true

Tool summary

ToolCategoryCapabilityRiskBudget
uniswap_api_get_quotetradingReadLayer 1Medium
uniswap_api_check_approvaltradingReadLayer 1Fast
uniswap_api_create_swap_calldatatradingWriteLayer 3Medium
uniswap_api_batch_swaptradingWriteLayer 3Medium
uniswap_api_create_delegated_swaptradingWriteLayer 3Medium
uniswap_api_submit_ordertradingWriteLayer 3Medium
uniswap_api_get_orderstradingReadLayer 1Fast
uniswap_api_check_swap_statustradingReadLayer 1Fast
uniswap_api_get_limit_order_quotetradingReadLayer 2Medium
uniswap_api_create_lp_positionlpWriteLayer 3Medium
uniswap_api_increase_lp_positionlpWriteLayer 2Medium
uniswap_api_decrease_lp_positionlpWriteLayer 2Medium
uniswap_api_claim_lp_feeslpWriteLayer 1Medium
uniswap_api_migrate_liquiditylpWriteLayer 3Slow
uniswap_api_claim_rewardslpWriteLayer 1Medium
uniswap_api_get_lp_pool_infolpReadLayer 1Fast
uniswap_api_get_bridgeable_tokensdataReadLayer 1Fast
uniswap_api_create_token_transferwalletWriteLayer 3Fast
uniswap_api_check_wallet_delegationwalletReadLayer 1Fast

Consolidation notes (24 -> 21):

  • uniswap_api_check_swap_approval + uniswap_api_check_lp_approval merged into uniswap_api_check_approval. Both hit the same API endpoint; the only difference was which tokens to check. Now accepts a tokens array.
  • uniswap_api_submit_uniswapx_order renamed to uniswap_api_submit_order. Cleaner name, same semantics.
  • uniswap_api_get_uniswapx_orders renamed to uniswap_api_get_orders. Cleaner name, same semantics.
  • uniswap_api_encode_eip7702 removed. It was a thin wrapper around transaction encoding that uniswap_api_create_delegated_swap already handles internally. Exposing raw EIP-7702 encoding as a separate tool added no value – the Golem never needs to encode arbitrary transaction batches outside the swap flow.

Relationship to core trading/LP tools: The uniswap_ prefix tools in 02-tools-onchain-data.md and 04-tools-trading.md read on-chain state directly via Alloy. The uniswap_api_ prefix tools in this file call the Uniswap Trading API via reqwest. Both coexist. The API tools provide routing, gasless execution, and cross-chain orchestration that on-chain reads cannot. The on-chain tools provide raw data access that doesn’t require an API key.