import { FutureConnector } from '../../src/exchanges/binance/FutureConnector' import { DerivativesTradingUsdsFuturesRestAPI } from '@binance/derivatives-trading-usds-futures' const describeBinanceIntegration = process.env.TEST_BINANCE === '1' ? describe : describe.skip // 集成测试 - 需要真实的 API 密钥 // 这些测试会调用真实的 Binance API,请确保有有效的 API 密钥 describeBinanceIntegration('FutureConnector Integration Tests', () => { let connector: FutureConnector beforeAll(() => { // 检查环境变量 if (!process.env.API_KEY || !process.env.API_SECRET) { console.warn('⚠️ 跳过集成测试:API_KEY 或 API_SECRET 未设置') return } connector = new FutureConnector(process.env.API_KEY, process.env.API_SECRET) }) // 跳过测试如果没有 API 密钥 const testIfApiKey = process.env.API_KEY && process.env.API_SECRET ? test : test.skip describe('Account Information', () => { testIfApiKey( 'should get account assets info', async () => { const assets = await connector.getAssetsInfo() expect(Array.isArray(assets)).toBe(true) assets.forEach(asset => { expect(asset).toHaveProperty('symbol') expect(asset).toHaveProperty('walletBalance') expect(Number(asset.walletBalance)).toBeGreaterThan(0) }) }, 10000, ) testIfApiKey( 'should get position info', async () => { const positions = await connector.getPositonInfo() expect(Array.isArray(positions)).toBe(true) positions.forEach(position => { expect(position).toHaveProperty('symbol') expect(position).toHaveProperty('positionAmt') expect(Number(position.positionAmt)).toBeGreaterThan(0) }) }, 10000, ) testIfApiKey( 'should get all positions', async () => { const positions = await connector.getAllPositions() expect(Array.isArray(positions)).toBe(true) positions.forEach(position => { expect(position).toHaveProperty('symbol') expect(position).toHaveProperty('positionAmt') expect(position).toHaveProperty('unrealizedPnl') }) }, 10000, ) testIfApiKey( 'should get position by symbol', async () => { const position = await connector.getPositionBalanceBySymbol('BTCUSDT') if (position) { expect(position).toHaveProperty('symbol', 'BTCUSDT') expect(position).toHaveProperty('positionAmt') expect(position).toHaveProperty('unrealizedPnl') } else { // 如果没有持仓,应该返回 null expect(position).toBeNull() } }, 10000, ) }) describe('Order Management', () => { testIfApiKey( 'should get current open orders', async () => { await expect(connector.getCurrentAllOpenPosition()).resolves.not.toThrow() }, 10000, ) testIfApiKey( 'should get order history', async () => { const orders = await connector.getOrderHistory('BTCUSDT', undefined, undefined, 10) expect(Array.isArray(orders)).toBe(true) if (orders.length > 0) { orders.forEach(order => { expect(order).toHaveProperty('symbol', 'BTCUSDT') expect(order).toHaveProperty('orderId') expect(order).toHaveProperty('status') }) } }, 10000, ) testIfApiKey( 'should get trade history', async () => { const trades = await connector.getTradeHistory('BTCUSDT', undefined, undefined, 10) expect(Array.isArray(trades)).toBe(true) if (trades.length > 0) { trades.forEach(trade => { expect(trade).toHaveProperty('symbol', 'BTCUSDT') expect(trade).toHaveProperty('id') expect(trade).toHaveProperty('price') expect(trade).toHaveProperty('qty') }) } }, 10000, ) }) describe('Trading Operations', () => { // 注意:这些测试会创建真实的订单,请谨慎使用 // 建议在测试环境中使用小额订单 testIfApiKey.skip( 'should place and cancel limit order', async () => { // 创建限价单 const orderResult = await connector.openLimitOrder( 'BTCUSDT', 'long', 0.001, // 最小数量 40000, // 远低于市价的价格,确保不会成交 'GTC', ) expect(orderResult).toBeDefined() expect(orderResult).toHaveProperty('orderId') expect(orderResult).toHaveProperty('status') // 撤销订单 if (orderResult && orderResult.orderId) { const cancelResult = await connector.cancelOrder('BTCUSDT', orderResult.orderId) expect(cancelResult).toBeDefined() } }, 30000, ) testIfApiKey.skip( 'should place market order', async () => { // 市价单会立即成交,请谨慎使用 const orderResult = await connector.openMarketOrder( 'BTCUSDT', 'long', 0.001, // 最小数量 ) expect(orderResult).toBeDefined() expect(orderResult).toHaveProperty('orderId') expect(orderResult).toHaveProperty('status') }, 30000, ) testIfApiKey.skip( 'should place stop order', async () => { // 止损单,设置远低于市价的价格 const orderResult = await connector.openStopOrder( 'BTCUSDT', 'long', 0.001, 30000, // 远低于市价的止损价格 'STOP_MARKET', ) expect(orderResult).toBeDefined() expect(orderResult).toHaveProperty('orderId') expect(orderResult).toHaveProperty('status') // 撤销订单 if (orderResult && orderResult.orderId) { const cancelResult = await connector.cancelOrder('BTCUSDT', orderResult.orderId) expect(cancelResult).toBeDefined() } }, 30000, ) }) describe('Account Settings', () => { testIfApiKey.skip( 'should set leverage', async () => { const result = await connector.setLeverage('BTCUSDT', 10) expect(result).toBeDefined() expect(result).toHaveProperty('leverage') expect(result).toHaveProperty('maxNotionalValue') }, 10000, ) testIfApiKey.skip( 'should set margin type', async () => { const result = await connector.setMarginType( 'BTCUSDT', DerivativesTradingUsdsFuturesRestAPI.ChangeMarginTypeMarginTypeEnum.ISOLATED, ) expect(result).toBeDefined() expect(result).toHaveProperty('code') }, 10000, ) }) describe('Error Handling', () => { testIfApiKey( 'should handle invalid symbol gracefully', async () => { const position = await connector.getPositionBalanceBySymbol('INVALID_SYMBOL') expect(position).toBeNull() }, 10000, ) testIfApiKey( 'should handle invalid order parameters', async () => { // 测试无效的订单参数 const result = await connector.openPosition( 'INVALID_SYMBOL', DerivativesTradingUsdsFuturesRestAPI.NewOrderSideEnum.BUY, 0, 0, ) // 应该返回 null 或抛出错误 expect(result).toBeNull() }, 10000, ) }) })