88 lines
2.8 KiB
TypeScript
88 lines
2.8 KiB
TypeScript
import { i18n } from '@/plugins/i18n'
|
||
|
||
/**
|
||
* 请求基础 URL,默认 https://api.xtrader.vip,可通过环境变量 VITE_API_BASE_URL 覆盖
|
||
*/
|
||
const BASE_URL =
|
||
typeof import.meta !== 'undefined' &&
|
||
(import.meta as unknown as { env?: Record<string, string> }).env?.VITE_API_BASE_URL
|
||
? (import.meta as unknown as { env: Record<string, string> }).env.VITE_API_BASE_URL
|
||
: 'https://api.xtrader.vip'
|
||
|
||
/** CLOB WebSocket URL,与 REST API 同源 */
|
||
export function getClobWsUrl(): string {
|
||
const base = BASE_URL || (typeof window !== 'undefined' ? window.location.origin : 'https://api.xtrader.vip')
|
||
const url = new URL(base)
|
||
const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
||
return `${protocol}//${url.host}/clob/ws`
|
||
}
|
||
|
||
/** User WebSocket URL(订单/持仓/余额推送),与 REST API 同源 */
|
||
export function getUserWsUrl(): string {
|
||
const base = BASE_URL || (typeof window !== 'undefined' ? window.location.origin : 'https://api.xtrader.vip')
|
||
const url = new URL(base)
|
||
const protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'
|
||
return `${protocol}//${url.host}/clob/ws/user`
|
||
}
|
||
|
||
export interface RequestConfig {
|
||
/** 请求头,如 { 'x-token': token, 'x-user-id': userId } */
|
||
headers?: Record<string, string>
|
||
}
|
||
|
||
/**
|
||
* 带 x-token 等自定义头的 GET 请求
|
||
*/
|
||
export async function get<T = unknown>(
|
||
path: string,
|
||
params?: Record<string, string | number | string[] | undefined>,
|
||
config?: RequestConfig,
|
||
): Promise<T> {
|
||
const url = new URL(path, BASE_URL || window.location.origin)
|
||
if (params) {
|
||
Object.entries(params).forEach(([key, value]) => {
|
||
if (value === undefined) return
|
||
if (Array.isArray(value)) {
|
||
value.forEach((v) => url.searchParams.append(key, String(v)))
|
||
} else {
|
||
url.searchParams.set(key, String(value))
|
||
}
|
||
})
|
||
}
|
||
const headers: Record<string, string> = {
|
||
'Content-Type': 'application/json',
|
||
'Accept-Language': i18n.global.locale.value as string,
|
||
...config?.headers,
|
||
}
|
||
const res = await fetch(url.toString(), { method: 'GET', headers })
|
||
if (!res.ok) {
|
||
throw new Error(`HTTP ${res.status}: ${res.statusText}`)
|
||
}
|
||
return res.json() as Promise<T>
|
||
}
|
||
|
||
/**
|
||
* 带 x-token 等自定义头的 POST 请求
|
||
*/
|
||
export async function post<T = unknown>(
|
||
path: string,
|
||
body?: unknown,
|
||
config?: RequestConfig,
|
||
): Promise<T> {
|
||
const url = new URL(path, BASE_URL || window.location.origin)
|
||
const headers: Record<string, string> = {
|
||
'Content-Type': 'application/json',
|
||
'Accept-Language': i18n.global.locale.value as string,
|
||
...config?.headers,
|
||
}
|
||
const res = await fetch(url.toString(), {
|
||
method: 'POST',
|
||
headers,
|
||
body: body !== undefined ? JSON.stringify(body) : undefined,
|
||
})
|
||
if (!res.ok) {
|
||
throw new Error(`HTTP ${res.status}: ${res.statusText}`)
|
||
}
|
||
return res.json() as Promise<T>
|
||
}
|