303 lines
7.4 KiB
TypeScript
303 lines
7.4 KiB
TypeScript
/**
|
||
* 模拟数据统一封装
|
||
* 供 Home、EventMarkets、OrderBook、Wallet 等使用
|
||
* 配合 src/config/mock.ts 的开关控制
|
||
*/
|
||
|
||
import type { PmEventListItem } from './event'
|
||
|
||
// --- 事件列表(来自 mockEventList) ---
|
||
import { MOCK_EVENT_LIST } from './mockEventList'
|
||
export { MOCK_EVENT_LIST }
|
||
|
||
// --- 分类树(来自 category) ---
|
||
export { MOCK_CATEGORY_TREE } from './category'
|
||
|
||
// --- 订单簿 mock ---
|
||
export interface MockOrderBookRow {
|
||
price: number
|
||
shares: number
|
||
}
|
||
|
||
/** 生成随机订单簿数据,每次进入页面不同;保证卖单最低价 > 买单最高价 */
|
||
export function generateRandomOrderBook(): {
|
||
asks: MockOrderBookRow[]
|
||
bids: MockOrderBookRow[]
|
||
lastPrice: number
|
||
spread: number
|
||
} {
|
||
const r = () => Math.random()
|
||
|
||
// 买单最高价 25–35,卖单最低价 = 买单最高价 + 1 + spread,保证有价差
|
||
const highestBid = Math.floor(25 + r() * 11)
|
||
const spread = Math.max(1, Math.floor(1 + r() * 3))
|
||
const lowestAsk = highestBid + spread
|
||
|
||
const askPrices = Array.from({ length: 9 }, (_, i) => lowestAsk + i)
|
||
const asks: MockOrderBookRow[] = askPrices.map((p) => ({
|
||
price: p,
|
||
shares: Math.round((500 + r() * 3000) * 10) / 10,
|
||
}))
|
||
|
||
const bidPrices = Array.from({ length: 12 }, (_, i) => highestBid - i)
|
||
const bids: MockOrderBookRow[] = bidPrices.map((p) => ({
|
||
price: Math.max(1, p),
|
||
shares: Math.round((200 + r() * 3000) * 10) / 10,
|
||
}))
|
||
|
||
const lastPrice = Math.floor((highestBid + lowestAsk) / 2)
|
||
|
||
return { asks, bids, lastPrice, spread }
|
||
}
|
||
|
||
/** @deprecated 使用 generateRandomOrderBook() 获取随机数据 */
|
||
export const MOCK_ORDER_BOOK_ASKS: MockOrderBookRow[] = [
|
||
{ price: 45, shares: 1000.0 },
|
||
{ price: 44, shares: 2500.0 },
|
||
{ price: 43, shares: 1800.0 },
|
||
{ price: 42, shares: 3200.0 },
|
||
{ price: 41, shares: 2000.0 },
|
||
{ price: 40, shares: 1500.0 },
|
||
{ price: 39, shares: 800.0 },
|
||
{ price: 38, shares: 500.0 },
|
||
{ price: 37, shares: 300.0 },
|
||
]
|
||
|
||
/** @deprecated 使用 generateRandomOrderBook() 获取随机数据 */
|
||
export const MOCK_ORDER_BOOK_BIDS: MockOrderBookRow[] = [
|
||
{ price: 36, shares: 200.0 },
|
||
{ price: 35, shares: 500.0 },
|
||
{ price: 34, shares: 1000.0 },
|
||
{ price: 33, shares: 1500.0 },
|
||
{ price: 32, shares: 2000.0 },
|
||
{ price: 31, shares: 2500.0 },
|
||
{ price: 30, shares: 3000.0 },
|
||
{ price: 29, shares: 2800.0 },
|
||
{ price: 28, shares: 2500.0 },
|
||
{ price: 27, shares: 2000.0 },
|
||
{ price: 26, shares: 1500.0 },
|
||
{ price: 25, shares: 1000.0 },
|
||
]
|
||
|
||
export const MOCK_ORDER_BOOK_LAST_PRICE = 37
|
||
export const MOCK_ORDER_BOOK_SPREAD = 1
|
||
|
||
// --- 钱包 mock ---
|
||
export const MOCK_TOKEN_ID =
|
||
'59966088656508531737144108943848781534186324373509174641856486864137458635937'
|
||
|
||
export interface MockPosition {
|
||
id: string
|
||
market: string
|
||
iconChar?: string
|
||
iconClass?: string
|
||
outcomeTag?: string
|
||
outcomePillClass?: string
|
||
shares: string
|
||
avgNow: string
|
||
bet: string
|
||
toWin: string
|
||
value: string
|
||
valueChange?: string
|
||
valueChangePct?: string
|
||
valueChangeLoss?: boolean
|
||
sellOutcome?: string
|
||
outcomeWord?: string
|
||
/** 用于领取结算(mock 时可选,便于展示未结算行) */
|
||
marketID?: string
|
||
tokenID?: string
|
||
needClaim?: boolean
|
||
}
|
||
|
||
export interface MockOpenOrder {
|
||
id: string
|
||
market: string
|
||
side: 'Yes' | 'No'
|
||
outcome: string
|
||
price: string
|
||
filled: string
|
||
total: string
|
||
expiration: string
|
||
actionLabel?: string
|
||
filledDisplay?: string
|
||
iconChar?: string
|
||
iconClass?: string
|
||
orderID?: number
|
||
tokenID?: string
|
||
}
|
||
|
||
export interface MockHistoryItem {
|
||
id: string
|
||
market: string
|
||
side: 'Yes' | 'No'
|
||
activity: string
|
||
value: string
|
||
activityDetail?: string
|
||
profitLoss?: string
|
||
profitLossNegative?: boolean
|
||
timeAgo?: string
|
||
avgPrice?: string
|
||
shares?: string
|
||
iconChar?: string
|
||
iconClass?: string
|
||
}
|
||
|
||
export const MOCK_WALLET_POSITIONS: MockPosition[] = [
|
||
{
|
||
id: 'p1',
|
||
market: 'Bitcoin Up or Down - February 9, 2:00AM-2:15AM ET',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
outcomeTag: 'Down 72¢',
|
||
outcomePillClass: 'pill-down',
|
||
shares: '6.9 shares',
|
||
avgNow: '72¢ → 0.5¢',
|
||
bet: '$4.95',
|
||
toWin: '$6.87',
|
||
value: '$0.03',
|
||
valueChange: '-$4.91',
|
||
valueChangePct: '99.31%',
|
||
valueChangeLoss: true,
|
||
sellOutcome: 'Down',
|
||
outcomeWord: 'Down',
|
||
marketID: 'mock-market-1',
|
||
tokenID: MOCK_TOKEN_ID,
|
||
needClaim: true,
|
||
},
|
||
{
|
||
id: 'p2',
|
||
market: 'Bitcoin Up or Down - February 9, 2:15AM-2:30AM ET',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
outcomeTag: 'Up 26¢',
|
||
outcomePillClass: 'pill-yes',
|
||
shares: '3.8 shares',
|
||
avgNow: '28¢ → 26¢',
|
||
bet: '$0.99',
|
||
toWin: '$3.54',
|
||
value: '$0.90',
|
||
valueChange: '-$0.09',
|
||
valueChangePct: '8.9%',
|
||
valueChangeLoss: true,
|
||
sellOutcome: 'Up',
|
||
outcomeWord: 'Up',
|
||
},
|
||
{
|
||
id: 'p3',
|
||
market: 'Will ETH merge complete by Q3?',
|
||
iconChar: 'Ξ',
|
||
iconClass: 'position-icon-eth',
|
||
outcomeTag: 'Yes 48¢',
|
||
outcomePillClass: 'pill-yes',
|
||
shares: '30 shares',
|
||
avgNow: '45¢ → 48¢',
|
||
bet: '$30',
|
||
toWin: '$36',
|
||
value: '$32',
|
||
valueChange: '+$2',
|
||
valueChangePct: '6.67%',
|
||
valueChangeLoss: false,
|
||
sellOutcome: 'Yes',
|
||
outcomeWord: 'Yes',
|
||
},
|
||
]
|
||
|
||
export const MOCK_WALLET_ORDERS: MockOpenOrder[] = [
|
||
{
|
||
id: 'o1',
|
||
market: 'Bitcoin Up or Down - February 9, 2:45AM-3:00AM ET',
|
||
side: 'Yes',
|
||
outcome: 'Up',
|
||
price: '1¢',
|
||
filled: '0',
|
||
total: '$0.05',
|
||
expiration: 'Until Cancelled',
|
||
actionLabel: 'Buy Up',
|
||
filledDisplay: '0/5',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
orderID: 5,
|
||
tokenID: MOCK_TOKEN_ID,
|
||
},
|
||
{
|
||
id: 'o2',
|
||
market: 'Will Bitcoin hit $100k by end of 2025?',
|
||
side: 'Yes',
|
||
outcome: 'Yes',
|
||
price: '70¢',
|
||
filled: '0',
|
||
total: '$70',
|
||
expiration: 'Dec 31, 2025',
|
||
orderID: 5,
|
||
tokenID: MOCK_TOKEN_ID,
|
||
},
|
||
{
|
||
id: 'o3',
|
||
market: 'Will ETH merge complete by Q3?',
|
||
side: 'No',
|
||
outcome: 'No',
|
||
price: '52¢',
|
||
filled: '25',
|
||
total: '$26',
|
||
expiration: 'Sep 30, 2025',
|
||
orderID: 5,
|
||
tokenID: MOCK_TOKEN_ID,
|
||
},
|
||
]
|
||
|
||
export const MOCK_WALLET_HISTORY: MockHistoryItem[] = [
|
||
{
|
||
id: 'h1',
|
||
market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
|
||
side: 'No',
|
||
activity: 'Sell No',
|
||
activityDetail: 'Sold 1 Down at 50¢',
|
||
value: '$0.50',
|
||
profitLoss: '+$0.50',
|
||
profitLossNegative: false,
|
||
timeAgo: '3 minutes ago',
|
||
avgPrice: '50¢',
|
||
shares: '1',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
},
|
||
{
|
||
id: 'h2',
|
||
market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
|
||
side: 'Yes',
|
||
activity: 'Sell Yes',
|
||
activityDetail: 'Sold 1 Up at 63¢',
|
||
value: '$0.63',
|
||
profitLoss: '+$0.63',
|
||
profitLossNegative: false,
|
||
timeAgo: '6 minutes ago',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
},
|
||
{
|
||
id: 'h3',
|
||
market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
|
||
side: 'Yes',
|
||
activity: 'Split',
|
||
activityDetail: 'Split',
|
||
value: '-$1.00',
|
||
profitLoss: '-$1.00',
|
||
profitLossNegative: true,
|
||
timeAgo: '7 minutes ago',
|
||
iconChar: '₿',
|
||
iconClass: 'position-icon-btc',
|
||
},
|
||
{
|
||
id: 'h4',
|
||
market: 'Will ETH merge complete by Q3?',
|
||
side: 'No',
|
||
activity: 'Sell No',
|
||
value: '$35.20',
|
||
},
|
||
]
|
||
|
||
export function getMockEventById(id: number): PmEventListItem | null {
|
||
const item = MOCK_EVENT_LIST.find((e) => e.ID === id)
|
||
return item && (item.markets?.length ?? 0) > 1 ? item : null
|
||
}
|