跳到主要内容

市场分类

服务:zepto-server(链外),不是链节点。
生产基址https://admin.auroran.io/api/
例:https://admin.auroran.io/api/public/market-categories
交易站浏览器前缀 /market-classifications-api/*/api/public/*
管理接口要 Admin Bearer,公开读无鉴权。
链上市场列表仍走 getMarkets

市场分类是后台可配置的运营元数据,不参与链上状态与共识。 分类体系为两级:总分类 → 子分类;名称、数量、层级均可在后台增删改。

分类与市场的关联采用 「分类大集合」模式:后端维护一张 market_catalog, 以 symbol 为键(统一小写存储) 记录「市场 → 分类」,包含链上尚未上架的市场。 前端拉取目录后,与链上市场列表按 symbol 忽略大小写 匹配归类; 管理员也可按 symbol 手动向分类中添加/移除市场。

默认种子对齐 Hyperliquid perpCategories:总分类 crypto / tradfi; crypto 下 layer1/layer2/defi/meme/ai/gaming/other, tradfi 下 stocks/indices/commodities/forex/bonds/otherpreipo(上市前)已从分类体系移除,同步时跳过且不会重建。

数据模型

market_categories(分类树):

字段类型说明
idu32分类 ID
parent_idu32?父分类 ID;null = 总分类(仅支持两级)
codeString稳定标识符(^[a-z0-9_]+$),用于 HL 导入映射
labelsMap<String,String>多语言展示名:locale → label(缺语言回退 zh → en → code)
sort_orderu32排序
enabledbool停用后不出现在公开接口
sourceStringseed(内置种子)/ manual(手工)/ hl(HL 同步)
created_at_msu64创建时间
updated_at_msu64最近更新时间

market_catalog(市场 → 分类大集合,现行分类来源):

字段类型说明
symbolString主键,统一小写存储,匹配忽略大小写
category_idu32关联的分类节点(允许总分类或子分类)
sourceStringhl(HL 同步)/ manual(管理员手工添加)
updated_byString最近操作人

market_classifications(旧 market_id 关联表)不再作为分类来源。 迁移时历史行一次性导入 market_catalogsource='manual')。 对应 HTTP 路由仍挂在 zepto-server(见 遗留路由), 交易界面与分类页只读 market_catalog

公开只读接口(无鉴权)

生产:https://admin.auroran.io/api/public/…。 交易站可由 nginx / Vite 反代 /market-classifications-api/*/api/public/*

GET /api/public/market-categories

仅返回启用分类,按 parent_id IS NULL DESC, parent_id, sort_order 排序。 响应含 source / created_at_ms / updated_at_ms

{
"categories": [{
"id": 1,
"parent_id": null,
"code": "crypto",
"labels": { "zh": "加密货币", "en": "Crypto" },
"sort_order": 10,
"enabled": true,
"source": "seed",
"created_at_ms": 1755000000000,
"updated_at_ms": 1755000000000
}]
}

GET /api/public/market-catalog

分类大集合(全部市场,含链上未上架)。symbol 已小写。不含 source / updated_by

{
"markets": [{
"symbol": "xyz:tsla",
"category_id": 12,
"category_code": "stocks"
}]
}

管理接口(Bearer 鉴权)

路由方法说明
/api/market-categoriesGET全部分类(含停用;字段同公开接口)
/api/market-categoriesPOST创建分类:{ parent_id?, code, labels, sort_order?, enabled? }{ ok, category }
/api/market-categories/{id}PUT更新分类(parent_id: null 显式清空为总分类)
/api/market-categories/{id}DELETE删除分类(有子分类或被市场使用时返回 409)
/api/market-catalogGET全量目录(含 source / updated_by
/api/market-categories/{id}/marketsPOST按 symbol 添加/移除市场:{ add?: string[], remove?: string[] }(忽略大小写,添加为 manual);空 add 且空 remove → 400
/api/market-categories/cleanupPOST一键整理:白名单子分类(股票/外汇/大宗商品/指数等)归位到对应总分类;删除已移除分类(如 preipo)及其目录市场

约束:两级层级(总分类不能挂在子分类下);停用分类不可被市场关联; 删除分类前需先解除子分类与市场关联。

从 Hyperliquid 同步(点一次执行一次,无定时)

以 Hyperliquid perpCategories 为源做全量覆盖同步,仅在管理员点击时执行。 同步不依赖链上市场,每个同步的分类会把 HL 中该分类下的全部市场 (含链上未上架)写入 market_catalogmanual 条目不会被覆盖。

POST /api/market-categories/sync/preview

预览(不写库),返回:

字段类型说明
candidatesSyncCandidate[]HL 有、本地没有的新分类
updatesSyncCandidate[]已有 source=hl 分类,本次会被覆盖

SyncCandidate{ code, labels, parent_code, hl_value, market_count }, 其中 market_count 为该分类下 HL 市场数量(含未上架)。

POST /api/market-categories/sync/import

Body:{ codes: string[] }(无 apply_to_markets;该字段已删除)。

语义:

  • 按 code 归一化(fxforexLayer 1layer1);preipo 跳过不导入;
  • 不存在的分类 → 新建(source=hl);已存在的 source=hl 分类 → 覆盖名称/挂载/启用; 手工(source=manual)与内置种子(source=seed)分类受保护不覆盖
  • 未知 HL 分类挂到自动创建的兜底总分类 misc 下(管理员可再调整);
  • 每个同步的分类:删除该分类下 source='hl' 的目录条目,写入 HL 当前全量市场 (统一小写、去重);manual 条目保留。

返回 { added, updated, skipped, markets_synced }

遗留路由(market_classifications)

下列路由仍注册、仍可调用,但不是交易界面的分类来源。 zepto-admin 从 Hyperliquid 创建市场时仍可能写旧表(best-effort)。

路由方法说明
/api/public/market-classificationsGETmarket_id → 分类列表(无鉴权)
/api/market-classificationsGET同上,含 updated_at_ms / updated_by(Bearer)
/api/market-classifications/{marketId}PUTbody { symbol, category_id },按 market_id upsert
/api/market-classifications/{marketId}DELETE按 market_id 删除旧关联

新接入只读 /api/public/market-catalog + /api/public/market-categories

前端匹配规则

前端将链上 getMarkets 与公开目录按 symbol 匹配(忽略大小写),解析顺序:

  1. 覆盖表(特殊命名,如 kBONK-USDkBONK);
  2. {dex}: 前缀(HIP-3,如 xyz:TSLATSLA);
  3. 交易对 base(如 BTC-USDTBTC)。

未匹配的市场保持「未分类」(交易界面回退旧的 symbol 前缀启发式分组); Native 市场由管理员在后台把其 symbol 添加到对应分类即可自动匹配。

交易界面(zepto-web)的市场选择器模仿 Hyperliquid 做两排分类: 第一排为总分类(全部 / 永续 + 总分类),选中总分类后出现第二排子分类 (全部 + 该总分类下的子分类),点子分类仅显示该子分类的市场。