Initial commit: Polymarket copy trading bot

- Backend: Spring Boot + Kotlin implementation
  - Account management with private key import
  - Leader management
  - Copy trading configuration
  - Order synchronization
  - Balance and position queries via Polymarket API
  - Ethereum RPC integration for USDC balance
  - Proxy address calculation

- Frontend: React + TypeScript
  - Account management UI
  - Mobile responsive design
  - Account import with private key/mnemonic support
  - Balance display and account details modal

- Database: MySQL with Flyway migrations
- API Integration: Polymarket CLOB API, Data API, Ethereum RPC
This commit is contained in:
WrBug
2025-11-21 04:32:08 +08:00
commit 4f7fef145f
70 changed files with 14618 additions and 0 deletions
+153
View File
@@ -0,0 +1,153 @@
import { create } from 'zustand'
import type { Account } from '../types'
import { apiService } from '../services/api'
interface AccountStore {
accounts: Account[]
currentAccount: Account | null
loading: boolean
error: string | null
// Actions
fetchAccounts: () => Promise<void>
setCurrentAccount: (account: Account | null) => void
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
positionBalance: string
totalBalance: string
positions: any[]
}>
}
export const useAccountStore = create<AccountStore>((set, get) => ({
accounts: [],
currentAccount: null,
loading: false,
error: null,
fetchAccounts: async () => {
set({ loading: true, error: null })
try {
const response = await apiService.accounts.list()
if (response.data.code === 0 && response.data.data) {
const accounts = response.data.data.list || []
set({ accounts, loading: false })
// 设置默认账户为当前账户
const defaultAccount = accounts.find((a: Account) => a.isDefault)
if (defaultAccount) {
set({ currentAccount: defaultAccount })
}
} else {
set({ error: response.data.msg || '获取账户列表失败', loading: false })
}
} catch (error: any) {
set({ error: error.message || '获取账户列表失败', loading: false })
}
},
setCurrentAccount: (account) => {
set({ currentAccount: account })
},
importAccount: async (data) => {
set({ loading: true, error: null })
try {
const response = await apiService.accounts.import(data)
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
}
},
updateAccount: async (data) => {
set({ loading: true, error: null })
try {
const response = await apiService.accounts.update(data)
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
}
},
deleteAccount: async (accountId) => {
set({ loading: true, error: null })
try {
const response = await apiService.accounts.delete({ 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
}
},
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 {
const response = await apiService.accounts.detail({ accountId })
if (response.data.code === 0 && response.data.data) {
set({ loading: false })
return response.data.data
} else {
const errorMsg = response.data.msg || '获取账户详情失败'
set({ error: errorMsg, loading: false })
throw new Error(errorMsg)
}
} catch (error: any) {
set({ error: error.message || '获取账户详情失败', loading: false })
throw error
}
},
fetchAccountBalance: async (accountId) => {
try {
const response = await apiService.accounts.balance({ accountId })
if (response.data.code === 0 && response.data.data) {
return response.data.data
} else {
throw new Error(response.data.msg || '获取账户余额失败')
}
} catch (error: any) {
throw error
}
}
}))