write.asset_manager.yield_claimer_cowswap
Claim LP fees from any position, then swap collected tokens to a target token using CowSwap's MEV-protected batch auctions. Encodes all required arguments for both yield claimer and CowSwapper.
Instructions
Encode args for yield claimer coupled with CowSwap. Claims LP fees, then swaps the claimed tokens to a target token via CowSwap batch auctions (MEV-protected). For staked LPs, sell_tokens is the staking reward token list (e.g. [AERO_address]). For non-staked LPs, sell_tokens is all LP fee tokens except the buy_token — e.g. for a WETH/USDC LP claiming fees as USDC, use sell_tokens: [WETH_address], buy_token: USDC_address. Sets metadata on BOTH the CowSwapper and the Yield Claimer. Returns { asset_managers, statuses, datas } with 2 entries (cowswapper + yield_claimer). Base only. Combinable with other intent tools.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dex_protocol | Yes | DEX protocol of the LP position — used to resolve the correct asset manager address. | |
| sell_tokens | Yes | Token addresses to sell. Staked LP: [AERO]. Non-staked: [token0, token1] minus buy_token. | |
| buy_token | Yes | Token address to receive after swap | |
| fee_recipient | Yes | Address to receive claimed fees | |
| enabled | No | True to enable, false to disable | |
| chain_id | No | Chain ID: 8453 (Base), 130 (Unichain), or 10 (Optimism) |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| description | No | ||
| asset_managers | Yes | ||
| statuses | Yes | ||
| datas | Yes | ||
| strategy_name | No |
Implementation Reference
- The main handler function for the 'write.asset_manager.yield_claimer_cowswap' tool. Validates inputs, resolves CowSwapper and YieldClaimer addresses, encodes CowSwap token metadata and yield claimer coupled callback data, and returns the formatted result with both asset manager entries.
async (params) => { try { const validChainId = validateChainId(params.chain_id); const amKey = dexProtocolToAmKey(params.dex_protocol); let cowSwapperAddress: string; try { cowSwapperAddress = getStandaloneAmAddress(validChainId, "cowSwapper"); } catch (err) { const reason = err instanceof Error ? err.message : String(err); throw new Error(`yield_claimer_cowswap requires cow_swapper. ${reason}`); } const yieldClaimerAddress = getAmProtocolAddress(validChainId, "yieldClaimers", amKey); if (!params.enabled) { return formatResult( disabledIntent( [cowSwapperAddress, yieldClaimerAddress], `Disable yield_claimer_cowswap (${params.dex_protocol})`, ), ); } const validSellTokens = params.sell_tokens.map((t, i) => validateAddress(t, `sell_tokens[${i}]`), ); const validBuyToken = validateAddress(params.buy_token, "buy_token"); const validFeeRecipient = validateAddress(params.fee_recipient, "fee_recipient"); const cowSwapperData = encodeCowSwapTokenMetadata( "cow_swap_yield_claim", validSellTokens, validBuyToken, ); const yieldClaimerData = encodeYieldClaimerCoupledCallbackData( COWSWAPPER_INITIATOR, validFeeRecipient, "cow_swap_yield_claim", ); const result = { description: `Enable yield_claimer_cowswap (${params.dex_protocol}, cowswap)`, asset_managers: [cowSwapperAddress, yieldClaimerAddress], statuses: [true, true], datas: [cowSwapperData, yieldClaimerData], }; return formatResult(result); } catch (err) { return { content: [ { type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, ); - src/tools/write/asset-managers/yield-claimer.ts:78-163 (registration)Registration of the 'write.asset_manager.yield_claimer_cowswap' tool on the MCP server, including annotations (title, readOnlyHint, destructiveHint, etc.), description, inputSchema (dex_protocol, sell_tokens, buy_token, fee_recipient, enabled, chain_id), and outputSchema (IntentOutput).
server.registerTool( "write.asset_manager.yield_claimer_cowswap", { annotations: { title: "Encode Yield Claimer + CowSwap Automation", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false, }, description: "Encode args for yield claimer coupled with CowSwap. Claims LP fees, then swaps the claimed tokens to a target token via CowSwap batch auctions (MEV-protected). For staked LPs, sell_tokens is the staking reward token list (e.g. [AERO_address]). For non-staked LPs, sell_tokens is all LP fee tokens except the buy_token — e.g. for a WETH/USDC LP claiming fees as USDC, use sell_tokens: [WETH_address], buy_token: USDC_address. Sets metadata on BOTH the CowSwapper and the Yield Claimer. Returns { asset_managers, statuses, datas } with 2 entries (cowswapper + yield_claimer). Base only. Combinable with other intent tools.", outputSchema: IntentOutput, inputSchema: { dex_protocol: DEX_PROTOCOL_SCHEMA, sell_tokens: z .array(z.string()) .describe( "Token addresses to sell. Staked LP: [AERO]. Non-staked: [token0, token1] minus buy_token.", ), buy_token: z.string().describe("Token address to receive after swap"), fee_recipient: z.string().describe("Address to receive claimed fees"), enabled: z.boolean().default(true).describe("True to enable, false to disable"), chain_id: z.number().default(8453).describe(CHAIN_ID_DESCRIPTION), }, }, async (params) => { try { const validChainId = validateChainId(params.chain_id); const amKey = dexProtocolToAmKey(params.dex_protocol); let cowSwapperAddress: string; try { cowSwapperAddress = getStandaloneAmAddress(validChainId, "cowSwapper"); } catch (err) { const reason = err instanceof Error ? err.message : String(err); throw new Error(`yield_claimer_cowswap requires cow_swapper. ${reason}`); } const yieldClaimerAddress = getAmProtocolAddress(validChainId, "yieldClaimers", amKey); if (!params.enabled) { return formatResult( disabledIntent( [cowSwapperAddress, yieldClaimerAddress], `Disable yield_claimer_cowswap (${params.dex_protocol})`, ), ); } const validSellTokens = params.sell_tokens.map((t, i) => validateAddress(t, `sell_tokens[${i}]`), ); const validBuyToken = validateAddress(params.buy_token, "buy_token"); const validFeeRecipient = validateAddress(params.fee_recipient, "fee_recipient"); const cowSwapperData = encodeCowSwapTokenMetadata( "cow_swap_yield_claim", validSellTokens, validBuyToken, ); const yieldClaimerData = encodeYieldClaimerCoupledCallbackData( COWSWAPPER_INITIATOR, validFeeRecipient, "cow_swap_yield_claim", ); const result = { description: `Enable yield_claimer_cowswap (${params.dex_protocol}, cowswap)`, asset_managers: [cowSwapperAddress, yieldClaimerAddress], statuses: [true, true], datas: [cowSwapperData, yieldClaimerData], }; return formatResult(result); } catch (err) { return { content: [ { type: "text" as const, text: `Error: ${err instanceof Error ? err.message : String(err)}`, }, ], isError: true, }; } }, ); - Input schema for the yield_claimer_cowswap tool: dex_protocol (enum), sell_tokens (string[]), buy_token (string), fee_recipient (string), enabled (boolean, default true), chain_id (number, default 8453).
inputSchema: { dex_protocol: DEX_PROTOCOL_SCHEMA, sell_tokens: z .array(z.string()) .describe( "Token addresses to sell. Staked LP: [AERO]. Non-staked: [token0, token1] minus buy_token.", ), buy_token: z.string().describe("Token address to receive after swap"), fee_recipient: z.string().describe("Address to receive claimed fees"), enabled: z.boolean().default(true).describe("True to enable, false to disable"), chain_id: z.number().default(8453).describe(CHAIN_ID_DESCRIPTION), }, - src/tools/output-schemas.ts:32-38 (schema)IntentOutput schema used as output schema for the tool: description (optional), asset_managers (string[]), statuses (boolean[]), datas (string[]), strategy_name (optional string).
export const IntentOutput = z.object({ description: z.string().optional(), asset_managers: z.array(z.string()), statuses: z.array(z.boolean()), datas: z.array(z.string()), strategy_name: z.string().optional(), }); - Helper function encodeCowSwapTokenMetadata that encodes sell_tokens and buy_token into ABI-encoded metadata for the CowSwapper, used by the yield_claimer_cowswap handler.
export function encodeCowSwapTokenMetadata( strategy: string, sellTokens: `0x${string}`[], buyToken: `0x${string}`, ): `0x${string}` { const innerData = encodeAbiParameters( [ { name: "sellTokens", type: "address[]" }, { name: "buyToken", type: "address" }, ], [sellTokens, buyToken], ); return encodeOuterMetadata(strategy, innerData); } - Helper function encodeYieldClaimerCoupledCallbackData that encodes the yield claimer callback data with coupled CowSwap metadata, used by the yield_claimer_cowswap handler.
export function encodeYieldClaimerCoupledCallbackData( initiator: `0x${string}`, feeRecipient: `0x${string}`, strategy: string, ): `0x${string}` { const metaData = encodeCoupledStrategyMetadata(strategy); return encodeAbiParameters( [ { name: "initiator", type: "address" }, { name: "feeRecipient", type: "address" }, { name: "maxClaimFee", type: "uint256" }, { name: "metaData_", type: "bytes" }, ], [initiator, feeRecipient, DEFAULT_MAX_CLAIM_FEE, metaData], ); }