Initial commit: add .gitignore and README
This commit is contained in:
87
tests/unit/adapters/aaveV3.test.ts
Normal file
87
tests/unit/adapters/aaveV3.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { AaveV3Adapter } from "../../../src/adapters/aaveV3.js";
|
||||
|
||||
describe("Aave V3 Adapter", () => {
|
||||
let adapter: AaveV3Adapter;
|
||||
let mockProvider: any;
|
||||
let mockSigner: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
mockSigner = {
|
||||
getAddress: vi.fn().mockResolvedValue("0x1234567890123456789012345678901234567890"),
|
||||
};
|
||||
|
||||
// Mock the adapter constructor
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
supply: vi.fn(),
|
||||
withdraw: vi.fn(),
|
||||
borrow: vi.fn(),
|
||||
repay: vi.fn(),
|
||||
flashLoanSimple: vi.fn(),
|
||||
setUserEMode: vi.fn(),
|
||||
setUserUseReserveAsCollateral: vi.fn(),
|
||||
getUserAccountData: vi.fn(),
|
||||
interface: {
|
||||
parseLog: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should validate asset address on supply", async () => {
|
||||
adapter = new AaveV3Adapter("mainnet", mockSigner as any);
|
||||
|
||||
await expect(
|
||||
adapter.supply("0x0000000000000000000000000000000000000000", 1000n)
|
||||
).rejects.toThrow("Invalid asset address");
|
||||
});
|
||||
|
||||
it("should validate asset address on withdraw", async () => {
|
||||
adapter = new AaveV3Adapter("mainnet", mockSigner as any);
|
||||
|
||||
await expect(
|
||||
adapter.withdraw("0x0000000000000000000000000000000000000000", 1000n)
|
||||
).rejects.toThrow("Invalid asset address");
|
||||
});
|
||||
|
||||
it("should calculate health factor correctly", async () => {
|
||||
adapter = new AaveV3Adapter("mainnet");
|
||||
|
||||
const mockData = {
|
||||
totalCollateralBase: 2000000n,
|
||||
totalDebtBase: 1000000n,
|
||||
availableBorrowsBase: 500000n,
|
||||
currentLiquidationThreshold: 8000n, // 80%
|
||||
ltv: 7500n, // 75%
|
||||
healthFactor: 2000000000000000000n, // 2.0
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
adapter.dataProvider.getUserAccountData = vi.fn().mockResolvedValue([
|
||||
mockData.totalCollateralBase,
|
||||
mockData.totalDebtBase,
|
||||
mockData.availableBorrowsBase,
|
||||
mockData.currentLiquidationThreshold,
|
||||
mockData.ltv,
|
||||
mockData.healthFactor,
|
||||
]);
|
||||
|
||||
const hf = await adapter.getUserHealthFactor("0x123");
|
||||
expect(hf).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("should handle different interest rate modes", async () => {
|
||||
adapter = new AaveV3Adapter("mainnet", mockSigner as any);
|
||||
|
||||
// Test variable rate mode (default)
|
||||
// Test stable rate mode
|
||||
// These would require mocking the contract calls
|
||||
expect(true).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
79
tests/unit/adapters/aggregators.test.ts
Normal file
79
tests/unit/adapters/aggregators.test.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { AggregatorAdapter } from "../../../src/adapters/aggregators.js";
|
||||
|
||||
describe("Aggregator Adapter", () => {
|
||||
let adapter: AggregatorAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
swap: vi.fn(),
|
||||
transformERC20: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
// Mock fetch
|
||||
global.fetch = vi.fn();
|
||||
});
|
||||
|
||||
it("should get 1inch quote", async () => {
|
||||
adapter = new AggregatorAdapter("mainnet");
|
||||
|
||||
// Mock 1inch API response
|
||||
(global.fetch as any).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
toAmount: "1000000",
|
||||
}),
|
||||
});
|
||||
|
||||
(global.fetch as any).mockResolvedValueOnce({
|
||||
ok: true,
|
||||
json: async () => ({
|
||||
tx: {
|
||||
data: "0x1234",
|
||||
to: "0x1111111254EEB25477B68fb85Ed929f73A960582",
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
const quote = await adapter.get1InchQuote(
|
||||
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
1000000n,
|
||||
50
|
||||
);
|
||||
|
||||
expect(quote).toBeDefined();
|
||||
expect(quote?.amountOut).toBeGreaterThan(0n);
|
||||
expect(quote?.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should fallback when 1inch API fails", async () => {
|
||||
adapter = new AggregatorAdapter("mainnet");
|
||||
|
||||
// Mock API failure
|
||||
(global.fetch as any).mockResolvedValueOnce({
|
||||
ok: false,
|
||||
});
|
||||
|
||||
const quote = await adapter.get1InchQuote(
|
||||
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
1000000n,
|
||||
50
|
||||
);
|
||||
|
||||
// Should return fallback quote
|
||||
expect(quote).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
74
tests/unit/adapters/balancer.test.ts
Normal file
74
tests/unit/adapters/balancer.test.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { BalancerAdapter } from "../../../src/adapters/balancer.js";
|
||||
|
||||
describe("Balancer Adapter", () => {
|
||||
let adapter: BalancerAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
swap: vi.fn(),
|
||||
batchSwap: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should encode single swap", async () => {
|
||||
adapter = new BalancerAdapter("mainnet");
|
||||
|
||||
const swapParams = {
|
||||
poolId: "0x...",
|
||||
kind: 0, // GIVEN_IN
|
||||
assetIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
assetOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
amount: 1000000n,
|
||||
userData: "0x",
|
||||
};
|
||||
|
||||
const data = await adapter.swap(swapParams);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode batch swap", async () => {
|
||||
adapter = new BalancerAdapter("mainnet");
|
||||
|
||||
const batchSwapParams = {
|
||||
kind: 0,
|
||||
swaps: [{
|
||||
poolId: "0x...",
|
||||
assetInIndex: 0,
|
||||
assetOutIndex: 1,
|
||||
amount: 1000000n,
|
||||
userData: "0x",
|
||||
}],
|
||||
assets: [
|
||||
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
],
|
||||
funds: {
|
||||
sender: "0x123",
|
||||
fromInternalBalance: false,
|
||||
recipient: "0x123",
|
||||
toInternalBalance: false,
|
||||
},
|
||||
limits: [0n, 0n],
|
||||
deadline: Math.floor(Date.now() / 1000) + 60 * 20,
|
||||
};
|
||||
|
||||
const data = await adapter.batchSwap(batchSwapParams);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
70
tests/unit/adapters/compoundV3.test.ts
Normal file
70
tests/unit/adapters/compoundV3.test.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { CompoundV3Adapter } from "../../../src/adapters/compoundV3.js";
|
||||
|
||||
describe("Compound V3 Adapter", () => {
|
||||
let adapter: CompoundV3Adapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
supply: vi.fn(),
|
||||
withdraw: vi.fn(),
|
||||
borrow: vi.fn(),
|
||||
repay: vi.fn(),
|
||||
allow: vi.fn(),
|
||||
getAccountLiquidity: vi.fn(),
|
||||
interface: {
|
||||
parseLog: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should supply assets", async () => {
|
||||
adapter = new CompoundV3Adapter("mainnet");
|
||||
// Test would verify supply call encoding
|
||||
expect(adapter).toBeDefined();
|
||||
});
|
||||
|
||||
it("should withdraw assets", async () => {
|
||||
adapter = new CompoundV3Adapter("mainnet");
|
||||
// Test would verify withdraw call encoding
|
||||
expect(adapter).toBeDefined();
|
||||
});
|
||||
|
||||
it("should borrow assets", async () => {
|
||||
adapter = new CompoundV3Adapter("mainnet");
|
||||
// Test would verify borrow call encoding
|
||||
expect(adapter).toBeDefined();
|
||||
});
|
||||
|
||||
it("should repay assets", async () => {
|
||||
adapter = new CompoundV3Adapter("mainnet");
|
||||
// Test would verify repay call encoding
|
||||
expect(adapter).toBeDefined();
|
||||
});
|
||||
|
||||
it("should calculate account liquidity", async () => {
|
||||
adapter = new CompoundV3Adapter("mainnet");
|
||||
|
||||
const mockLiquidity = {
|
||||
isLiquid: true,
|
||||
shortfall: 0n,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
adapter.comet.getAccountLiquidity = vi.fn().mockResolvedValue([
|
||||
true,
|
||||
0n,
|
||||
]);
|
||||
|
||||
const liquidity = await adapter.getAccountLiquidity("0x123");
|
||||
expect(liquidity).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
69
tests/unit/adapters/curve.test.ts
Normal file
69
tests/unit/adapters/curve.test.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { CurveAdapter } from "../../../src/adapters/curve.js";
|
||||
|
||||
describe("Curve Adapter", () => {
|
||||
let adapter: CurveAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
exchange: vi.fn(),
|
||||
exchange_underlying: vi.fn(),
|
||||
get_pool_from_lp_token: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should find pool for LP token", async () => {
|
||||
adapter = new CurveAdapter("mainnet");
|
||||
|
||||
// Mock registry response
|
||||
mockProvider.call = vi.fn().mockResolvedValue(
|
||||
"0x000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c7"
|
||||
);
|
||||
|
||||
const pool = await adapter.findPool("0x6c3F90f043a72FA612cbac8115EE7e52BDe6E490");
|
||||
expect(pool).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode exchange", async () => {
|
||||
adapter = new CurveAdapter("mainnet");
|
||||
|
||||
const data = await adapter.exchange(
|
||||
"0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
|
||||
0,
|
||||
1,
|
||||
1000000n,
|
||||
990000n
|
||||
);
|
||||
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode exchange_underlying", async () => {
|
||||
adapter = new CurveAdapter("mainnet");
|
||||
|
||||
const data = await adapter.exchangeUnderlying(
|
||||
"0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7",
|
||||
0,
|
||||
1,
|
||||
1000000n,
|
||||
990000n
|
||||
);
|
||||
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
42
tests/unit/adapters/lido.test.ts
Normal file
42
tests/unit/adapters/lido.test.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { LidoAdapter } from "../../../src/adapters/lido.js";
|
||||
|
||||
describe("Lido Adapter", () => {
|
||||
let adapter: LidoAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
wrap: vi.fn(),
|
||||
unwrap: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should encode wrap operation", async () => {
|
||||
adapter = new LidoAdapter("mainnet");
|
||||
|
||||
const data = await adapter.wrap(1000000000000000000n);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode unwrap operation", async () => {
|
||||
adapter = new LidoAdapter("mainnet");
|
||||
|
||||
const data = await adapter.unwrap(1000000000000000000n);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
77
tests/unit/adapters/maker.test.ts
Normal file
77
tests/unit/adapters/maker.test.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { MakerAdapter } from "../../../src/adapters/maker.js";
|
||||
|
||||
describe("MakerDAO Adapter", () => {
|
||||
let adapter: MakerAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
open: vi.fn(),
|
||||
frob: vi.fn(),
|
||||
join: vi.fn(),
|
||||
exit: vi.fn(),
|
||||
interface: {
|
||||
parseLog: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should open vault and parse CDP ID", async () => {
|
||||
adapter = new MakerAdapter("mainnet");
|
||||
|
||||
// Mock transaction with NewCdp event
|
||||
const mockReceipt = {
|
||||
logs: [{
|
||||
topics: ["0x...", "0x0000000000000000000000000000000000000000000000000000000000000123"],
|
||||
data: "0x",
|
||||
}],
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
adapter.cdpManager.open = vi.fn().mockResolvedValue({
|
||||
wait: vi.fn().mockResolvedValue(mockReceipt),
|
||||
});
|
||||
|
||||
// @ts-ignore
|
||||
adapter.cdpManager.interface.parseLog = vi.fn().mockReturnValue({
|
||||
name: "NewCdp",
|
||||
args: {
|
||||
usr: "0x123",
|
||||
own: "0x456",
|
||||
cdp: 291n, // CDP ID
|
||||
},
|
||||
});
|
||||
|
||||
const cdpId = await adapter.openVault("ETH-A");
|
||||
expect(cdpId).toBe(291n);
|
||||
});
|
||||
|
||||
it("should encode frob operation", async () => {
|
||||
adapter = new MakerAdapter("mainnet");
|
||||
|
||||
const data = await adapter.frob(291n, 1000000000000000000n, 1000n);
|
||||
expect(data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode join operation", async () => {
|
||||
adapter = new MakerAdapter("mainnet");
|
||||
|
||||
const data = await adapter.join(1000000n);
|
||||
expect(data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode exit operation", async () => {
|
||||
adapter = new MakerAdapter("mainnet");
|
||||
|
||||
const data = await adapter.exit(1000000n);
|
||||
expect(data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
62
tests/unit/adapters/perps.test.ts
Normal file
62
tests/unit/adapters/perps.test.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { PerpsAdapter } from "../../../src/adapters/perps.js";
|
||||
|
||||
describe("Perps Adapter", () => {
|
||||
let adapter: PerpsAdapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
increasePosition: vi.fn(),
|
||||
decreasePosition: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should encode increase position", async () => {
|
||||
adapter = new PerpsAdapter("mainnet");
|
||||
|
||||
const params = {
|
||||
path: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
|
||||
indexToken: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
amountIn: 1000000n,
|
||||
minOut: 990000n,
|
||||
sizeDelta: 2000000n,
|
||||
isLong: true,
|
||||
acceptablePrice: 1000000n,
|
||||
};
|
||||
|
||||
const data = await adapter.increasePosition(params);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode decrease position", async () => {
|
||||
adapter = new PerpsAdapter("mainnet");
|
||||
|
||||
const params = {
|
||||
path: ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
|
||||
indexToken: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
collateralDelta: 500000n,
|
||||
sizeDelta: 1000000n,
|
||||
isLong: true,
|
||||
receiver: "0x123",
|
||||
acceptablePrice: 1000000n,
|
||||
};
|
||||
|
||||
const data = await adapter.decreasePosition(params);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
104
tests/unit/adapters/uniswapV3.test.ts
Normal file
104
tests/unit/adapters/uniswapV3.test.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { UniswapV3Adapter } from "../../../src/adapters/uniswapV3.js";
|
||||
|
||||
describe("Uniswap V3 Adapter", () => {
|
||||
let adapter: UniswapV3Adapter;
|
||||
let mockProvider: any;
|
||||
|
||||
beforeEach(() => {
|
||||
mockProvider = {
|
||||
getNetwork: vi.fn().mockResolvedValue({ chainId: 1n }),
|
||||
call: vi.fn(),
|
||||
};
|
||||
|
||||
vi.spyOn(require("ethers"), "JsonRpcProvider").mockImplementation(() => mockProvider);
|
||||
vi.spyOn(require("ethers"), "Contract").mockImplementation(() => ({
|
||||
exactInputSingle: vi.fn(),
|
||||
exactOutputSingle: vi.fn(),
|
||||
quoteExactInputSingle: vi.fn(),
|
||||
interface: {
|
||||
encodeFunctionData: vi.fn(),
|
||||
},
|
||||
}));
|
||||
});
|
||||
|
||||
it("should encode exact input swap", async () => {
|
||||
adapter = new UniswapV3Adapter("mainnet");
|
||||
|
||||
const params = {
|
||||
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
tokenOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
fee: 3000,
|
||||
amountIn: 1000000n,
|
||||
amountOutMinimum: 990000n,
|
||||
recipient: "0x123",
|
||||
deadline: Math.floor(Date.now() / 1000) + 60 * 20,
|
||||
};
|
||||
|
||||
const data = await adapter.swapExactInput(params);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode exact output swap", async () => {
|
||||
adapter = new UniswapV3Adapter("mainnet");
|
||||
|
||||
const params = {
|
||||
tokenIn: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
tokenOut: "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
fee: 3000,
|
||||
amountOut: 1000000n,
|
||||
amountInMaximum: 1010000n,
|
||||
recipient: "0x123",
|
||||
deadline: Math.floor(Date.now() / 1000) + 60 * 20,
|
||||
};
|
||||
|
||||
const data = await adapter.swapExactOutput(params);
|
||||
expect(data).toBeDefined();
|
||||
expect(data.to).toBeDefined();
|
||||
expect(data.data).toBeDefined();
|
||||
});
|
||||
|
||||
it("should encode path correctly", () => {
|
||||
adapter = new UniswapV3Adapter("mainnet");
|
||||
|
||||
const path = adapter.encodePath(
|
||||
["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "0xdAC17F958D2ee523a2206206994597C13D831ec7"],
|
||||
[3000]
|
||||
);
|
||||
|
||||
expect(path).toBeDefined();
|
||||
expect(path.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it("should get quote for exact input", async () => {
|
||||
adapter = new UniswapV3Adapter("mainnet");
|
||||
|
||||
// Mock quoter response
|
||||
mockProvider.call = vi.fn().mockResolvedValue(
|
||||
"0x00000000000000000000000000000000000000000000000000000000000f4240" // 1000000
|
||||
);
|
||||
|
||||
const quote = await adapter.quoteExactInput(
|
||||
"0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
3000,
|
||||
1000000n
|
||||
);
|
||||
|
||||
expect(quote).toBeGreaterThan(0n);
|
||||
});
|
||||
|
||||
it("should validate fee tiers", () => {
|
||||
adapter = new UniswapV3Adapter("mainnet");
|
||||
|
||||
const validFees = [100, 500, 3000, 10000];
|
||||
validFees.forEach(fee => {
|
||||
expect(adapter.isValidFee(fee)).toBe(true);
|
||||
});
|
||||
|
||||
expect(adapter.isValidFee(999)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user