feat: 实现跟单订单跟踪和统计功能

- 添加订单跟踪实体和Repository(CopyOrderTracking, SellMatchRecord, SellMatchDetail)
- 实现订单跟踪服务(CopyOrderTrackingService),支持买入/卖出订单的创建和匹配
- 实现跟单统计服务(CopyTradingStatisticsService),支持盈亏统计和订单列表查询
- 添加失败交易记录(FailedTrade)和已处理交易去重(ProcessedTrade)
- 实现轮询服务(CopyTradingPollingService),使用Data API /activity接口轮询Leader交易
- 支持多元市场(使用outcomeIndex而不是YES/NO)
- 重试时重新生成salt并重新签名
- 添加风险控制检查(每日订单数、每日亏损、单笔订单大小限制)
- 支持价格容忍度和延迟跟单
- 添加数据库迁移文件(V8, V9, V10)
- 前端:账户管理显示代理钱包地址,添加复制功能,移除默认账户逻辑
- 修复API响应字段映射问题(orderID, transactionsHashes)
- 缩短轮询间隔到2秒
This commit is contained in:
WrBug
2025-12-02 03:34:43 +08:00
parent 844cd686eb
commit dffbc5124f
33 changed files with 2916 additions and 80 deletions
+3 -21
View File
@@ -14,7 +14,6 @@ interface AccountStore {
importAccount: (data: any) => Promise<void>
updateAccount: (data: any) => Promise<void>
deleteAccount: (accountId: number) => Promise<void>
setDefaultAccount: (accountId: number) => Promise<void>
fetchAccountDetail: (accountId: number) => Promise<Account>
fetchAccountBalance: (accountId: number) => Promise<{
availableBalance: string
@@ -38,10 +37,9 @@ export const useAccountStore = create<AccountStore>((set, get) => ({
const accounts = response.data.data.list || []
set({ accounts, loading: false })
// 设置默认账户为当前账户
const defaultAccount = accounts.find((a: Account) => a.isDefault)
if (defaultAccount) {
set({ currentAccount: defaultAccount })
// 如果没有当前账户,设置第一个账户为当前账户
if (accounts.length > 0 && !get().currentAccount) {
set({ currentAccount: accounts[0] })
}
} else {
set({ error: response.data.msg || '获取账户列表失败', loading: false })
@@ -103,22 +101,6 @@ export const useAccountStore = create<AccountStore>((set, get) => ({
}
},
setDefaultAccount: async (accountId) => {
set({ loading: true, error: null })
try {
const response = await apiService.accounts.setDefault({ accountId })
if (response.data.code === 0) {
await get().fetchAccounts()
} else {
set({ error: response.data.msg || '设置默认账户失败', loading: false })
throw new Error(response.data.msg || '设置默认账户失败')
}
} catch (error: any) {
set({ error: error.message || '设置默认账户失败', loading: false })
throw error
}
},
fetchAccountDetail: async (accountId) => {
set({ loading: true, error: null })
try {