/** * Pacifica数据接口客户端 * * 负责处理Pacifica DEX的所有数据查询接口 * 包括价格、订单簿、K线、交易历史等 */ import { UniversalHttpClient } from '@/utils/universalHttpClient' import { HttpClientRequest, HttpClientResponse } from '@/types/httpClient' import { PacificaPriceData, PacificaTicker, PacificaOrderBook, PacificaKline, PacificaTrade, PacificaAggTrade, PacificaSymbol, PacificaMarketDataParams, PacificaApiResponse, PacificaListResponse, } from '@/types/pacifica' export class PacificaDataClient { private httpClient: UniversalHttpClient private accountId: string constructor(httpClient: UniversalHttpClient, accountId: string) { this.httpClient = httpClient this.accountId = accountId } // ======================== 市场数据接口 ======================== /** * 获取交易对信息 */ async getExchangeInfo(): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: '/api/v3/exchangeInfo', headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{ symbols: PacificaSymbol[] }>(request) return this.wrapResponse(response) } /** * 获取单个交易对最新价格 */ async getPrice(symbol: string): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/ticker/price?symbol=${symbol}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取所有交易对价格 */ async getAllPrices(): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: '/api/v3/ticker/price', headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取24hr价格变动统计 */ async getTicker24hr(symbol?: string): Promise> { const url = symbol ? `/api/v3/ticker/24hr?symbol=${symbol}` : '/api/v3/ticker/24hr' const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取订单簿深度 */ async getOrderBook(symbol: string, limit: number = 100): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/depth?symbol=${symbol}&limit=${limit}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取最近成交记录 */ async getRecentTrades(symbol: string, limit: number = 500): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/trades?symbol=${symbol}&limit=${limit}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取历史成交记录 */ async getHistoricalTrades( symbol: string, params: PacificaMarketDataParams = {}, ): Promise> { const queryParams = new URLSearchParams() queryParams.append('symbol', symbol) if (params.limit) queryParams.append('limit', params.limit.toString()) if (params.fromId) queryParams.append('fromId', params.fromId.toString()) const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/historicalTrades?${queryParams.toString()}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取聚合交易记录 */ async getAggTrades( symbol: string, params: PacificaMarketDataParams = {}, ): Promise> { const queryParams = new URLSearchParams() queryParams.append('symbol', symbol) if (params.limit) queryParams.append('limit', params.limit.toString()) if (params.fromId) queryParams.append('fromId', params.fromId.toString()) if (params.startTime) queryParams.append('startTime', params.startTime.toString()) if (params.endTime) queryParams.append('endTime', params.endTime.toString()) const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/aggTrades?${queryParams.toString()}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 获取K线数据 */ async getKlines( symbol: string, interval: string, params: PacificaMarketDataParams = {}, ): Promise> { const queryParams = new URLSearchParams() queryParams.append('symbol', symbol) queryParams.append('interval', interval) if (params.limit) queryParams.append('limit', params.limit.toString()) if (params.startTime) queryParams.append('startTime', params.startTime.toString()) if (params.endTime) queryParams.append('endTime', params.endTime.toString()) const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/klines?${queryParams.toString()}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) // 转换原始K线数据为结构化对象 const klines: PacificaKline[] = response.data.map((kline: any[]) => ({ symbol, openTime: kline[0], open: kline[1], high: kline[2], low: kline[3], close: kline[4], volume: kline[5], closeTime: kline[6], quoteVolume: kline[7], trades: kline[8], takerBuyBaseVolume: kline[9], takerBuyQuoteVolume: kline[10], interval, firstTradeId: 0, lastTradeId: 0, })) return this.wrapResponse({ ...response, data: klines, }) } /** * 获取平均价格 */ async getAvgPrice(symbol: string): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/avgPrice?symbol=${symbol}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{ mins: number; price: string }>(request) return this.wrapResponse(response) } /** * 获取服务器时间 */ async getServerTime(): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: '/api/v3/time', headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{ serverTime: number }>(request) return this.wrapResponse(response) } /** * 测试连接 */ async ping(): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: '/api/v3/ping', headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{}>(request) return this.wrapResponse(response) } // ======================== 批量查询接口 ======================== /** * 批量获取多个交易对价格 */ async getBatchPrices(symbols: string[]): Promise> { const symbolsParam = JSON.stringify(symbols) const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/ticker/price?symbols=${encodeURIComponent(symbolsParam)}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } /** * 批量获取多个交易对24hr统计 */ async getBatch24hrTickers(symbols: string[]): Promise> { const symbolsParam = JSON.stringify(symbols) const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'GET', url: `/api/v3/ticker/24hr?symbols=${encodeURIComponent(symbolsParam)}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request(request) return this.wrapResponse(response) } // ======================== 实时数据流接口 ======================== /** * 获取WebSocket连接的监听密钥 */ async getListenKey(): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'POST', url: '/api/v3/userDataStream', headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{ listenKey: string }>(request) return this.wrapResponse(response) } /** * 延长监听密钥有效期 */ async keepAliveListenKey(listenKey: string): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'PUT', url: `/api/v3/userDataStream?listenKey=${listenKey}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{}>(request) return this.wrapResponse(response) } /** * 关闭监听密钥 */ async closeListenKey(listenKey: string): Promise> { const request: HttpClientRequest = { platform: 'pacifica', accountId: this.accountId, method: 'DELETE', url: `/api/v3/userDataStream?listenKey=${listenKey}`, headers: { 'Content-Type': 'application/json', }, } const response = await this.httpClient.request<{}>(request) return this.wrapResponse(response) } // ======================== 辅助方法 ======================== /** * 包装响应数据为统一格式 */ private wrapResponse(response: HttpClientResponse): PacificaApiResponse { return { data: response.data, success: response.status >= 200 && response.status < 300, code: response.status, message: response.statusText, timestamp: Date.now(), } } /** * 构建查询参数字符串 */ private buildQueryString(params: Record): string { const queryParams = new URLSearchParams() Object.entries(params).forEach(([key, value]) => { if (value !== undefined && value !== null) { queryParams.append(key, value.toString()) } }) return queryParams.toString() } /** * 格式化符号参数 */ private formatSymbol(symbol: string): string { return symbol.toUpperCase() } /** * 验证时间间隔参数 */ private validateInterval(interval: string): boolean { const validIntervals = ['1m', '3m', '5m', '15m', '30m', '1h', '2h', '4h', '6h', '8h', '12h', '1d', '3d', '1w', '1M'] return validIntervals.includes(interval) } /** * 获取客户端配置 */ getClientConfig() { return { accountId: this.accountId, platform: 'pacifica', endpoints: { exchangeInfo: '/api/v3/exchangeInfo', price: '/api/v3/ticker/price', ticker24hr: '/api/v3/ticker/24hr', orderBook: '/api/v3/depth', trades: '/api/v3/trades', klines: '/api/v3/klines', ping: '/api/v3/ping', time: '/api/v3/time', }, } } }