quoteSwap.test.ts•6.69 kB
import { test, expect, describe } from "bun:test";
import { quoteSwapTool } from "../tools/quoteSwap";
describe("quoteSwap - Preview Mode", () => {
test("should return valid estimation without wallet", async () => {
// Test parameters: swap USDC on Arbitrum to USDC on Ethereum (PREVIEW MODE - without user addresses)
const params = {
srcChainId: "42161", // Arbitrum
srcToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831", // USDC on Arbitrum
amount: "1000000", // 1 USDC (6 decimals)
dstChainId: "1", // Ethereum mainnet
dstToken: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" // USDC on Ethereum
// Note: No userAddress - this is preview mode
};
// The API might fail, but we should handle it gracefully
try {
const result = await quoteSwapTool.handler(params);
// Verify the result structure
expect(result).toBeDefined();
expect(result.summary).toBeDefined();
expect(result.summary.srcChainId).toBe("42161");
expect(result.summary.dstChainId).toBe("1");
// Verify tokens info exists
expect(result.tokens).toBeDefined();
expect(result.tokens.srcToken).toBeDefined();
expect(result.tokens.dstToken).toBeDefined();
// Verify transaction preview exists (might be null if API failed)
expect(result.txPreview).toBeDefined();
// Verify estimation exists
expect(result.estimation).toBeDefined();
// Verify raw data exists
expect(result.raw).toBeDefined();
console.log("\n✅ quoteSwap PREVIEW MODE SUCCESS:");
console.log(`From: Chain ${result.summary.srcChainId} (${result.tokens.srcToken.symbol || 'Unknown'})`);
console.log(`To: Chain ${result.summary.dstChainId} (${result.tokens.dstToken.symbol || 'Unknown'})`);
if (result.estimation) {
console.log(`\nEstimation:`);
console.log(` Input: ${result.estimation.srcChainTokenIn?.amount} (${result.estimation.srcChainTokenIn?.symbol})`);
console.log(` Output: ${result.estimation.dstChainTokenOut?.amount} (${result.estimation.dstChainTokenOut?.symbol})`);
console.log(` Fees: ${result.estimation.srcChainTokenIn?.approximateOperatingExpense}`);
console.log(` USD Value: $${result.estimation.dstChainTokenOut?.approximateUsdValue}`);
}
console.log("\n API RESPONSE:");
console.log(JSON.stringify(result.raw, null, 2));
} catch (error) {
// If API fails, that's okay for testing
console.log("API error (expected in some cases):", error);
expect(error).toBeInstanceOf(Error);
}
}, 30000);
});
describe("quoteSwap - Full Mode", () => {
test("should return complete order with transaction data", async () => {
const fullModeParams = {
srcChainId: "56",
srcToken: "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
amount: "100000000000000000000",
dstChainId: "43114",
dstToken: "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
senderAddress: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
dstChainTokenOutRecipient: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
affiliateFeePercent: 0.1,
affiliateFeeRecipient: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
};
try {
const result = await quoteSwapTool.handler(fullModeParams);
expect(result).toBeDefined();
expect(result.summary).toBeDefined();
expect(result.tokens).toBeDefined();
expect(result.estimation).toBeDefined();
console.log("\n✅ quoteSwap FULL MODE SUCCESS:");
console.log(`From: Chain ${result.summary.srcChainId} (${result.tokens.srcToken.symbol || 'Unknown'})`);
console.log(`To: Chain ${result.summary.dstChainId} (${result.tokens.dstToken.symbol || 'Unknown'})`);
if (result.estimation) {
console.log(`\nEstimation:`);
console.log(` Input: ${result.estimation.srcChainTokenIn?.amount} (${result.estimation.srcChainTokenIn?.symbol})`);
console.log(` Output: ${result.estimation.dstChainTokenOut?.amount} (${result.estimation.dstChainTokenOut?.symbol})`);
console.log(` USD Input: $${result.estimation.srcChainTokenIn?.approximateUsdValue}`);
console.log(` USD Output: $${result.estimation.dstChainTokenOut?.approximateUsdValue}`);
if (result.estimation.costsDetails) {
console.log(`\n Fee Breakdown:`);
result.estimation.costsDetails.forEach((cost: any) => {
console.log(` - ${cost.type}: ${cost.payload?.feeAmount || cost.amountIn} ${cost.payload?.feeBps ? `(${cost.payload.feeBps} bps)` : ''}`);
});
}
}
console.log(`\nTransaction Data:`);
console.log(` to: ${result.txPreview.to || 'null'}`);
console.log(` value: ${result.txPreview.value || 'null'}`);
console.log(` data: ${result.txPreview.data ? result.txPreview.data.substring(0, 66) + '...' : 'null'}`);
if (result.raw?.orderId) {
console.log(`\nOrder ID: ${result.raw.orderId}`);
}
if (result.raw?.fixFee) {
console.log(`Fix Fee: ${result.raw.fixFee} wei`);
}
console.log("\n📦 RAW API RESPONSE:");
console.log(JSON.stringify(result.raw, null, 2));
// En full mode debe tener tx data
expect(result.txPreview.to).toBeTruthy();
expect(result.txPreview.data).toBeTruthy();
} catch (error) {
console.error("Full mode error:", error);
expect(error).toBeInstanceOf(Error);
}
}, 60000); // Aumentado timeout para full mode
});
describe("quoteSwap - Error Handling", () => {
test("should reject invalid parameters", async () => {
const invalidParams = {
srcChainId: "999999", // Invalid chain ID
srcToken: "0x0000000000000000000000000000000000000000",
amount: "0",
dstChainId: "999999",
dstToken: "0x0000000000000000000000000000000000000000"
};
// Should throw an error
try {
const result = await quoteSwapTool.handler(invalidParams);
console.log("Invalid params result:", JSON.stringify(result, null, 2));
} catch (error) {
expect(error).toBeInstanceOf(Error);
console.log("Expected error:", error);
}
}, 30000);
test("should validate same source and destination chain", async () => {
const sameChainParams = {
srcChainId: "42161", // Arbitrum
srcToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
amount: "1000000",
dstChainId: "42161", // Same as source!
dstToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831"
};
try {
const result = await quoteSwapTool.handler(sameChainParams);
console.log("Same chain result:", result);
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error instanceof Error && error.message).toContain("different");
console.log("✓ Correctly rejected same chain:", error);
}
}, 30000);
});