开发者指南

Open API 实施方案

Microcosm Open API 实施方案

版本: v2.2 状态: ✅ Phase 1-3 已部署 | ✅ Phase 5-8 已完成 | ✅ 科技树 API 已实施 | ✅ 用户来源追踪已实施 创建日期: 2026-01-08 更新日期: 2026-02-02 当前版本: open-api-service v1.1.22, blockchain-service v1.2.38 目标: 为所有外部项目提供标准化的 Microcosm 业务数据访问接口

v2.2 更新 (2026-02-02):

  • ✅ 新增公开 stats 端点: /v1/mcc/stats, /v1/mcd/stats (无需认证)
  • ✅ 用户来源追踪 (source_project_id) 已实施,OAuth 登录自动记录
  • ✅ 开发者伴生矿已上线,DHC 项目配置完成

v2.1 更新 (2026-02-01): ✅ 新增 Microcosm 科技树 CronJob (tech-tree-daily-update),基于 KPI 自动更新科技树状态

v2.0 更新 (2026-02-01): ✅ 科技树 API (/v1/tech-tree/*) 已实施,删除 Double Helix 历史遗留 CronJob

v1.9 更新 (2026-01-25): ✅ Phase 8 项目注册与 MCD 白名单管理功能已实施完成

v1.7 更新 (2026-01-19): 新增 Section 16 价格预言机架构,Open API /v1/mcc/price 作为预言机备用价格来源

v1.6 更新 (2026-01-16): 新增 Phase 7 Solana 合约 API(Territory NFT、Auction Solana、Fragment、Lending),共 23 个端点

v1.3 更新: 新增 Phase 5 交易类 API 架构设计,包含铸造提交、资金管理、转账请求、Webhook 回调机制和零信任安全模型


1. 背景与目标

1.1 当前问题

问题描述
架构局限当前 API 仅支持 K8s 集群内部访问
扩展性差外部项目(AWS、阿里云等)无法安全访问 Microcosm 数据
临时方案泛滥每个项目都在写临时代理代码
缺乏标准化无统一的 API 规范和文档

1.2 目标

  1. 公开化: 提供可从任意网络访问的 Public API
  2. 标准化: 遵循 OpenAPI 3.1 规范
  3. 安全性: OAuth 2.0 + API Rate Limiting
  4. 可扩展: 支持未来新增业务数据
  5. 高可用: 多区域部署支持

2. 工业标准遵循

2.1 API 设计标准

标准版本用途
OpenAPI Specification3.1.0API 文档规范
RESTful API DesignLevel 3 (HATEOAS)资源设计原则
JSON:API1.1响应格式规范
RFC 7807-Problem Details for HTTP APIs (错误响应)
RFC 6749-OAuth 2.0 Authorization Framework
RFC 6750-Bearer Token Usage
Semantic Versioning2.0.0API 版本管理

2.2 安全标准

标准用途
OAuth 2.0 + PKCE公共客户端授权
JWT (RFC 7519)Access Token 格式
TLS 1.3传输加密
CORS跨域访问控制
Rate Limiting (RFC 6585)速率限制响应头

3. API 架构设计

3.1 整体架构

外部项目层:

项目部署平台
Double HelixGCP
Event HorizonGCP
第三方项目 AAWS
第三方项目 B阿里云

所有外部项目通过 HTTPS 请求访问统一入口。

Microcosm Open API Gateway (https://api.microcosm.money):

  • OAuth 2.0 Token Validation
  • Rate Limiting
  • Request Logging
  • API Versioning (/v1, /v2)

Microcosm K8s 集群内部:

  1. open-api-service (统一入口) 接收 Gateway 转发的请求
  2. open-api-service 根据请求类型转发到内部服务:
内部服务职责
user-service用户信息
blockchain-service链上数据
organization-service组织/领地

3.2 域名规划

域名用途
api.microcosm.moneyOpen API 入口 (新增)
auth.microcosm.moneyOAuth 认证服务 (现有)
microcosm.money前端门户 (现有)

3.3 API 版本策略

https://api.microcosm.money/v1/mcc/balance https://api.microcosm.money/v1/mcd/balance https://api.microcosm.money/v2/mcc/balance (未来版本)
  • URL Path Versioning: /v1/, /v2/
  • 版本生命周期: 新版本发布后,旧版本支持 12 个月
  • Breaking Changes: 仅在大版本升级时引入

4. API 端点设计

4.1 链上数据 API (On-Chain)

4.1.1 MCC Token API

方法端点描述权限
GET/v1/mcc/balance获取当前用户 MCC 余额mcc:read
GET/v1/mcc/balance/{address}获取指定地址 MCC 余额mcc:read:public
GET/v1/mcc/transactions获取当前用户 MCC 交易记录mcc:read
GET/v1/mcc/price获取 MCC 当前价格(预言机备用来源)公开
POST/v1/mcc/price设置管理员价格(预言机备用来源)mcc:admin
GET/v1/mcc/stats获取 MCC 全局统计公开

价格预言机架构: 详见 Section 16

/v1/mcc/price 端点说明:

  • 作为价格预言机服务的备用来源(优先级 2)
  • 当 Pyth 市场价格不可用时,预言机服务读取此端点的管理员价格
  • POST 端点仅限管理员设置价格,用于市场异常时的人工干预

4.1.2 MCD Token API

方法端点描述权限
GET/v1/mcd/balance获取当前用户 MCD 余额mcd:read
GET/v1/mcd/transactions获取 MCD 交易记录mcd:read
GET/v1/mcd/rewards获取 MCD 每日奖励记录mcd:read
GET/v1/mcd/stats获取 MCD 全局统计公开

4.2 链下数据 API (Off-Chain)

4.2.1 用户 API

方法端点描述权限
GET/v1/users/me获取当前用户信息user:read
GET/v1/users/me/profile获取用户详细资料user:read
PATCH/v1/users/me/profile更新用户资料 (display_name)user:write
POST/v1/users/me/avatar上传用户头像user:write
GET/v1/users/{uid}获取指定用户公开信息user:read:public

4.2.2 组织 API

方法端点描述权限
GET/v1/organizations获取组织列表org:read
GET/v1/organizations/{id}获取组织详情org:read
GET/v1/organizations/{id}/members获取组织成员org:read

4.2.3 铸造 API

方法端点描述权限
GET/v1/mining/records获取铸造记录mining:read
GET/v1/mining/stats获取铸造统计mining:read

4.2.4 科技树 API (2026-02-01 新增)

方法端点描述权限
GET/v1/tech-tree/config获取科技树配置公开
GET/v1/tech-tree/user获取用户科技树进度org:read
GET/v1/tech-tree/bonus获取用户科技树加成org:read
POST/v1/tech-tree/unlock解锁科技树节点org:read
POST/v1/tech-tree/upgrade升级科技树节点org:read

科技树加成用途:

  • Double Helix 等项目用于计算用户铸造加成
  • 返回 bonus_multiplier 字段,直接用于铸造产出计算
  • 示例:bonus_multiplier = 1.15 表示用户有 15% 的加成

科技树 KPI 规则:

配置项说明
满员率阈值> 90%Station 成员 ≥ 900/1000
人均铸造阈值≥ 20 USDC/天当日 Station 成员人均铸造投入
达标窗口30 天统计最近 30 天 KPI
点亮条件≥ 21 天达标30 天内满足两个 KPI 条件的天数

科技树加成配置:

单位类型加成累加后点亮条件
Station+10%10%自身 KPI ≥ 21天达标
Matrix+20%30%所辖 Station 平均达标天数 ≥ 21
Sector+30%60%所辖 Station 平均达标天数 ≥ 21
System+40%100%所辖 Station 平均达标天数 ≥ 21

CronJob: tech-tree-daily-update

  • 执行时间: UTC 00:30 (北京时间 08:30)
  • 配置文件: k8s/tech-tree-update-cronjob.yaml
  • 执行流程:
    1. 计算每个 Station 的每日 KPI(满员率、人均铸造)
    2. 记录到 unit_kpi_daily
    3. 更新所有单位的科技树状态
    4. 更新用户铸造加成缓存 (user_mining_bonus_cache)

5. 认证与授权

5.1 OAuth 2.0 Scopes

Scope描述
openidOpenID Connect 基础
profile用户基本信息
email用户邮箱
mcc:read读取 MCC 余额和交易
mcd:read读取 MCD 余额和交易
user:read读取用户信息
user:write更新用户资料 (display_name, avatar)
org:read读取组织信息
mining:read读取铸造记录

5.2 Token 获取流程

1. 外部项目在 Microcosm Developer Portal 注册应用 2. 获取 client_id 和 client_secret (机密客户端) 或仅 client_id (公共客户端, 需使用 PKCE) 3. 用户授权后获取 access_token 4. 使用 Bearer Token 调用 API

5.3 请求示例

bash
# 获取 MCD 余额
curl -X GET "https://api.microcosm.money/v1/mcd/balance" \
  -H "Authorization: Bearer {access_token}" \
  -H "Accept: application/json"

5.4 响应格式 (JSON:API 规范)

成功响应:

json
{
  "data": {
    "type": "mcd_balance",
    "id": "user_123",
    "attributes": {
      "total_balance": "1250.50",
      "available_balance": "1200.00",
      "frozen_balance": "50.50",
      "updated_at": "2026-01-08T10:30:00Z"
    }
  },
  "meta": {
    "request_id": "req_abc123",
    "api_version": "v1"
  }
}

错误响应 (RFC 7807):

json
{
  "type": "https://api.microcosm.money/errors/insufficient-scope",
  "title": "Insufficient Scope",
  "status": 403,
  "detail": "The access token does not have the 'mcd:read' scope required for this endpoint.",
  "instance": "/v1/mcd/balance"
}

6. 速率限制

6.1 限制策略

客户端类型限制窗口
免费开发者100 请求每分钟
标准项目1,000 请求每分钟
企业项目10,000 请求每分钟

6.2 响应头

X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 998 X-RateLimit-Reset: 1704700800 Retry-After: 60 (仅在限制时返回)

6.3 超限响应

json
{
  "type": "https://api.microcosm.money/errors/rate-limit-exceeded",
  "title": "Rate Limit Exceeded",
  "status": 429,
  "detail": "You have exceeded the rate limit of 1000 requests per minute.",
  "retry_after": 45
}

7. 实施计划

Phase 1: 基础设施 ✅ 完成

任务描述产出状态
1.1 域名配置配置 api.microcosm.money DNSA 记录指向 Gateway
1.2 SSL 证书申请 Google Managed Certificate自动续期证书
1.3 Gateway 配置创建 HTTPRoute for Open API路由配置
1.4 open-api-service创建新服务作为统一入口服务代码 + Dockerfile

Phase 2: 核心 API ✅ 完成

任务描述产出状态
2.1 MCC API实现 MCC 余额/交易接口API 端点
2.2 MCD API实现 MCD 余额/奖励接口API 端点
2.3 用户 API实现用户信息接口API 端点
2.4 组织 API实现组织/单位信息接口API 端点
2.5 铸造 API实现铸造记录/统计接口API 端点
2.6 OpenAPI 文档生成 OpenAPI 3.1 规范文档openapi.yaml

Phase 3: 安全加固 ✅ 完成

任务描述产出状态
3.1 Scope 验证实现 OAuth Scope 校验中间件权限控制代码
3.2 Rate Limiting实现基于 Redis 的速率限制限流中间件
3.3 请求日志实现 API 调用审计日志日志系统

Phase 4: 开发者体验 (优先级: 中) ⏳ 待实施

任务描述产出状态
4.1 Developer Portal创建开发者注册/管理页面前端页面
4.2 API 文档站部署交互式 API 文档Swagger UI / Redoc
4.3 SDK 生成自动生成 Python/TypeScript SDKSDK 包

Phase 5: 交易类 API (优先级: 高) ✅ 代码实施完成

详细架构设计见 Section 13

任务描述产出状态
5.1 铸造提交 API实现 /v1/mining/submit-activityAPI 端点
5.2 资金管理 API实现 /v1/funds/* 系列端点 (冻结/解冻/转账)API 端点
5.3 转账请求 API实现 /v1/transfer/* 系列端点API 端点
5.4 Webhook 系统实现 Webhook 注册、签名验证、异步发送Webhook 服务
5.5 项目注册实现项目管理 API 及权限配置管理端点
5.6 审计日志实现交易审计系统 (transaction_audit_log 表)数据库表 + 日志
5.7 限额控制实现单次/每日操作限额检查中间件
5.8 幂等性控制实现 idempotency_key 机制防重放中间件

Phase 6: 用户画像 API (优先级: 中) ✅ 代码实施完成

详细架构设计见 Section 15

任务描述产出状态
6.1 用户基础画像 API实现 /v1/users/{uid}/profileAPI 端点
6.2 项目属性查询 API实现 /v1/users/{uid}/projects/{project_id}/attributesAPI 端点
6.3 完整画像聚合 API实现 /v1/users/{uid}/full-profileAPI 端点
6.4 项目状态查询 API实现 /v1/projects/{project_id}/statusAPI 端点
6.5 项目属性上报 API实现 POST /v1/users/{uid}/attributesAPI 端点
6.6 属性删除 API实现 DELETE /v1/users/{uid}/attributesAPI 端点
6.7 批量属性查询 API实现 POST /v1/users/batch/attributesAPI 端点
6.8 数据库表创建 user_project_attributes, project_status_history数据库表

Phase 7: Solana 合约 API (优先级: 高) ✅ 代码实施完成

为第三方项目提供 Solana 链上合约的只读查询接口

任务描述产出状态
7.1 Territory NFT API实现 /v1/territory/* 系列端点 (4 个)API 端点
7.2 Auction Solana API实现 /v1/auction-solana/* 系列端点 (6 个)API 端点
7.3 Fragment API实现 /v1/fragment/* 系列端点 (5 个)API 端点
7.4 Lending API实现 /v1/lending/* 系列端点 (8 个)API 端点

端点详情:

模块端点方法说明
Territory NFT/v1/territory/collectionGET获取 Collection 配置
/v1/territory/nft/{mint}GET获取 NFT 元数据
/v1/territory/nfts/{wallet}GET获取用户 NFT 列表
/v1/territory/unit/{unit_id}/nftGET获取单位关联 NFT
Auction Solana/v1/auction-solana/configGET获取拍卖配置
/v1/auction-solana/activeGET获取活跃拍卖列表
/v1/auction-solana/auction/{id}GET获取拍卖详情
/v1/auction-solana/auction/{id}/bidsGET获取竞价历史
/v1/auction-solana/bids/{wallet}GET获取用户竞价记录
/v1/auction-solana/auctions/{wallet}GET获取用户创建的拍卖
Fragment/v1/fragment/configGET获取碎片化配置
/v1/fragment/vaultsGET获取所有 Vault 列表
/v1/fragment/vault/{id}GET获取 Vault 详情
/v1/fragment/vault/{id}/holdersGET获取 Vault 持仓分布
/v1/fragment/holdings/{wallet}GET获取用户持仓
Lending/v1/lending/poolGET获取借贷池配置
/v1/lending/statsGET获取借贷池统计
/v1/lending/position/{wallet}GET获取用户仓位
/v1/lending/loans/{wallet}GET获取用户贷款列表
/v1/lending/loan/{wallet}/{loan_id}GET获取贷款详情
/v1/lending/lp-balance/{wallet}GET获取 LP Token 余额
/v1/lending/calculate-interestPOST计算利息
/v1/lending/estimate-borrow-costPOST估算借款成本

8. 技术栈选型

8.1 open-api-service 技术栈

组件选择理由
框架FastAPI自动 OpenAPI 生成,高性能
运行时Uvicorn + Gunicorn生产级 ASGI 服务器
缓存Redis速率限制 + 响应缓存
日志Structlog + Cloud Logging结构化日志

8.2 部署架构

yaml
# open-api-service 部署
apiVersion: apps/v1
kind: Deployment
metadata:
  name: open-api-service
  namespace: microcosm
spec:
  replicas: 2  # HA 部署
  template:
    spec:
      containers:
      - name: open-api-service
        image: asia-northeast1-docker.pkg.dev/microcosm/microcosm/open-api-service:v1.0.0
        resources:
          requests:
            cpu: 200m
            memory: 256Mi
          limits:
            cpu: 500m
            memory: 512Mi

9. Double Helix 接入示例

9.1 更新后的 API 调用

typescript
// frontend-service/lib/api/services.ts

const MICROCOSM_API_BASE = 'https://api.microcosm.money/v1'

export async function getMCDBalance(): Promise<APIResponse<MCDBalanceType>> {
  const token = getAccessToken()
  const response = await fetch(`${MICROCOSM_API_BASE}/mcd/balance`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Accept': 'application/json'
    }
  })
  return response.json()
}

export async function getMCDTransactions(params?: MCDHistoryParams): Promise<APIResponse<MCDTransaction[]>> {
  const token = getAccessToken()
  const queryString = new URLSearchParams(params as any).toString()
  const response = await fetch(`${MICROCOSM_API_BASE}/mcd/transactions?${queryString}`, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Accept': 'application/json'
    }
  })
  return response.json()
}

9.2 无需修改 api-gateway

由于直接调用 Microcosm Open API,不再需要在 Double Helix api-gateway 中添加代理路由。


10. 安全考虑

10.1 威胁模型

威胁缓解措施
Token 泄露短 TTL (1小时) + Refresh Token 轮换
API 滥用Rate Limiting + 异常检测
数据泄露TLS 1.3 强制 + 最小权限原则
CSRFSameSite Cookie + CORS 严格策略

10.2 CORS 配置

python
# open-api-service CORS 配置
ALLOWED_ORIGINS = [
    "https://doublehelix.money",
    "https://www.doublehelix.money",
    "https://poly.microcosm.money",
    "https://microcosm.money",
    # 开发环境
    "http://localhost:3000",
    "http://localhost:3001",
]

11. 监控与告警

11.1 关键指标

指标阈值告警
API 延迟 P99> 500ms警告
API 延迟 P99> 1000ms严重
错误率> 1%警告
错误率> 5%严重
Rate Limit 触发率> 10%警告

11.2 Grafana Dashboard

创建专用 Open API 监控面板,包含:

  • 请求量 (QPS)
  • 延迟分布
  • 错误分类
  • 调用者分布
  • Rate Limit 统计

12. 审核清单

请确认以下事项后批准实施:

  • API 端点设计是否满足业务需求
  • OAuth Scope 划分是否合理
  • Rate Limit 限制是否合适
  • 实施阶段优先级是否正确
  • 安全措施是否充分
  • 是否需要添加其他 API 端点

附录 A: OpenAPI 规范示例

yaml
openapi: 3.1.0
info:
  title: Microcosm Open API
  version: 1.0.0
  description: Public API for Microcosm ecosystem

servers:
  - url: https://api.microcosm.money/v1
    description: Production

security:
  - oauth2: []

paths:
  /mcd/balance:
    get:
      summary: Get MCD Balance
      operationId: getMCDBalance
      security:
        - oauth2: [mcd:read]
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MCDBalanceResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'

components:
  securitySchemes:
    oauth2:
      type: oauth2
      flows:
        authorizationCode:
          authorizationUrl: https://auth.microcosm.money/oauth/authorize
          tokenUrl: https://auth.microcosm.money/oauth/token
          scopes:
            mcd:read: Read MCD balance and transactions
            mcc:read: Read MCC balance and transactions
            user:read: Read user profile
            org:read: Read organization information
            mining:read: Read mining records and stats

附录 B: 实施记录

2026-01-09 Phase 1-3 实施完成

实施内容:

  1. OAuth Scope 验证中间件 (dependencies.py)

    • 实现 RequireScope 类,支持多 scope 验证
    • 预定义验证器: require_mcc_read, require_mcd_read, require_user_read, require_org_read, require_mining_read
    • 管理员角色自动拥有所有权限
    • Token 内省结果缓存 (5分钟 TTL)
  2. Redis Rate Limiting (rate_limiter.py)

    • 滑动窗口算法实现
    • 支持按 Token/API Key/IP 识别客户端
    • Redis 不可用时自动降级到内存存储
    • 配置: 默认 100 请求/分钟
  3. 请求审计日志 (audit_logger.py)

    • 使用 structlog 输出结构化 JSON 日志
    • 记录: 请求方法、路径、客户端 IP、延迟、状态码
    • 自动添加 X-Request-ID 响应头
    • 安全事件专用日志函数
  4. 组织 API (routers/organizations.py)

    • GET /v1/organizations - 获取组织列表
    • GET /v1/organizations/{id} - 获取组织详情
    • GET /v1/organizations/{id}/members - 获取组织成员
    • GET /v1/organizations/{id}/stats - 获取组织统计 (公开)
  5. 铸造 API (routers/mining.py)

    • GET /v1/mining/records - 获取铸造记录
    • GET /v1/mining/stats - 获取个人铸造统计
    • GET /v1/mining/global-stats - 获取全局铸造统计 (公开)

新增文件:

  • fastapi_app/rate_limiter.py - Redis 速率限制器
  • fastapi_app/audit_logger.py - 审计日志系统
  • fastapi_app/routers/organizations.py - 组织 API
  • fastapi_app/routers/mining.py - 铸造 API
  • k8s/redis.yaml - Redis 部署配置

更新文件:

  • fastapi_app/dependencies.py - 添加 Scope 验证
  • fastapi_app/main.py - 注册新中间件和路由
  • fastapi_app/routers/mcc.py - 添加 Scope 验证
  • fastapi_app/routers/mcd.py - 添加 Scope 验证
  • fastapi_app/routers/users.py - 添加 Scope 验证
  • requirements.txt - 添加 redis, structlog 依赖
  • k8s/deployment.yaml - 添加 REDIS_URL 环境变量

部署步骤:

bash
# 1. 部署 Redis
kubectl apply -f services/open-api-service/k8s/redis.yaml

# 2. 构建并部署 open-api-service
cd services/open-api-service
gcloud builds submit --config=cloudbuild.yaml --region=asia-northeast1 \
  --substitutions=_IMAGE_URI=<registry>/<project>/open-api-service:<version> .

# 3. 更新部署
kubectl set image deploy/open-api-service \
  open-api-service=<registry>/<project>/open-api-service:<version> \
  -n microcosm

2026-01-10 部署完成

部署状态:

组件版本状态副本数
Redis7-alpine✅ Running1
open-api-servicev1.1.1✅ Running2

已上线 API 端点:

分类端点权限
MCC/v1/mcc/balancemcc:read
MCC/v1/mcc/balance/{address}公开
MCC/v1/mcc/transactionsmcc:read
MCC/v1/mcc/price公开
MCC/v1/mcc/stats公开
MCD/v1/mcd/balancemcd:read
MCD/v1/mcd/transactionsmcd:read
MCD/v1/mcd/rewardsmcd:read
MCD/v1/mcd/stats公开
Users/v1/users/meuser:read
Users/v1/users/me/profileuser:read
UsersPATCH /v1/users/me/profileuser:write
UsersPOST /v1/users/me/avataruser:write
Users/v1/users/{uid}公开
Organizations/v1/organizationsorg:read
Organizations/v1/organizations/{org_id}org:read
Organizations/v1/organizations/{org_id}/membersorg:read
Organizations/v1/organizations/{org_id}/stats公开
Mining/v1/mining/recordsmining:read
Mining/v1/mining/statsmining:read
Mining/v1/mining/global-stats公开

访问地址:

修复记录:

  • v1.1.1: 修复 audit_logger.py 中 structlog 事件参数冲突问题

文档状态: ✅ Phase 1-3 已部署上线,Phase 4-5 待实施


13. Phase 5: 交易类 API 架构设计 (优先级: 高)

核心原则: Microcosm 是唯一的链上数据控制者,所有资产操作必须通过 Microcosm API 执行。

13.1 架构原则

Microcosm 作为链上数据的唯一控制者:

原则说明
1. 所有资产操作必须通过 Microcosm API第三方项目不能直接操作链上数据,只能请求 Microcosm 执行操作
2. 资金验证由 Microcosm 负责检查用户余额是否足够、冻结/解冻资金、验证交易证明
3. 链上写入只有 Microcosm 有私钥MCC Token Mint/Transfer、MCD 奖励发放、交易记录上链
4. 异步确认通过 Webhook 通知链上交易确认后回调第三方项目、状态更新通知

13.2 数据流架构

参与方:

参与方包含
外部项目Double Helix、Event Horizon、第三方项目
Microcosm 内部open-api-service、blockchain-service、PostgreSQL、Webhook Service
链上Solana Chain (MCC Token、交易记录)

数据流:

  1. 请求阶段: 外部项目发送请求到 open-api-service (验证权限、验证签名、速率限制)
  2. 同步响应: open-api-service 返回 {status: "pending"},同时将请求转发给 blockchain-service (余额检查、冻结资金、链上写入)
  3. 链上处理: blockchain-service 与 Solana Chain 交互,结果写入 PostgreSQL (pending_transactions、mining_activities、locked_funds)
  4. 异步回调: 链上确认后,Webhook Service 向外部项目发送回调通知

13.3 交易类 API 端点设计

13.3.1 铸造活动 API

方法端点描述权限
POST/v1/mining/submit-activity提交铸造活动mining:write
GET/v1/mining/activity/{id}查询活动状态mining:read
POST/v1/mining/batch-submit批量提交活动mining:write

请求示例 - 提交铸造活动:

json
POST /v1/mining/submit-activity
Authorization: Bearer {project_access_token}
X-Project-ID: double_helix

{
  "user_uid": "Drt0n1i6y1UVF8wqydT3ckQewM22",
  "activity_type": "trading",
  "activity_data": {
    "trade_volume_usdc": 10000,
    "trade_count": 15,
    "profit_usdc": 250
  },
  "proof": {
    "type": "signed_hash",
    "hash": "0x...",
    "signature": "...",
    "timestamp": "2026-01-10T12:00:00Z"
  },
  "idempotency_key": "dh-2026-01-10-user123-batch1"
}

响应:

json
{
  "data": {
    "type": "mining_activity",
    "id": "act_abc123",
    "attributes": {
      "status": "pending_verification",
      "mcd_estimated": "50.00",
      "created_at": "2026-01-10T12:00:01Z"
    }
  },
  "meta": {
    "webhook_url": "Will notify when confirmed"
  }
}

13.3.2 资金管理 API

方法端点描述权限
POST/v1/funds/lock冻结用户资金funds:manage
POST/v1/funds/unlock解冻用户资金funds:manage
POST/v1/funds/transfer项目内转账funds:transfer
GET/v1/funds/locked/{user_uid}查询冻结资金funds:read

请求示例 - 冻结资金(拍卖出价):

json
POST /v1/funds/lock
Authorization: Bearer {project_access_token}
X-Project-ID: event_horizon

{
  "user_uid": "user123",
  "currency": "MCC",
  "amount": "100.00",
  "reason": "auction_bid",
  "reference_id": "auction_456",
  "expires_at": "2026-01-11T00:00:00Z",
  "idempotency_key": "eh-auction-456-bid-user123"
}

响应:

json
{
  "data": {
    "type": "fund_lock",
    "id": "lock_xyz789",
    "attributes": {
      "status": "locked",
      "user_uid": "user123",
      "currency": "MCC",
      "amount": "100.00",
      "available_balance": "900.00",
      "locked_until": "2026-01-11T00:00:00Z"
    }
  }
}

13.3.3 转账请求 API

方法端点描述权限
POST/v1/transfer/request发起转账请求transfer:write
GET/v1/transfer/{id}查询转账状态transfer:read
POST/v1/transfer/{id}/cancel取消转账transfer:write

请求示例 - 拍卖结算转账:

json
POST /v1/transfer/request
Authorization: Bearer {project_access_token}
X-Project-ID: event_horizon

{
  "transfer_type": "auction_settlement",
  "from_uid": "bidder_user",
  "to_uid": "seller_user",
  "currency": "MCC",
  "amount": "100.00",
  "reference": {
    "auction_id": "auction_456",
    "item_id": "item_789"
  },
  "requires_onchain": true,
  "idempotency_key": "eh-auction-456-settlement"
}

13.4 Webhook 回调机制

13.4.1 Webhook 事件类型

事件描述触发时机
mining.activity.verified铸造活动已验证活动验证通过
mining.reward.confirmed铸造奖励已确认链上交易确认
funds.locked资金已冻结冻结操作完成
funds.unlocked资金已解冻解冻操作完成
transfer.completed转账已完成链上交易确认
transfer.failed转账失败交易被拒绝

13.4.2 Webhook 注册

json
POST /v1/webhooks/register
Authorization: Bearer {project_access_token}

{
  "url": "https://doublehelix.money/api/webhooks/microcosm",
  "events": ["mining.reward.confirmed", "transfer.completed"],
  "secret": "whsec_xxx..."
}

13.4.3 Webhook 请求格式

json
POST https://doublehelix.money/api/webhooks/microcosm
X-Microcosm-Signature: sha256=xxx...
X-Microcosm-Event: mining.reward.confirmed
X-Microcosm-Delivery: evt_123

{
  "id": "evt_abc123",
  "type": "mining.reward.confirmed",
  "created_at": "2026-01-10T12:05:00Z",
  "data": {
    "activity_id": "act_abc123",
    "user_uid": "Drt0n1i6y1UVF8wqydT3ckQewM22",
    "mcd_amount": "50.00",
    "tx_signature": "5xyz...abc",
    "block_height": 12345678
  }
}

13.4.4 签名验证

python
import hmac
import hashlib

def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        payload,
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(f"sha256={expected}", signature)

13.5 项目级权限模型

13.5.1 项目注册

json
POST /v1/projects/register
Authorization: Bearer {admin_token}

{
  "project_id": "double_helix",
  "name": "Double Helix Trading",
  "description": "Quantitative trading platform",
  "webhook_url": "https://doublehelix.money/api/webhooks/microcosm",
  "allowed_scopes": [
    "mining:write",
    "mining:read",
    "funds:read"
  ],
  "rate_limit_tier": "standard"
}

13.5.2 项目 Scopes

Scope描述适用场景
mining:write提交铸造活动Double Helix
funds:manage冻结/解冻资金Event Horizon 拍卖
funds:transfer项目内转账Event Horizon 结算
transfer:write发起转账请求所有需要转账的项目
auction:manage管理拍卖Event Horizon

13.5.3 权限继承

Token 类型权限范围
用户 Token (OAuth)用户级权限: mcc:read, mcd:read, user:read
项目 Token (API Key)项目级权限: mining:write, funds:manage;只能操作该项目的用户数据

13.6 安全模型

13.6.0 核心安全原则 ⚠️ 重要

零信任安全模型 - Microcosm 是链上数据的唯一控制者:

#原则详细说明
1Microcosm 持有所有 Authority 密钥MCC Token Mint Authority、MCD Token Mint Authority、Territory NFT Mint Authority、所有 PDA 控制权
2项目开发者没有任何链上写入能力项目不能直接调用 Solana 合约,不能持有任何 Authority 密钥,只能通过 Microcosm API 请求执行操作
3Microcosm 不信任项目传入的数据项目声称"用户已充值 100 USDC" -- Microcosm 必须链上验证;项目声称"铸造活动有效" -- 必须独立验证交易证明;项目声称"资金已到账" -- 必须确认链上交易状态
4资金到账必须链上确认充值: 监听链上 Transfer 事件确认到账后才记入账户;铸造奖励: Microcosm 自己发起 Mint,不接受项目"已发放"声明;转账: 必须等待链上交易 finalized 才确认成功
5每笔交易必须有唯一 ID (防止重复提交)idempotency_key: 项目必须为每个操作提供唯一标识;24 小时内同一 key 只能使用一次;防止网络抖动导致的重复请求
6项目必须使用 API 签名请求头包含 X-Project-Signature;使用 HMAC-SHA256 签名请求体;验证失败直接拒绝请求
7所有敏感操作有审计日志记录: 项目 ID、用户 UID、操作类型、请求/响应、时间戳;日志不可篡改 (Cloud Logging + BigQuery 归档);支持事后审计和异常检测

13.6.1 API 签名验证

所有交易类 API 请求必须携带签名,用于验证请求来源和防止篡改。

请求头:

X-Project-ID: double_helix X-Timestamp: 1704700800 X-Signature: sha256=abc123...

签名生成算法:

python
import hmac
import hashlib
import json
import time

def generate_signature(api_secret: str, method: str, path: str, body: dict, timestamp: int) -> str:
    """
    生成 API 请求签名

    签名格式: HMAC-SHA256(secret, method + path + timestamp + body_json)
    """
    body_json = json.dumps(body, separators=(',', ':'), sort_keys=True)
    payload = f"{method}\n{path}\n{timestamp}\n{body_json}"
    signature = hmac.new(
        api_secret.encode(),
        payload.encode(),
        hashlib.sha256
    ).hexdigest()
    return f"sha256={signature}"


# 使用示例
signature = generate_signature(
    api_secret="whsec_xxx...",
    method="POST",
    path="/v1/mining/submit-activity",
    body={"user_uid": "user123", "activity_type": "trading", ...},
    timestamp=int(time.time())
)

服务端验证:

python
def verify_signature(request) -> bool:
    project_id = request.headers.get("X-Project-ID")
    timestamp = int(request.headers.get("X-Timestamp", 0))
    signature = request.headers.get("X-Signature", "")

    # 1. 时间戳验证 (5分钟窗口)
    if abs(time.time() - timestamp) > 300:
        return False

    # 2. 获取项目密钥
    api_secret = get_project_secret(project_id)
    if not api_secret:
        return False

    # 3. 重新计算签名
    expected = generate_signature(
        api_secret=api_secret,
        method=request.method,
        path=request.path,
        body=request.json(),
        timestamp=timestamp
    )

    # 4. 常量时间比较
    return hmac.compare_digest(expected, signature)

13.6.2 防重放攻击

  • 幂等键 (Idempotency Key): 所有写入操作必须携带
  • 时间窗口: 请求时间戳与服务器时间差不超过 5 分钟
  • Nonce 检查: 同一幂等键 24 小时内不可重复使用

幂等键使用:

python
# Redis 存储已使用的 idempotency_key
def check_idempotency(key: str) -> bool:
    """返回 True 表示该 key 首次使用,False 表示重复"""
    result = redis.set(f"idempotency:{key}", "1", nx=True, ex=86400)  # 24小时过期
    return result is not None

13.6.3 操作审计

sql
-- 所有交易类操作记录
CREATE TABLE transaction_audit_log (
    id SERIAL PRIMARY KEY,
    project_id VARCHAR(50) NOT NULL,
    operation_type VARCHAR(50) NOT NULL,  -- 'mining_submit', 'funds_lock', 'transfer'
    user_uid VARCHAR(100) NOT NULL,
    request_body JSONB NOT NULL,
    response_body JSONB,
    status VARCHAR(20) NOT NULL,  -- 'success', 'failed', 'pending'
    idempotency_key VARCHAR(100) UNIQUE,
    ip_address INET,
    created_at TIMESTAMP DEFAULT NOW()
);

13.6.3 限额控制

操作单次限额每日限额适用项目
铸造提交1000 MCD10000 MCDDouble Helix
资金冻结10000 MCC100000 MCCEvent Horizon
转账请求5000 MCC50000 MCC所有项目

13.7 实施任务

任务描述产出状态
5.1 铸造提交 API实现 /v1/mining/submit-activityAPI 端点
5.2 资金管理 API实现 /v1/funds/* 系列端点API 端点
5.3 转账请求 API实现 /v1/transfer/* 系列端点API 端点
5.4 Webhook 系统实现 Webhook 注册和发送Webhook 服务
5.5 项目注册实现项目管理 API管理端点
5.6 审计日志实现交易审计系统数据库表 + 日志
5.7 限额控制实现操作限额检查中间件

13.8 第三方项目接入流程

  1. 项目注册: 在 Microcosm Developer Portal 注册项目,获取 project_id 和 api_secret,配置 Webhook URL
  2. 配置权限: 申请所需 Scopes (需审核),设置 IP 白名单 (可选),配置限额 (可选)
  3. 集成开发: 使用 SDK 或直接调用 API,实现 Webhook 接收端点,实现签名验证
  4. 测试验证: 使用沙箱环境测试,验证 Webhook 接收,验证错误处理
  5. 上线: 切换到生产环境,监控 API 调用状态

14. 场景示例

14.1 Double Helix 铸造场景

参与方: Double Helix (策略 Pod) / Microcosm Open API / Solana Chain

步骤发送方接收方操作
1-Double Helix用户完成一笔交易,profit = 250 USDC
2Double HelixMicrocosmPOST /v1/mining/submit-activity { user_uid, trade_volume, proof }
3-Microcosm验证项目权限
4-Microcosm验证交易证明
5-Microcosm计算 MCD 奖励: 50 MCD
6MicrocosmDouble Helix返回 { status: "pending_onchain" }
7MicrocosmSolana调用 blockchain-service,Mint 50 MCD to user
8SolanaMicrocosm返回 tx_signature
9MicrocosmDouble HelixWebhook: mining.reward.confirmed { mcd_amount: 50, tx_sig: ... }

14.2 Event Horizon 拍卖场景

参与方: Event Horizon (预测市场) / Microcosm Open API / Solana Chain

用户出价阶段:

步骤发送方接收方操作
1Event HorizonMicrocosmPOST /v1/funds/lock { user_uid, amount: 100 MCC, reason: "auction_bid" }
2-Microcosm检查余额
3-Microcosm冻结 100 MCC
4MicrocosmEvent Horizon返回 { status: "locked" }

拍卖进行中,可能有多次出价...

拍卖结束阶段:

步骤发送方接收方操作
5Event HorizonMicrocosmPOST /v1/transfer/request { from: bidder, to: seller, amount: 100 MCC }
6-Microcosm验证冻结资金
7MicrocosmSolana解冻 + Transfer on-chain
8SolanaMicrocosm链上确认
9MicrocosmEvent HorizonWebhook: transfer.completed { tx_signature: ... }
10Event HorizonMicrocosmPOST /v1/funds/unlock { lock_id: ..., reason: "outbid" }
11-Microcosm解冻落选者资金
12MicrocosmEvent Horizon返回 { status: "unlocked" }

15. Phase 6: 用户画像 API 架构设计

核心理念: Microcosm 作为用户档案中心,聚合所有项目的用户属性数据,提供跨项目的用户画像查询能力。

15.1 用户角色模型

Microcosm 生态中有三种角色类型:

角色范围来源说明
Microcosm 角色全局Microcosm 核心系统admin, unit_manager, unit_member, user
项目角色项目内各项目系统如 Double Helix 的 trader, Event Horizon 的 bettor
组织角色组织内组织系统组织内的职位和权限

15.2 属性累积模型

用户属性累积模型

示例用户 UID: Drt0n1i6y1UVF8wqydT3ckQewM22

Microcosm 基础属性 (全局可见):

属性示例值
emailuser@example.com
displayName"用户昵称"
role"unit_member"
mcc_balance1000.00
mcd_balance5000.00
created_at"2024-01-15"

Double Helix 属性 (项目私有,需授权访问):

属性示例值
project_role"trader"
total_trade_volume150000.00
total_profit3500.00
active_strategies3
risk_level"medium"
last_trade_at"2026-01-09"

Event Horizon 属性 (项目私有,需授权访问):

属性示例值
project_role"bettor"
total_bets45
win_rate0.62
prediction_accuracy0.71
badges["early_adopter", "prediction_master"]

15.3 属性可见性规则

属性类型可见性说明
Microcosm 基础属性公开所有已登录用户可查询任意用户的基础信息
项目属性 (visibility=public)公开项目设置为公开的属性,任何人可查询
项目属性 (visibility=private)私有仅用户本人和该项目可查询
项目属性 (visibility=authorized)授权用户授权的项目可查询

15.4 API 端点设计

15.4.1 读取类 API (OAuth Token 认证)

方法端点描述权限
GET/v1/users/{uid}/profile获取用户 Microcosm 基础画像user:read
GET/v1/users/{uid}/projects/{project_id}/attributes获取用户在特定项目的属性user:read + 可见性检查
GET/v1/users/{uid}/full-profile获取用户完整画像 (含所有可见项目属性)user:read

15.4.2 写入类 API (项目签名认证)

方法端点描述权限
POST/v1/users/{uid}/attributes项目上报用户属性项目签名
DELETE/v1/users/{uid}/attributes项目删除用户属性项目签名
POST/v1/users/batch/attributes批量查询用户属性项目签名

15.4.3 公开 API (无需认证)

方法端点描述权限
GET/v1/projects/{project_id}/status获取项目状态公开

15.5 数据库设计

sql
-- 用户项目属性表
CREATE TABLE user_project_attributes (
    id SERIAL PRIMARY KEY,
    uid VARCHAR(100) NOT NULL,                    -- 用户 UID
    project_id VARCHAR(50) NOT NULL,              -- 项目 ID
    attribute_key VARCHAR(100) NOT NULL,          -- 属性键
    attribute_value JSONB NOT NULL,               -- 属性值 (支持复杂结构)
    visibility VARCHAR(20) DEFAULT 'private',     -- public/private/authorized
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW(),
    UNIQUE(uid, project_id, attribute_key)
);

-- 项目状态历史表
CREATE TABLE project_status_history (
    id SERIAL PRIMARY KEY,
    project_id VARCHAR(50) NOT NULL,
    status VARCHAR(20) NOT NULL,                  -- active/maintenance/testing/discontinued/deleted
    reason TEXT,
    changed_by VARCHAR(100),                      -- 操作者 UID
    created_at TIMESTAMP DEFAULT NOW()
);

-- 索引
CREATE INDEX idx_user_project_attrs_uid ON user_project_attributes(uid);
CREATE INDEX idx_user_project_attrs_project ON user_project_attributes(project_id);
CREATE INDEX idx_project_status_history ON project_status_history(project_id, created_at DESC);

15.6 项目状态生命周期

  • active (正常运营) --> maintenance (维护中) --> 可恢复为 active
  • active (正常运营) --> testing (测试中) --> 可恢复为 active
  • active (正常运营) --> discontinued (已停运) --> deleted (已删除)
状态说明属性查询属性写入
active正常运营
maintenance临时维护
testing测试阶段
discontinued已停运
deleted已删除

附录 C: Phase 6 实施记录

2026-01-10 Phase 6 实施完成

实施内容:

  1. 用户画像路由 (routers/user_attributes.py)

    • GET /v1/users/{uid}/profile - 获取 Microcosm 基础画像
    • GET /v1/users/{uid}/projects/{project_id}/attributes - 获取项目属性
    • GET /v1/users/{uid}/full-profile - 获取完整画像
    • GET /v1/projects/{project_id}/status - 获取项目状态 (公开)
    • POST /v1/users/{uid}/attributes - 项目上报属性
    • DELETE /v1/users/{uid}/attributes - 删除属性
    • POST /v1/users/batch/attributes - 批量查询
  2. 数据库表初始化

    • user_project_attributes 表 (UPSERT 支持)
    • project_status_history
  3. 权限控制

    • 读取 API: OAuth Token + Scope 验证
    • 写入 API: 项目签名验证
    • 可见性检查: public/private/authorized

新增文件:

  • fastapi_app/routers/user_attributes.py - 用户画像 API

更新文件:

  • fastapi_app/routers/__init__.py - 添加 user_attributes 导入
  • fastapi_app/main.py - 注册新路由和表初始化

部署信息:

  • 镜像: open-api-service:phase6-user-profile
  • 命名空间: microcosm

API 文档:

Phase 6 新增端点:

分类端点权限
User ProfileGET /v1/users/{uid}/profileuser:read
User ProfileGET /v1/users/{uid}/projects/{project_id}/attributesuser:read
User ProfileGET /v1/users/{uid}/full-profileuser:read
User ProfilePOST /v1/users/{uid}/attributes项目签名
User ProfileDELETE /v1/users/{uid}/attributes项目签名
User ProfilePOST /v1/users/batch/attributes项目签名
ProjectGET /v1/projects/{project_id}/status公开


2026-01-15 用户资料写入 API 实施完成

实施内容:

  1. 用户资料更新端点 (routers/users.py)

    • PATCH /v1/users/me/profile - 更新 display_name
    • POST /v1/users/me/avatar - 上传头像图片
  2. 服务间信任机制 (user-service/app/middleware.py)

    • 新增 TRUSTED_INTERNAL_SERVICES 列表
    • 支持 X-Internal-Service + X-User-UID 头部认证
    • 允许 open-api-service 代理用户请求到 user-service
  3. 新增 OAuth Scope

    • user:write - 更新用户资料权限

更新文件:

  • services/open-api-service/fastapi_app/routers/users.py - 添加 PATCH/POST 端点
  • services/open-api-service/fastapi_app/dependencies.py - 添加 require_user_write
  • services/user-service/app/routes/users.py - 添加 /profile PATCH 端点
  • services/user-service/app/database/users.py - 添加 update_display_name 函数
  • services/user-service/app/middleware.py - 添加服务间信任机制

部署版本:

  • user-service: v2.1.8
  • open-api-service: v1.2.0

API 文档:

端点方法权限说明
/v1/users/me/profilePATCHuser:write更新 display_name (1-50字符)
/v1/users/me/avatarPOSTuser:write上传头像 (jpg/png/gif/webp, 最大2MB)

共享用户架构说明:

Microcosm 是统一用户平台,所有第三方项目 (Double Helix, Event Horizon 等) 共享同一用户系统。用户在任意项目更新 display_name 或 avatar 后,所有项目立即生效。

文档状态: ✅ Phase 1-3, 5, 6, 7 已部署上线,Phase 4 待实施


2026-01-16 Phase 7: Solana 合约 API 实施完成

实施内容:

  1. Territory NFT API (routers/territory.py)

    • GET /v1/territory/collection - Collection 配置
    • GET /v1/territory/nft/{mint} - NFT 元数据
    • GET /v1/territory/nfts/{wallet} - 用户 NFT 列表
    • GET /v1/territory/unit/{unit_id}/nft - 单位关联 NFT
  2. Auction Solana API (routers/auction_solana.py)

    • GET /v1/auction-solana/config - 拍卖配置
    • GET /v1/auction-solana/active - 活跃拍卖列表
    • GET /v1/auction-solana/auction/{id} - 拍卖详情
    • GET /v1/auction-solana/auction/{id}/bids - 竞价历史
    • GET /v1/auction-solana/bids/{wallet} - 用户竞价记录
    • GET /v1/auction-solana/auctions/{wallet} - 用户创建的拍卖
  3. Fragment API (routers/fragment.py)

    • GET /v1/fragment/config - 碎片化配置
    • GET /v1/fragment/vaults - 所有 Vault 列表
    • GET /v1/fragment/vault/{id} - Vault 详情
    • GET /v1/fragment/vault/{id}/holders - 持仓分布
    • GET /v1/fragment/holdings/{wallet} - 用户持仓
  4. Lending API (routers/lending.py)

    • GET /v1/lending/pool - 借贷池配置
    • GET /v1/lending/stats - 借贷池统计
    • GET /v1/lending/position/{wallet} - 用户仓位
    • GET /v1/lending/loans/{wallet} - 用户贷款列表
    • GET /v1/lending/loan/{wallet}/{loan_id} - 贷款详情
    • GET /v1/lending/lp-balance/{wallet} - LP Token 余额
    • POST /v1/lending/calculate-interest - 计算利息
    • POST /v1/lending/estimate-borrow-cost - 估算借款成本

新增文件:

  • fastapi_app/routers/territory.py - Territory NFT API
  • fastapi_app/routers/auction_solana.py - Auction Solana API
  • fastapi_app/routers/fragment.py - Fragment API
  • fastapi_app/routers/lending.py - Lending API

更新文件:

  • fastapi_app/main.py - 注册 4 个新路由
  • requirements.txt - 无新增依赖

部署版本:

  • open-api-service: v1.1.0

API 统计:

  • 新增端点: 23 个
  • 总端点数: 约 50 个

2026-01-18 Open API Scope 别名映射修复

问题描述:

非 admin 角色用户(如 miner)在 Double Helix 前端无法显示头像和昵称,admin 用户正常。

根因分析:

  1. Open API 返回 403: /v1/users/me/profile 端点需要 user:read scope
  2. Double Helix OAuth token scope: "openid profile email trading" - 没有 user:read
  3. admin 用户正常: RequireScope 类对 admin 角色自动跳过 scope 检查
  4. 共享模块缺失字段: microcosm_common/users/repository.pyget_user_by_uid 未返回 display_nameavatar_url

修复内容:

修复 1: Open API Scope 别名映射 (fastapi_app/dependencies.py)

python
class RequireScope:
    # OpenID Connect 标准 scope 到 Microcosm scope 的映射
    SCOPE_ALIASES = {
        "profile": {"user:read"},  # OIDC profile scope 等同于 user:read
    }

    async def __call__(self, request: Request) -> UserInfo:
        user = await verify_oauth_token(request)
        user_scopes = set(user.scopes)

        # 展开 scope 别名 (OpenID Connect 兼容)
        expanded_scopes = set(user_scopes)
        for scope in user_scopes:
            if scope in self.SCOPE_ALIASES:
                expanded_scopes.update(self.SCOPE_ALIASES[scope])

        # 管理员角色自动拥有所有权限
        if user.role == "admin":
            return user

        # 检查是否拥有所需的 scope
        missing_scopes = self.required_scopes - expanded_scopes
        ...

修复 2: 共享模块返回完整字段 (services/common/microcosm_common/users/repository.py)

python
def get_user_by_uid(uid: str) -> Optional[Dict[str, Any]]:
    ...
    return {
        'uid': user['uid'],
        'email': user.get('email'),
        'wallet_address': user.get('wallet_address'),
        'role': user.get('role', 'user'),
        'api_keys_configured': user.get('api_keys_configured', False),
        'display_name': user.get('display_name'),    # 新增
        'avatar_url': user.get('avatar_url'),        # 新增
        'created_at': user.get('created_at'),
        'updated_at': user.get('updated_at')
    }

关键经验:

  1. OpenID Connect 兼容: profile 是 OIDC 标准 scope,应等同于 user:read
  2. admin 角色特殊: admin 自动拥有所有权限,不受 scope 限制,容易掩盖 scope 问题
  3. 共享模块一致性: 使用共享模块时要确保返回所有必要字段

部署版本:

  • user-service: v2.1.9
  • open-api-service: v1.1.2

影响范围:

  • 所有非 admin 角色用户现在可以正常获取头像和昵称
  • Double Helix、Event Horizon 等使用 OAuth 接入的项目均受益

2026-01-16 Double Helix OAuth Callback 用户资料修复

问题描述:

Double Helix 前端侧边栏无法显示用户头像和昵称(显示默认头像和 "User")。

根因分析:

OAuth callback 页面 (app/auth/callback/page.tsx) 在调用 authManager.setUser() 时,没有传递 displayNameavatarUrl 字段,即使 /api/users/profile API 已正确返回这些数据。

修复内容:

修改 c:\double-helix\services\frontend-service\app\auth\callback\page.tsx:

typescript
// 修复前 ❌
authManager.setUser({
  uid: userData.uid,
  email: userData.email || "",
  role: finalRole as any,
  apiKeysConfigured: userData.api_keys_configured || false,
})

// 修复后 ✅
authManager.setUser({
  uid: userData.uid,
  email: userData.email || "",
  role: finalRole as any,
  displayName: userData.display_name || null,   // 新增
  avatarUrl: userData.avatar_url || null,       // 新增
  apiKeysConfigured: userData.api_keys_configured || false,
})

关键经验:

  1. 字段名映射: API 返回 snake_case (display_name, avatar_url),前端 User 类型使用 camelCase (displayName, avatarUrl)
  2. 响应解包: Profile API 响应格式为 {success: true, user: {...}},需要兼容处理 data.user || data
  3. OAuth Callback 职责: Callback 必须在 setUser 时传递完整用户信息,包括 displayName 和 avatarUrl

部署版本:

  • Double Helix frontend-service: v1.3.4

影响范围:

  • 用户登录后侧边栏立即显示正确的头像和昵称
  • 所有使用 Microcosm OAuth 的项目都需要注意此问题

16. 价格预言机架构

权威定义: 详见 docs/_definitions/distribution-ratios.md

v1.7 更新 (2026-01-19): 新增价格预言机架构,Open API 作为备用价格来源

16.1 架构概览

价格预言机架构 (Price Oracle Architecture)

价格来源 (按优先级):

优先级来源
1Pyth 市场价格
2Open API 价格
3默认 10 USDC

以上价格来源汇入预言机服务 (链下),每 4 小时更新一次。

Reincarnation 合约 (链上):

参数说明
base_price预言机更新的 30 天均价
premium_bps500 (5% 溢价)
buyback_pricebase_price x 1.05

用户交易 (x402):

用户交易时从合约读取 buyback_price: 用户 MCC --> 合约读取 buyback_price --> 用户获得 USDC

16.2 核心原则

原则说明
合约是唯一真实来源用户交易价格从 Reincarnation 合约读取,不从数据库或 API
合约不关心价格来源合约只认预言机服务更新的 base_price
Open API 是备用来源/v1/mcc/price 作为 Pyth 不可用时的回退
价格来源有优先级Pyth > Open API > 默认价格

16.3 价格来源优先级

优先级来源说明何时使用
1Pyth 市场价格从 Pyth Network 获取的实时市场价格正常情况下使用
2Open API 管理员价格通过 /v1/mcc/price 设置的价格Pyth 不可用时回退
3默认价格10 USDC所有来源失效时的兜底

16.4 Open API 价格端点

GET /v1/mcc/price

获取当前 MCC 价格(供预言机服务查询)。

响应示例:

json
{
  "data": {
    "type": "mcc_price",
    "attributes": {
      "price_usdc": "10.50",
      "source": "admin",
      "updated_at": "2026-01-19T10:00:00Z"
    }
  }
}

POST /v1/mcc/price

设置管理员价格(仅限管理员)。

请求:

json
{
  "price_usdc": "10.50"
}

响应:

json
{
  "data": {
    "type": "mcc_price",
    "attributes": {
      "price_usdc": "10.50",
      "source": "admin",
      "updated_at": "2026-01-19T10:00:00Z"
    }
  }
}

16.5 更新频率

组件更新频率说明
预言机服务每 4 小时聚合价格来源,计算 30 天均价
合约 base_price预言机触发时预言机调用 update_price 指令
数据库缓存每小时仅用于前端展示,不用于交易
用户交易实时每次交易从合约读取最新价格

16.6 价格计算公式

base_price = AVG(30天 × 4小时收盘价) = 180 个数据点的平均值 buyback_price = base_price × 1.05 (+5% 溢价)

16.7 预言机服务职责

职责说明
价格聚合按优先级从多个来源获取价格
均价计算计算 30 天 × 4 小时的 180 个数据点均值
合约更新调用 Reincarnation 合约的 update_price 指令
价格历史存储历史价格数据供均价计算

2026-01-19 v1.7 更新记录

新增内容:

  1. 价格预言机架构文档 (Section 16)

    • 架构概览图
    • 核心原则
    • 价格来源优先级
    • Open API 价格端点详细说明
    • 更新频率表
    • 价格计算公式
  2. MCC API 端点更新 (Section 4.1.1)

    • 更新 /v1/mcc/price 描述:标注为预言机备用来源
    • 新增 POST /v1/mcc/price 端点:管理员设置价格

关键架构变更:

  • Open API /v1/mcc/price 现在是价格预言机服务的备用来源(优先级 2)
  • 预言机服务聚合价格后更新合约,合约是用户交易的唯一价格来源
  • 遵循 x402 非托管架构:用户交易直接读取合约价格

17. Phase 8: 项目注册与 MCD 白名单管理

17.1 概述

本章节描述项目开发者注册流程和 MCD 钱包白名单管理机制。开发者在申请 Project ID 时需提交 MCC/MCD 钱包地址,管理员审核后将项目添加到链上白名单。

17.2 架构概览

项目注册与白名单流程:

步骤操作方动作结果
1开发者 (Portal)提交项目申请数据库记录状态为 pending
2管理员 (Admin)审核申请 (Open API)状态更新为 approved
3系统 (Solana)链上同步白名单创建 Whitelist PDA

17.3 数据库表设计

17.3.1 project_applications

sql
CREATE TABLE project_applications (
    id SERIAL PRIMARY KEY,
    application_id VARCHAR(36) NOT NULL UNIQUE,    -- UUID
    project_name VARCHAR(100) NOT NULL,            -- 项目名称
    project_description TEXT,                       -- 项目描述
    developer_uid VARCHAR(100) NOT NULL,           -- 申请人 Firebase UID
    developer_email VARCHAR(255) NOT NULL,         -- 申请人邮箱
    company_name VARCHAR(100),                     -- 公司名称
    website_url VARCHAR(255),                      -- 项目官网

    -- 钱包地址
    mcc_wallet_address VARCHAR(64),                -- MCC 收款钱包地址
    mcd_wallet_address VARCHAR(64) NOT NULL,       -- MCD 收款钱包地址 (必填)

    -- 审核信息
    status VARCHAR(20) NOT NULL DEFAULT 'pending', -- pending/approved/rejected/suspended
    reviewed_by VARCHAR(100),                      -- 审核人 UID
    reviewed_at TIMESTAMP,                         -- 审核时间
    rejection_reason TEXT,                         -- 拒绝原因

    -- 批准后生成
    project_id INTEGER,                            -- 数据库自增 ID (审批后生成)
    api_key VARCHAR(64),                           -- API Key (审批后生成)
    api_secret_hash VARCHAR(128),                  -- API Secret Hash

    -- 链上信息
    whitelist_pda VARCHAR(64),                     -- 链上白名单 PDA 地址
    whitelist_bump INTEGER,                        -- PDA bump
    whitelist_tx VARCHAR(128),                     -- 上链交易签名

    -- 时间戳
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_project_apps_status ON project_applications(status);
CREATE INDEX idx_project_apps_developer ON project_applications(developer_uid);
CREATE INDEX idx_project_apps_project_id ON project_applications(project_id);

17.3.2 mcd_wallet_whitelist

sql
-- 此表已存在于 organization-service
-- 参考 CLAUDE.md 中的 MCD 白名单机制说明
CREATE TABLE mcd_wallet_whitelist (
    id SERIAL PRIMARY KEY,
    project_id INTEGER NOT NULL UNIQUE,
    project_name VARCHAR(100) NOT NULL,
    wallet_address VARCHAR(64) NOT NULL,
    pda_address VARCHAR(64),                       -- 链上 PDA 地址
    pda_bump INTEGER,
    status VARCHAR(20) NOT NULL DEFAULT 'active',  -- active/suspended/removed
    created_by VARCHAR(100) NOT NULL,              -- 创建人 UID
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_whitelist_wallet ON mcd_wallet_whitelist(wallet_address);
CREATE INDEX idx_whitelist_status ON mcd_wallet_whitelist(status);

17.4 API 端点定义

17.4.1 项目申请 API

POST /v1/projects/apply

开发者提交项目申请。

请求头:

Authorization: Bearer {firebase_id_token}

请求体:

json
{
  "project_name": "My DApp",
  "project_description": "A decentralized application for...",
  "company_name": "My Company Ltd.",
  "website_url": "https://mydapp.com",
  "mcc_wallet_address": "5uo1HYjQXokE9UAd8UYiwAKomL5WACqpQMbV2Ftk7pXx",
  "mcd_wallet_address": "GaQdEfHjJar2X3Kqo8ptAgyretc6hakX8ZqeLW1cmRuS"  // 官方开发者项目备用钱包地址
}

响应 (201 Created):

json
{
  "data": {
    "type": "project_application",
    "id": "app-uuid-12345",
    "attributes": {
      "project_name": "My DApp",
      "status": "pending",
      "mcd_wallet_address": "GaQdEfHjJar2X3Kqo8ptAgyretc6hakX8ZqeLW1cmRuS"  // 官方开发者项目备用钱包地址,
      "created_at": "2026-01-26T10:00:00Z"
    }
  }
}

验证规则:

  • mcd_wallet_address 必填,必须是有效的 Solana Base58 地址
  • mcc_wallet_address 选填,如果提供必须是有效地址
  • project_name 长度 3-100 字符
  • 同一用户最多有 1 个 pending 状态的申请
GET /v1/projects/applications

查询当前用户的申请记录。

响应:

json
{
  "data": [
    {
      "type": "project_application",
      "id": "app-uuid-12345",
      "attributes": {
        "project_name": "My DApp",
        "status": "approved",
        "project_id": 2,
        "api_key": "mc_live_abc123...",
        "created_at": "2026-01-26T10:00:00Z",
        "reviewed_at": "2026-01-26T12:00:00Z"
      }
    }
  ]
}
GET /v1/projects/applications/{application_id}

查询单个申请详情。

17.4.2 管理员审核 API

GET /v1/admin/projects/applications

获取所有项目申请列表(管理员)。

请求参数:

?status=pending # 筛选状态: pending/approved/rejected/all ?page=1&per_page=20 # 分页

响应:

json
{
  "data": [
    {
      "type": "project_application",
      "id": "app-uuid-12345",
      "attributes": {
        "project_name": "My DApp",
        "developer_email": "dev@example.com",
        "company_name": "My Company Ltd.",
        "mcd_wallet_address": "GaQdEfHjJar2X3Kqo8ptAgyretc6hakX8ZqeLW1cmRuS"  // 官方开发者项目备用钱包地址,
        "status": "pending",
        "created_at": "2026-01-26T10:00:00Z"
      }
    }
  ],
  "meta": {
    "total": 15,
    "page": 1,
    "per_page": 20
  }
}
POST /v1/admin/projects/applications/{application_id}/approve

批准项目申请,自动创建 Project ID、API Key 并同步到链上白名单。

响应 (200 OK):

json
{
  "data": {
    "type": "project_application",
    "id": "app-uuid-12345",
    "attributes": {
      "status": "approved",
      "project_id": 2,
      "api_key": "mc_live_xxxxxxxxxxxxxxxx",
      "api_secret": "mc_secret_yyyyyyyyyyyy",
      "whitelist_pda": "2sKFrgbgekkhw3jZgJiskP1YVhwKYrMkfLRTjHgD1Kio",
      "whitelist_tx": "5ScZLQTuFqw3..."
    }
  }
}

注意: api_secret 仅在批准响应中返回一次,需提醒开发者妥善保存。

POST /v1/admin/projects/applications/{application_id}/reject

拒绝项目申请。

请求体:

json
{
  "reason": "项目描述不符合接入标准"
}

17.4.3 MCD 白名单管理 API

GET /v1/admin/mcd/whitelist

获取 MCD 白名单列表。

响应:

json
{
  "data": [
    {
      "type": "mcd_whitelist_entry",
      "id": "1",
      "attributes": {
        "project_id": 2,
        "project_name": "Double Helix",
        "wallet_address": "4E4qsLLG2P88vLGTE4n39ayjaRAExbZRUdhJkrPCiBEA",
        "pda_address": "4Ch4RXdjUf5Mjw2L9R9zemCTRwTk1iE8rySrYq8rnnB7",
        "status": "active",
        "created_at": "2026-01-26T00:00:00Z"
      }
    }
  ]
}
PUT /v1/admin/mcd/whitelist/{project_id}/status

更新白名单状态(暂停/激活)。

请求体:

json
{
  "status": "suspended"
}

响应:

json
{
  "data": {
    "type": "mcd_whitelist_entry",
    "id": "1",
    "attributes": {
      "status": "suspended",
      "updated_at": "2026-01-26T15:00:00Z"
    }
  }
}
DELETE /v1/admin/mcd/whitelist/{project_id}

从白名单移除项目(链上 + 数据库)。

响应 (200 OK):

json
{
  "data": {
    "message": "Project removed from whitelist",
    "remove_tx": "3kSVduyRZjYZAB2..."
  }
}

17.5 链上白名单操作

17.5.1 PDA 派生

python
# Python 实现 (blockchain-service)
from solders.pubkey import Pubkey

MCD_PROGRAM_ID = Pubkey.from_string("J9UwVmFEr7ujLcp19T8nqpDnpBLcDzpL4cpwh5TMSd36")
MCD_WHITELIST_SEED = b"mcd_whitelist"

def get_whitelist_pda(project_id: int) -> tuple[Pubkey, int]:
    """计算白名单 PDA 地址"""
    project_id_bytes = project_id.to_bytes(8, 'little')
    pda, bump = Pubkey.find_program_address(
        [MCD_WHITELIST_SEED, project_id_bytes],
        MCD_PROGRAM_ID
    )
    return pda, bump

17.5.2 添加到白名单

python
async def add_to_whitelist(
    project_id: int,
    project_name: str,
    wallet_address: str
) -> str:
    """
    调用 MCD 合约 add_to_whitelist 指令
    返回交易签名
    """
    # 1. 计算 PDA
    whitelist_pda, bump = get_whitelist_pda(project_id)

    # 2. 构造指令
    discriminator = get_instruction_discriminator("add_to_whitelist")
    # [8 bytes discriminator] + [8 bytes project_id] + [4 bytes name_len] + [name bytes]

    # 3. 发送交易
    tx_sig = await send_transaction(...)
    return tx_sig

17.5.3 链上指令列表

指令用途权限
add_to_whitelist添加项目到白名单管理员 (authority)
remove_from_whitelist移除项目管理员
update_whitelist_status更新状态 (active/suspended)管理员

17.6 前端管理页面

17.6.1 开发者申请页面

路径: /developer/apply

功能:

  • 填写项目信息表单
  • 输入 MCC/MCD 钱包地址
  • 钱包地址格式验证
  • 提交申请

组件结构:

tsx
// app/(dashboard)/developer/apply/page.tsx
export default function ProjectApplicationPage() {
  return (
    <div className="container mx-auto py-8">
      <h1>申请项目接入</h1>
      <ProjectApplicationForm />
    </div>
  )
}

17.6.2 管理员项目审核页面

路径: /admin/project-applications

功能:

  • 项目申请列表(按状态筛选)
  • 查看申请详情
  • 批准/拒绝操作
  • 批准后显示生成的 API Key

组件结构:

tsx
// app/(dashboard)/admin/project-applications/page.tsx
export default function ProjectApplicationsAdminPage() {
  return (
    <div className="container mx-auto py-8">
      <h1>项目申请管理</h1>
      <Tabs defaultValue="pending">
        <TabsList>
          <TabsTrigger value="pending">待审核</TabsTrigger>
          <TabsTrigger value="approved">已批准</TabsTrigger>
          <TabsTrigger value="rejected">已拒绝</TabsTrigger>
        </TabsList>
        <TabsContent value="pending">
          <ApplicationList status="pending" />
        </TabsContent>
        {/* ... */}
      </Tabs>
    </div>
  )
}

17.6.3 MCD 白名单管理页面

路径: /admin/mcd-whitelist

功能:

  • 白名单项目列表
  • 项目状态管理(激活/暂停)
  • 移除项目
  • 链上 PDA 地址显示
  • 交易记录查看

组件结构:

tsx
// app/(dashboard)/admin/mcd-whitelist/page.tsx
export default function McdWhitelistAdminPage() {
  return (
    <div className="container mx-auto py-8">
      <h1>MCD 白名单管理</h1>
      <WhitelistTable />
    </div>
  )
}

17.7 安全考虑

安全措施说明
钱包地址验证验证 Base58 格式,检查链上账户是否存在
权限控制只有管理员可以批准/拒绝申请
API Secret 安全只在批准时返回一次,存储 hash 值
链上验证consume_mcd 指令验证目标地址是否在白名单
审计日志所有审核操作记录到 audit_logs

17.8 实施清单

阶段任务服务状态
1创建 project_applicationsdatabase✅ 完成
2实现项目申请 APIopen-api-service✅ 完成
3实现管理员审核 APIopen-api-service✅ 完成
4集成链上白名单操作blockchain-service✅ 完成
5开发者申请页面portal-service⏳ 待实施
6管理员审核页面portal-service✅ 完成
7MCD 白名单管理页面portal-service✅ 完成

2026-01-25 v1.9 Phase 8 实施完成

✅ 已实施功能:

  1. 数据库 (✅ 完成)

    • project_applications 表已创建
    • mcd_wallet_whitelist 表已创建
  2. open-api-service v1.1.8 (✅ 完成)

    • POST /api/open/projects/applications - 开发者提交项目申请
    • GET /api/open/projects/applications - 查询申请记录
    • GET /api/open/admin/projects/applications - 管理员查看申请列表
    • POST /api/open/admin/projects/applications/{id}/approve - 批准申请
    • POST /api/open/admin/projects/applications/{id}/reject - 拒绝申请
    • GET /api/open/admin/mcd/whitelist - 获取白名单列表
    • PUT /api/open/admin/mcd/whitelist/{project_id}/status - 更新白名单状态
    • DELETE /api/open/admin/mcd/whitelist/{project_id} - 移除白名单
  3. blockchain-service v1.2.28 (✅ 完成)

    • McdService.add_to_whitelist() - 链上添加白名单
    • McdService.update_whitelist_status() - 链上更新状态
    • McdService.remove_from_whitelist() - 链上移除白名单
  4. portal-service v1.7.23 (✅ 完成)

    • /admin/project-applications - 项目申请审核页面
    • /admin/mcd-whitelist - MCD 白名单管理页面
    • 管理员菜单已添加两个新入口

待实施:

  • 开发者申请页面 (用户端)

2026-01-26 v1.8 更新记录

新增内容:

  1. Phase 8: 项目注册与 MCD 白名单管理 (Section 17)

    • 完整的项目申请流程设计
    • 数据库表结构 (project_applications)
    • 开发者申请 API (POST /v1/projects/apply)
    • 管理员审核 API (/v1/admin/projects/applications/*)
    • MCD 白名单管理 API (/v1/admin/mcd/whitelist/*)
    • 链上白名单操作说明
    • 前端页面设计
  2. 新增 API 端点:

    • POST /v1/projects/apply - 开发者提交项目申请
    • GET /v1/projects/applications - 查询申请记录
    • GET /v1/admin/projects/applications - 管理员查看申请列表
    • POST /v1/admin/projects/applications/{id}/approve - 批准申请
    • POST /v1/admin/projects/applications/{id}/reject - 拒绝申请
    • GET /v1/admin/mcd/whitelist - 获取白名单列表
    • PUT /v1/admin/mcd/whitelist/{project_id}/status - 更新白名单状态
    • DELETE /v1/admin/mcd/whitelist/{project_id} - 移除白名单

关键设计:

  • 开发者申请时必须提交 MCD 钱包地址
  • 管理员批准后自动生成 Project ID、API Key
  • 批准后自动调用链上 add_to_whitelist 指令
  • 支持白名单状态管理(激活/暂停/移除)
询问 AI
询问 AI