From ddca28e51c01e1f22687729237adcd2471a13386 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 26 Feb 2026 16:10:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=EF=BC=9A=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E6=95=B0=E6=8D=AE=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 8 ++ docs/api/mockData.md | 41 ++++++ docs/api/mockEventList.md | 2 +- docs/config/mock.md | 37 +++++ src/api/mockData.ts | 262 +++++++++++++++++++++++++++++++++++ src/components/OrderBook.vue | 56 +++----- src/config/mock.ts | 35 +++++ src/views/EventMarkets.vue | 12 +- src/views/Home.vue | 3 +- src/views/Wallet.vue | 166 +++------------------- 10 files changed, 426 insertions(+), 196 deletions(-) create mode 100644 docs/api/mockData.md create mode 100644 docs/config/mock.md create mode 100644 src/api/mockData.ts create mode 100644 src/config/mock.ts diff --git a/.env.example b/.env.example index f97eb53..e06629c 100644 --- a/.env.example +++ b/.env.example @@ -6,6 +6,14 @@ # WebSocket 路径前缀(可选)。若 CLOB WS 在 /api/clob/ws 且 API base 无 /api,则设: # VITE_WS_PATH_PREFIX=/api # +# 模拟数据开关(方便本地测试): +# VITE_USE_MOCK_DATA=true # 总开关:全部启用 mock +# VITE_USE_MOCK_DATA=false # 全部关闭 mock +# VITE_USE_MOCK_CATEGORY=true # 分类树用 mock +# VITE_USE_MOCK_EVENT=true # 事件接口失败时 mock 兜底(默认 true) +# VITE_USE_MOCK_ORDER_BOOK=true # 订单簿无 CLOB 时用 mock(默认 true) +# VITE_USE_MOCK_WALLET=true # 钱包持仓/订单/历史用 mock(默认 true) +# # 生产打包/部署时自动使用 .env.production 中的 https://api.xtrader.vip # SSH 部署(npm run deploy),不配置时使用默认值 diff --git a/docs/api/mockData.md b/docs/api/mockData.md new file mode 100644 index 0000000..43626c9 --- /dev/null +++ b/docs/api/mockData.md @@ -0,0 +1,41 @@ +# mockData.ts + +**路径**:`src/api/mockData.ts` + +## 功能用途 + +模拟数据统一封装,集中管理事件、分类、订单簿、钱包等 mock 数据,配合 `src/config/mock.ts` 的开关使用。 + +## 导出内容 + +| 导出 | 类型 | 说明 | +|------|------|------| +| `MOCK_EVENT_LIST` | `PmEventListItem[]` | 模拟事件列表(来自 mockEventList) | +| `MOCK_CATEGORY_TREE` | `CategoryTreeNode[]` | 模拟分类树(来自 category) | +| `MOCK_ORDER_BOOK_ASKS` | `MockOrderBookRow[]` | 订单簿卖单 | +| `MOCK_ORDER_BOOK_BIDS` | `MockOrderBookRow[]` | 订单簿买单 | +| `MOCK_ORDER_BOOK_LAST_PRICE` | `number` | 最新价 | +| `MOCK_ORDER_BOOK_SPREAD` | `number` | 价差 | +| `MOCK_TOKEN_ID` | `string` | 测试用 token ID | +| `MOCK_WALLET_POSITIONS` | `MockPosition[]` | 钱包持仓 | +| `MOCK_WALLET_ORDERS` | `MockOpenOrder[]` | 钱包未成交订单 | +| `MOCK_WALLET_HISTORY` | `MockHistoryItem[]` | 钱包历史 | +| `getMockEventById(id)` | `(id: number) => PmEventListItem \| null` | 按 ID 获取 mock 事件 | + +## 使用方式 + +```typescript +import { MOCK_WALLET_POSITIONS, getMockEventById } from '@/api/mockData' +import { USE_MOCK_WALLET } from '@/config/mock' + +if (USE_MOCK_WALLET) { + positions.value = [...MOCK_WALLET_POSITIONS] +} + +const fallback = getMockEventById(9001) +``` + +## 扩展方式 + +1. 新增 mock 数据:在 `mockData.ts` 中定义并导出 +2. 修改现有数据:直接编辑对应常量 diff --git a/docs/api/mockEventList.md b/docs/api/mockEventList.md index 44ef0c4..1a76bcb 100644 --- a/docs/api/mockEventList.md +++ b/docs/api/mockEventList.md @@ -24,4 +24,4 @@ const cards = MOCK_EVENT_LIST.map(mapEventItemToCard) ## 扩展方式 1. **新增 mock 项**:在 `MOCK_EVENT_LIST` 中追加符合 `PmEventListItem` 结构的对象 -2. **环境切换**:在 Home 等视图中根据 `import.meta.env.DEV` 选择使用 mock 或真实接口 +2. **统一入口**:`MOCK_EVENT_LIST` 已由 `src/api/mockData.ts` 统一导出,配合 `src/config/mock.ts` 的 `USE_MOCK_EVENT` 开关使用 diff --git a/docs/config/mock.md b/docs/config/mock.md new file mode 100644 index 0000000..fee500f --- /dev/null +++ b/docs/config/mock.md @@ -0,0 +1,37 @@ +# mock.ts + +**路径**:`src/config/mock.ts` + +## 功能用途 + +模拟数据开关配置,通过环境变量控制各模块是否使用 mock 数据,方便本地测试与联调。 + +## 开关说明 + +| 变量 | 说明 | 默认值 | +|------|------|--------| +| `VITE_USE_MOCK_DATA` | 总开关:`true` 全部启用,`false` 全部关闭 | - | +| `VITE_USE_MOCK_CATEGORY` | 分类树:Home 使用模拟分类 | false | +| `VITE_USE_MOCK_EVENT` | 事件:EventMarkets 接口失败时 mock 兜底 | true | +| `VITE_USE_MOCK_ORDER_BOOK` | 订单簿:无 CLOB 数据时用 mock | true | +| `VITE_USE_MOCK_WALLET` | 钱包:持仓/订单/历史用 mock | true | + +## 使用方式 + +在 `.env` 中配置: + +```bash +# 全部启用 mock +VITE_USE_MOCK_DATA=true + +# 全部关闭 mock(联调真实接口时) +VITE_USE_MOCK_DATA=false + +# 仅分类树用 mock +VITE_USE_MOCK_CATEGORY=true +``` + +## 扩展方式 + +1. 新增模块开关:在 `mock.ts` 中增加 `USE_MOCK_XXX` 导出 +2. 新增 mock 数据:在 `src/api/mockData.ts` 中补充并导出 diff --git a/src/api/mockData.ts b/src/api/mockData.ts new file mode 100644 index 0000000..65e5d0d --- /dev/null +++ b/src/api/mockData.ts @@ -0,0 +1,262 @@ +/** + * 模拟数据统一封装 + * 供 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 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 }, +] + +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 +} + +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', + }, + { + 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 +} diff --git a/src/components/OrderBook.vue b/src/components/OrderBook.vue index 2e454f0..c77b3a3 100644 --- a/src/components/OrderBook.vue +++ b/src/components/OrderBook.vue @@ -82,6 +82,13 @@ import { ref, computed, watch } from 'vue' import { useI18n } from 'vue-i18n' import HorizontalProgressBar from './HorizontalProgressBar.vue' +import { + MOCK_ORDER_BOOK_ASKS, + MOCK_ORDER_BOOK_BIDS, + MOCK_ORDER_BOOK_LAST_PRICE, + MOCK_ORDER_BOOK_SPREAD, +} from '../api/mockData' +import { USE_MOCK_ORDER_BOOK } from '../config/mock' const { t } = useI18n() @@ -118,48 +125,27 @@ const props = withDefaults( // State const activeTrade = ref('up') -// 使用 props 或回退到 mock 数据 -const internalAsks = ref([ - { 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 }, -]) -const internalBids = ref([ - { 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 }, -]) -const internalLastPrice = ref(37) -const internalSpread = ref(1) +// 使用 props 或回退到 mock 数据(来自 mockData 统一封装) +const internalAsks = ref([...MOCK_ORDER_BOOK_ASKS]) +const internalBids = ref([...MOCK_ORDER_BOOK_BIDS]) +const internalLastPrice = ref(MOCK_ORDER_BOOK_LAST_PRICE) +const internalSpread = ref(MOCK_ORDER_BOOK_SPREAD) -// 当有外部数据时使用 props,否则用 mock +// 当有外部数据时使用 props,否则在 USE_MOCK_ORDER_BOOK 时用 mock const asks = computed(() => - props.asks?.length ? props.asks : internalAsks.value, + props.asks?.length ? props.asks : USE_MOCK_ORDER_BOOK ? internalAsks.value : [], ) const bids = computed(() => - props.bids?.length ? props.bids : internalBids.value, + props.bids?.length ? props.bids : USE_MOCK_ORDER_BOOK ? internalBids.value : [], ) const displayLastPrice = computed(() => - props.lastPrice ?? internalLastPrice.value, + props.lastPrice ?? (USE_MOCK_ORDER_BOOK ? internalLastPrice.value : 0), +) +const displaySpread = computed(() => + props.spread ?? (USE_MOCK_ORDER_BOOK ? internalSpread.value : 0), ) -const displaySpread = computed(() => props.spread ?? internalSpread.value) -// 仅在没有外部数据时运行 mock 更新 +// 仅在没有外部数据且开启 mock 时运行 mock 更新 let mockInterval: ReturnType | undefined watch( () => props.connected || (props.asks?.length ?? 0) > 0, @@ -167,7 +153,7 @@ watch( if (hasRealData && mockInterval) { clearInterval(mockInterval) mockInterval = undefined - } else if (!hasRealData && !mockInterval) { + } else if (!hasRealData && USE_MOCK_ORDER_BOOK && !mockInterval) { mockInterval = setInterval(() => { const randomAskIndex = Math.floor(Math.random() * internalAsks.value.length) const askItem = internalAsks.value[randomAskIndex] diff --git a/src/config/mock.ts b/src/config/mock.ts new file mode 100644 index 0000000..9b2843f --- /dev/null +++ b/src/config/mock.ts @@ -0,0 +1,35 @@ +/** + * 模拟数据开关配置 + * 通过环境变量控制,方便本地测试与联调 + * + * 使用方式: + * - .env 中设置 VITE_USE_MOCK_DATA=true 开启总开关 + * - 或单独设置各模块:VITE_USE_MOCK_CATEGORY、VITE_USE_MOCK_EVENT、VITE_USE_MOCK_ORDER_BOOK、VITE_USE_MOCK_WALLET + */ + +const env = typeof import.meta !== 'undefined' ? (import.meta as { env?: Record }).env : {} + +function isTruthy(val: string | undefined): boolean { + return val === 'true' || val === '1' || val === 'yes' +} +function isFalsy(val: string | undefined): boolean { + return val === 'false' || val === '0' || val === 'no' +} + +const master = env?.VITE_USE_MOCK_DATA + +/** 分类树:Home 使用模拟分类(一层二层三层 UI 测试),默认 false */ +export const USE_MOCK_CATEGORY = + isTruthy(master) || (master === undefined && isTruthy(env?.VITE_USE_MOCK_CATEGORY)) + +/** 事件/市场:EventMarkets 接口失败时用 mock 兜底,默认 true */ +export const USE_MOCK_EVENT = + isFalsy(master) ? false : isTruthy(master) || isTruthy(env?.VITE_USE_MOCK_EVENT) || env?.VITE_USE_MOCK_EVENT === undefined + +/** 订单簿:OrderBook 无 CLOB 数据时使用 mock,默认 true */ +export const USE_MOCK_ORDER_BOOK = + isFalsy(master) ? false : isTruthy(master) || isTruthy(env?.VITE_USE_MOCK_ORDER_BOOK) || env?.VITE_USE_MOCK_ORDER_BOOK === undefined + +/** 钱包:Wallet 持仓/订单/历史使用 mock,默认 true */ +export const USE_MOCK_WALLET = + isFalsy(master) ? false : isTruthy(master) || isTruthy(env?.VITE_USE_MOCK_WALLET) || env?.VITE_USE_MOCK_WALLET === undefined diff --git a/src/views/EventMarkets.vue b/src/views/EventMarkets.vue index fb9d76e..d626b6c 100644 --- a/src/views/EventMarkets.vue +++ b/src/views/EventMarkets.vue @@ -197,7 +197,8 @@ import { type PmEventListItem, type PmEventMarketItem, } from '../api/event' -import { MOCK_EVENT_LIST } from '../api/mockEventList' +import { getMockEventById } from '../api/mockData' +import { USE_MOCK_EVENT } from '../config/mock' import { useI18n } from 'vue-i18n' import { useUserStore } from '../stores/user' import { useToastStore } from '../stores/toast' @@ -643,7 +644,7 @@ async function loadEventDetail() { eventDetail.value = res.data ?? null detailError.value = null } else { - const fallback = isNumericId ? getMockEventById(numId) : null + const fallback = USE_MOCK_EVENT && isNumericId ? getMockEventById(numId) : null if (fallback) { eventDetail.value = fallback detailError.value = null @@ -653,7 +654,7 @@ async function loadEventDetail() { } } } catch (e) { - const fallback = isNumericId ? getMockEventById(numId) : null + const fallback = USE_MOCK_EVENT && isNumericId ? getMockEventById(numId) : null if (fallback) { eventDetail.value = fallback detailError.value = null @@ -666,11 +667,6 @@ async function loadEventDetail() { } } -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 -} - onMounted(() => { loadEventDetail() window.addEventListener('resize', handleResize) diff --git a/src/views/Home.vue b/src/views/Home.vue index 17c70f8..ffa5eca 100644 --- a/src/views/Home.vue +++ b/src/views/Home.vue @@ -322,6 +322,7 @@ import { resolveCategoryIconColor, type CategoryTreeNode, } from '../api/category' +import { USE_MOCK_CATEGORY } from '../config/mock' import { useI18n } from 'vue-i18n' import { useSearchHistory } from '../composables/useSearchHistory' import { useToastStore } from '../stores/toast' @@ -651,8 +652,6 @@ onMounted(() => { } } - /** 开发时设为 true 可始终使用模拟数据查看一二三层 UI */ - const USE_MOCK_CATEGORY = false if (USE_MOCK_CATEGORY) { categoryTree.value = enrichWithIcons(MOCK_CATEGORY_TREE) initCategorySelection() diff --git a/src/views/Wallet.vue b/src/views/Wallet.vue index fd68be6..b82f1a8 100644 --- a/src/views/Wallet.vue +++ b/src/views/Wallet.vue @@ -573,6 +573,13 @@ import DepositDialog from '../components/DepositDialog.vue' import WithdrawDialog from '../components/WithdrawDialog.vue' import { useUserStore } from '../stores/user' import { pmCancelOrder } from '../api/market' +import { + MOCK_TOKEN_ID, + MOCK_WALLET_POSITIONS, + MOCK_WALLET_ORDERS, + MOCK_WALLET_HISTORY, +} from '../api/mockData' +import { USE_MOCK_WALLET } from '../config/mock' const { mobile } = useDisplay() const userStore = useUserStore() @@ -669,156 +676,15 @@ interface HistoryItem { iconClass?: string } -const positions = ref([ - { - 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', - }, - { - 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', - }, -]) -const MOCK_TOKEN_ID = - '59966088656508531737144108943848781534186324373509174641856486864137458635937' -const openOrders = ref([ - { - 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, - }, -]) -const history = ref([ - { - 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', - }, -]) +const positions = ref( + USE_MOCK_WALLET ? [...MOCK_WALLET_POSITIONS] : [], +) +const openOrders = ref( + USE_MOCK_WALLET ? [...MOCK_WALLET_ORDERS] : [], +) +const history = ref( + USE_MOCK_WALLET ? [...MOCK_WALLET_HISTORY] : [], +) function matchSearch(text: string): boolean { const q = search.value.trim().toLowerCase()