import { z } from 'zod';
import { DataiClient } from '../utils/api-client.js';
import { WalletAddressSchema, ChainSchema } from '../utils/validation.js';
import { DataAIError, ValidationError, APIError, NetworkError, TimeoutError } from '../utils/error-handler.js';
/**
* Tool 3: Get User DeFi Positions by Multiple Chains
*
* COMPREHENSIVE DESCRIPTION:
* This tool fetches DeFi positions for a specific wallet address across multiple specified blockchain networks.
* It allows for targeted multi-chain analysis by selecting specific chains of interest rather than querying all chains.
* Perfect for comparing positions across Layer 1 vs Layer 2, or analyzing specific ecosystem exposure.
*
* USE CASES:
* - Multi-chain portfolio comparison
* - Layer 1 vs Layer 2 analysis
* - Ecosystem-specific exposure (e.g., Ethereum + Arbitrum)
* - Migration planning between chains
* - Selective chain monitoring
* - Cost-benefit analysis across networks
*
* PERFORMANCE:
* - Faster than all-chain queries when targeting specific chains
* - Typical response time: 2-5 seconds (depending on chain count)
* - Parallel processing for multiple chains
* - Optimized for 2-5 chain queries
*/
export function createGetUserDeFiPositionsByMultipleChainsTool(client: DataiClient) {
return {
name: "get_defi_multi_chains",
description: "Get DeFi positions for a wallet across multiple specified blockchain networks. Allows targeted multi-chain analysis by selecting specific chains of interest for comparison and portfolio analysis.",
parameters: z.object({
wallet: WalletAddressSchema.describe("Ethereum wallet address (42-character hex string starting with 0x) to get DeFi positions for"),
chains: z.array(ChainSchema).min(1).describe("Array of blockchain networks to query. Example: ['eth', 'arb', 'base']. Supported: eth, arb, matic, avax, bsc, base, op")
}),
annotations: {
readOnlyHint: true,
destructiveHint: false,
openWorldHint: true,
idempotentHint: true,
streamingHint: false,
title: "Multi-Chain DeFi Positions",
category: "Multi-Chain Analysis",
tags: ["defi", "multi-chain", "selective", "comparison", "positions"]
},
execute: async (args: { wallet: string; chains: string[] }, context: { log: any }) => {
const { log } = context;
const startTime = Date.now();
const executionId = crypto.randomUUID().slice(0, 8);
log.info("Starting get_defi_multi_chains", {
executionId,
wallet: args.wallet,
chains: args.chains
});
try {
// Validate parameters
const validatedArgs = {
wallet: WalletAddressSchema.parse(args.wallet),
chains: z.array(ChainSchema).min(1).parse(args.chains)
};
// Make API request
const response = await client.getUserDeFiPositionsByMultipleChains(validatedArgs.wallet, validatedArgs.chains);
const duration = Date.now() - startTime;
const positionCount = Array.isArray(response.data) ? response.data.length : 0;
log.info("Multi-chain DeFi positions fetched successfully", {
executionId,
wallet: validatedArgs.wallet,
positionCount,
duration: `${duration}ms`
});
return {
content: [{
type: "text" as const,
text: JSON.stringify(response.data, null, 2)
}]
};
} catch (error: any) {
const duration = Date.now() - startTime;
log.error("Failed to fetch multi-chain DeFi positions", {
executionId,
wallet: args.wallet,
chains: args.chains,
duration: `${duration}ms`,
error: error.message,
errorType: error.constructor.name,
errorCode: error.code || 'UNKNOWN',
success: false
});
// Transform error for user-friendly response
if (error instanceof ValidationError) {
if (error.message.includes('wallet')) {
throw new DataAIError(
`Invalid wallet address: ${args.wallet}. Please provide a valid Ethereum address (42 characters, starting with 0x).`,
'VALIDATION_ERROR'
);
} else if (error.message.includes('chains')) {
throw new DataAIError(
`Invalid chains array: ${JSON.stringify(args.chains)}. Please provide an array of valid chain identifiers: eth, arb, matic, avax, bsc, base, op.`,
'VALIDATION_ERROR'
);
} else {
throw new DataAIError(`Invalid parameters: ${error.message}`, 'VALIDATION_ERROR');
}
} else if (error instanceof TimeoutError) {
throw new DataAIError(
`Request timed out after ${duration}ms for ${args.chains.length} chains. Multi-chain queries may take longer. Please try again or reduce the number of chains.`,
'TIMEOUT_ERROR'
);
} else if (error instanceof NetworkError) {
throw new DataAIError(
`Network error occurred while fetching DeFi positions across ${args.chains.length} chains. Please check your connection and try again.`,
'NETWORK_ERROR'
);
} else if (error instanceof APIError) {
if (error.message.includes('404')) {
throw new DataAIError(
`No DeFi positions found for wallet ${args.wallet} on the specified chains: ${args.chains.join(', ')}. The wallet may not be active on these networks.`,
'NOT_FOUND'
);
} else if (error.message.includes('429')) {
throw new DataAIError(
'Rate limit exceeded. Multi-chain queries are resource-intensive. Please wait a moment before making another request.',
'RATE_LIMIT_EXCEEDED'
);
} else {
throw new DataAIError(`API error: ${error.message}`, 'API_ERROR');
}
} else {
throw new DataAIError(
`Failed to fetch DeFi positions across chains ${args.chains.join(', ')}: ${error.message}. Please try again or contact support if the issue persists.`,
'UNKNOWN_ERROR'
);
}
}
}
};
}