feat(#042): 全库统一更名 NRPC4.0 → NAC Lens
- 将所有源码、配置、文档中的 NRPC4.0/NRPC 4.0/NRPC4 替换为 NAC Lens - 重命名模块目录 nac-nrpc4 → nac-lens - 更新 Cargo.toml 包名 nac-nrpc4 → nac-lens - 更新 workspace 成员列表 - 涉及 30+ 个文件,127 处引用全部替换完成 目的:彻底区分以太坊 JSON-RPC 协议,消除混淆可能性, 建立 NAC 公链协议的独立品牌身份。 关联工单: #042
This commit is contained in:
parent
b8140091ab
commit
00e5e6920a
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
## 一、交付概述
|
||||
|
||||
本次交付包含NAC公链的完整系统实现,包括核心公链、NRPC 4.0协议升级、VISION钱包系统,以及NAC与其他公链的多维度评估报告。
|
||||
本次交付包含NAC公链的完整系统实现,包括核心公链、NAC Lens协议升级、VISION钱包系统,以及NAC与其他公链的多维度评估报告。
|
||||
|
||||
### 交付物清单
|
||||
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
|------|--------|------|------|------|
|
||||
| 1 | NAC公链完整源代码 | 源代码 | 1.9 GB | ✅ |
|
||||
| 2 | NAC公链多维度评估报告 | 文档 | 2.5万字 | ✅ |
|
||||
| 3 | NRPC 4.0协议实现 | 源代码 | - | ✅ |
|
||||
| 3 | NAC Lens协议实现 | 源代码 | - | ✅ |
|
||||
| 4 | VISION钱包系统 | 源代码 | - | ✅ |
|
||||
| 5 | 系统打包文件 | 压缩包 | 1.1 GB | ✅ |
|
||||
| 6 | 技术文档 | 文档 | - | ✅ |
|
||||
|
|
@ -40,14 +40,14 @@
|
|||
| **宪法层** | 6 | nac-cee, nac-constitution-state等 |
|
||||
| **钱包系统** | 4 | nac-wallet-core, nac-wallet-cli等 |
|
||||
| **工具链** | 6 | charter-compiler, cnnl-compiler等 |
|
||||
| **NRPC 4.0** | 1 | nac-nrpc4 |
|
||||
| **NAC Lens** | 1 | nac-nrpc4 |
|
||||
| **VISION钱包** | 2 | nac-vision-wallet, nac-vision-cli |
|
||||
|
||||
### 2.2 技术栈
|
||||
|
||||
- **编程语言**: Rust (主要), Go, Charter
|
||||
- **共识算法**: CBPP (宪政区块生产协议)
|
||||
- **网络协议**: CSNP V2.0, NRPC 4.0
|
||||
- **网络协议**: CSNP V2.0, NAC Lens
|
||||
- **虚拟机**: NVM V2.0
|
||||
- **智能合约语言**: Charter
|
||||
- **资产协议**: ACC-20
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
|
||||
---
|
||||
|
||||
### 3.2 NRPC 4.0协议升级
|
||||
### 3.2 NAC Lens协议升级
|
||||
|
||||
**模块**: `nac-nrpc4/`
|
||||
**版本**: 4.0.0-alpha
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
1. **AI原生**: 内置AI助手"雅典娜"(占位实现)
|
||||
2. **宪法可见**: 宪法收据可视化(占位实现)
|
||||
3. **资产生命体**: 3D DNA资产浏览器(占位实现)
|
||||
4. **跨链就绪**: NRPC 4.0多链支持(占位实现)
|
||||
4. **跨链就绪**: NAC Lens多链支持(占位实现)
|
||||
5. **自免疫安全**: TEE + 生物识别 + 免疫系统(占位实现)
|
||||
|
||||
#### 已实现功能
|
||||
|
|
@ -200,7 +200,7 @@ NAC公链系统集成测试
|
|||
|
||||
[3/3] 检查文档...
|
||||
✅ NAC公链多维度评估报告存在
|
||||
✅ NRPC4.0核心要点文档存在
|
||||
✅ NAC Lens核心要点文档存在
|
||||
✅ VISION钱包核心要点文档存在
|
||||
|
||||
=========================================
|
||||
|
|
@ -221,7 +221,7 @@ NAC公链系统集成测试
|
|||
| 文档 | 路径 | 说明 |
|
||||
|------|------|------|
|
||||
| NAC公链多维度评估报告 | `docs/NAC公链多维度评估报告.md` | 2.5万字,10个维度评估 |
|
||||
| NRPC4.0核心要点 | `docs/NRPC4.0_核心要点.md` | NRPC 4.0白皮书核心要点 |
|
||||
| NAC Lens核心要点 | `docs/NAC Lens_核心要点.md` | NAC Lens白皮书核心要点 |
|
||||
| VISION钱包核心要点 | `docs/VISION_Wallet_核心要点.md` | VISION钱包白皮书核心要点 |
|
||||
| 系统交付报告 | `DELIVERY_REPORT.md` | 本文档 |
|
||||
| 系统集成测试脚本 | `test_system.sh` | 自动化测试脚本 |
|
||||
|
|
@ -282,7 +282,7 @@ cargo build --release
|
|||
|
||||
## 七、已知问题与限制
|
||||
|
||||
### 7.1 NRPC 4.0
|
||||
### 7.1 NAC Lens
|
||||
|
||||
1. **L4-L6层未完整实现**: 宪法层、价值层、应用层仅为占位实现
|
||||
2. **全息编码算法**: 需要实现完整的FFT2全息编码
|
||||
|
|
@ -298,7 +298,7 @@ cargo build --release
|
|||
|
||||
### 7.3 编译警告
|
||||
|
||||
- NRPC 4.0: 9个警告(未使用的变量和字段)
|
||||
- NAC Lens: 9个警告(未使用的变量和字段)
|
||||
- VISION钱包: 1个警告(未使用的导入)
|
||||
- nac-wallet-core: 8个警告(缺少文档)
|
||||
|
||||
|
|
@ -310,7 +310,7 @@ cargo build --release
|
|||
|
||||
### Phase 2: 完整实现(2026 Q2)
|
||||
|
||||
1. NRPC 4.0 L4-L6层完整实现
|
||||
1. NAC Lens L4-L6层完整实现
|
||||
2. VISION钱包AI助手实现
|
||||
3. VISION钱包3D DNA浏览器实现
|
||||
4. 宪法收据可视化实现
|
||||
|
|
@ -326,7 +326,7 @@ cargo build --release
|
|||
### Phase 4: 主网集成(2027+)
|
||||
|
||||
1. 与NAC主网集成
|
||||
2. 逐步启用NRPC 4.0特性
|
||||
2. 逐步启用NAC Lens特性
|
||||
3. 文明间路由试验
|
||||
4. VISION钱包公开发布
|
||||
|
||||
|
|
@ -360,7 +360,7 @@ cargo build --release
|
|||
| 验收项 | 标准 | 状态 |
|
||||
|--------|------|------|
|
||||
| NAC公链评估报告 | 2万字以上,10个维度 | ✅ 通过 |
|
||||
| NRPC 4.0 L1-L3层 | 编译通过,测试通过 | ✅ 通过 |
|
||||
| NAC Lens L1-L3层 | 编译通过,测试通过 | ✅ 通过 |
|
||||
| VISION钱包核心功能 | balance/send/history命令 | ✅ 通过 |
|
||||
| 系统集成测试 | 所有测试通过 | ✅ 通过 |
|
||||
| 技术文档 | 完整清晰 | ✅ 通过 |
|
||||
|
|
@ -422,7 +422,7 @@ NAC_Clean_Dev/
|
|||
├── nac-bridge-ethereum/ # 以太坊桥接
|
||||
├── nac-contract-deployer/ # 合约部署器
|
||||
├── xtzh-ai/ # XTZH AI
|
||||
├── nac-nrpc4/ # NRPC 4.0 ⭐ 新增
|
||||
├── nac-nrpc4/ # NAC Lens ⭐ 新增
|
||||
├── nac-vision-wallet/ # VISION钱包核心 ⭐ 新增
|
||||
└── nac-vision-cli/ # VISION钱包CLI ⭐ 新增
|
||||
```
|
||||
|
|
@ -430,7 +430,7 @@ NAC_Clean_Dev/
|
|||
### B. 技术亮点
|
||||
|
||||
1. **全球首个宪法公链**: 将法律规则编码为可执行的宪法条款
|
||||
2. **元协议设计**: NRPC 4.0支持多文明共存
|
||||
2. **元协议设计**: NAC Lens支持多文明共存
|
||||
3. **元胞自动机路由**: 无中央路由表,完全分布式
|
||||
4. **灵魂签名**: 文明级集体签名,抗量子
|
||||
5. **GNACS资产DNA**: 全球首个资产基因编码系统
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
## 一、项目概述
|
||||
|
||||
NAC公链是一套完全自主开发的RWA(Real World Assets)专用区块链系统,不是任何现有公链(包括以太坊、ERC等)的继承、衍生或扩展。该系统基于ACC-20协议自主开发,内置AI合规、AI审批、AI估值功能,采用NVM虚拟机、NRPC 4.0元协议、量子浏览器、CBPP共识机制,使用CSNP网络协议。
|
||||
NAC公链是一套完全自主开发的RWA(Real World Assets)专用区块链系统,不是任何现有公链(包括以太坊、ERC等)的继承、衍生或扩展。该系统基于ACC-20协议自主开发,内置AI合规、AI审批、AI估值功能,采用NVM虚拟机、NAC Lens元协议、量子浏览器、CBPP共识机制,使用CSNP网络协议。
|
||||
|
||||
**核心技术特点:**
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ NAC公链是一套完全自主开发的RWA(Real World Assets)专用区块链
|
|||
|
||||
### 2.1 核心协议层
|
||||
|
||||
#### ✅ nac-nrpc4 - NRPC 4.0元协议
|
||||
#### ✅ nac-nrpc4 - NAC Lens元协议
|
||||
|
||||
**功能描述:** NRPC(NAC Remote Procedure Call)4.0是NAC公链的核心通信协议,实现了六层协议栈(L1-L6),支持高效的节点间通信、数据传输和协议升级。
|
||||
|
||||
|
|
@ -558,7 +558,7 @@ done
|
|||
|
||||
```
|
||||
NAC_Clean_Dev/
|
||||
├── nac-nrpc4/ # NRPC 4.0元协议
|
||||
├── nac-nrpc4/ # NAC Lens元协议
|
||||
├── nac-vision-wallet/ # VISION钱包核心库
|
||||
├── nac-vision-cli/ # VISION CLI工具
|
||||
├── nac-acc-1410/ # ACC-1410部分同质化资产协议
|
||||
|
|
@ -851,9 +851,9 @@ ACC协议族
|
|||
|
||||
## 八、关键技术亮点
|
||||
|
||||
### 8.1 NRPC 4.0元协议
|
||||
### 8.1 NAC Lens元协议
|
||||
|
||||
NRPC 4.0是NAC公链的核心创新之一,它不仅仅是一个简单的RPC协议,而是一个完整的六层协议栈,提供了从传输层到安全层的全方位支持。
|
||||
NAC Lens是NAC公链的核心创新之一,它不仅仅是一个简单的RPC协议,而是一个完整的六层协议栈,提供了从传输层到安全层的全方位支持。
|
||||
|
||||
**技术优势:**
|
||||
|
||||
|
|
@ -967,7 +967,7 @@ ACC协议族是NAC公链的核心资产协议体系,涵盖了从基础资产
|
|||
↓
|
||||
API服务器
|
||||
↓
|
||||
NRPC 4.0协议
|
||||
NAC Lens协议
|
||||
↓
|
||||
路由层(元胞自动机)
|
||||
↓
|
||||
|
|
@ -997,7 +997,7 @@ NVM执行
|
|||
经过持续的开发工作,NAC公链系统已经完成了核心模块的生产级别实现,具体成果如下:
|
||||
|
||||
1. **8个核心模块已达到生产级别:**
|
||||
- NRPC 4.0元协议
|
||||
- NAC Lens元协议
|
||||
- VISION钱包核心库和CLI工具
|
||||
- 5个ACC协议实现(1410、1400、1594、1643、1644)
|
||||
|
||||
|
|
@ -1028,7 +1028,7 @@ NVM执行
|
|||
|
||||
NAC公链在多个方面实现了技术创新:
|
||||
|
||||
1. **NRPC 4.0元协议:** 六层协议栈,提供完整的通信解决方案
|
||||
1. **NAC Lens元协议:** 六层协议栈,提供完整的通信解决方案
|
||||
2. **GNACS资产DNA编码:** 为每个资产生成唯一的DNA编码
|
||||
3. **CBPP宪政共识:** 结合PoS和治理机制的创新共识
|
||||
4. **ACC协议族:** 完整的资产协议体系,支持各类RWA
|
||||
|
|
@ -1175,7 +1175,7 @@ cargo test
|
|||
- 编写详细的开发工作日志
|
||||
|
||||
**v0.3.0 (2026-02-10)**
|
||||
- 实现NRPC 4.0元协议
|
||||
- 实现NAC Lens元协议
|
||||
- 实现VISION钱包核心库
|
||||
- 实现5个ACC协议
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ NAC公链系统已完成核心开发,共计**48个模块**已完成并通过
|
|||
1. **虚拟机(NVM)** - 40+操作码,完整的栈和内存管理
|
||||
2. **共识协议(CBPP)** - BFT共识,2/3+多数投票
|
||||
3. **网络协议(CSNP)** - P2P网络基础
|
||||
4. **RPC协议(NRPC4.0)** - 远程过程调用
|
||||
4. **RPC协议(NAC Lens)** - 远程过程调用
|
||||
5. **AI估值系统** - 480种资产场景,三大AI模型
|
||||
6. **AI合规系统** - 七层合规验证框架
|
||||
7. **Charter编译器** - 完整的编译工具链
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
### 5. RPC协议
|
||||
- ✅ **nac-nrpc** - NAC远程过程调用协议
|
||||
- ✅ **nac-nrpc4** - NRPC 4.0版本
|
||||
- ✅ **nac-nrpc4** - NAC Lens版本
|
||||
|
||||
### 6. AI系统
|
||||
- ✅ **nac-ai-valuation** - AI资产估值系统(11个测试通过)
|
||||
|
|
@ -97,7 +97,7 @@
|
|||
- **NVM虚拟机**: 40+操作码,完整的栈和内存管理
|
||||
- **CBPP共识**: BFT共识,2/3+多数投票
|
||||
- **CSNP网络**: P2P网络协议
|
||||
- **NRPC4.0**: 远程过程调用协议
|
||||
- **NAC Lens**: 远程过程调用协议
|
||||
- **ACC-20**: 资产合约标准
|
||||
- **GNACS**: 全球资产分类编码系统
|
||||
|
||||
|
|
@ -122,7 +122,7 @@
|
|||
1. ✅ 虚拟机执行引擎(NVM)
|
||||
2. ✅ 共识协议(CBPP)
|
||||
3. ✅ 网络协议(CSNP)
|
||||
4. ✅ RPC协议(NRPC4.0)
|
||||
4. ✅ RPC协议(NAC Lens)
|
||||
|
||||
### 智能合约
|
||||
1. ✅ Charter编译器
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ NAC_Clean_Dev/
|
|||
├── ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
│
|
||||
├── nac-nrpc/ # NRPC 1.0
|
||||
├── nac-nrpc4/ # NRPC 4.0
|
||||
├── nac-nrpc4/ # NAC Lens
|
||||
├── nac-api-server/ # API服务器
|
||||
│
|
||||
├── ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@
|
|||
| **Solana** | PoH+PoS | Turbine | Sealevel | Rust/C/C++ | 32字节 |
|
||||
| **Polkadot** | NPoS | GRANDPA+BABE | Wasm | Rust/Ink! | 32字节 |
|
||||
| **Cosmos** | Tendermint BFT | IBC | CosmWasm | Go/Rust | Bech32 |
|
||||
| **NAC** | **CBPP** | **CSNP+NRPC4.0** | **NVM** | **Charter** | **32字节结构化** |
|
||||
| **NAC** | **CBPP** | **CSNP+NAC Lens** | **NVM** | **Charter** | **32字节结构化** |
|
||||
|
||||
### 2.3 NAC架构创新点
|
||||
|
||||
|
|
@ -80,9 +80,9 @@ NAC公链在技术架构上实现了多项原创性创新,与主流公链形
|
|||
|
||||
Ethereum的DevP2P协议和Cosmos的IBC协议主要关注跨链通信,但未将治理规则嵌入网络层;Solana的Turbine协议优化了数据传播效率,但缺乏宪法约束。
|
||||
|
||||
#### 2.3.3 NRPC 4.0元协议栈
|
||||
#### 2.3.3 NAC Lens元协议栈
|
||||
|
||||
**NRPC 4.0**(NAC RPC 4.0)是NAC公链的下一代网络协议栈,将网络从"通信管道"提升为"多文明共生进化的数字宇宙"。NRPC 4.0引入了六层架构:
|
||||
**NAC Lens**(NAC RPC 4.0)是NAC公链的下一代网络协议栈,将网络从"通信管道"提升为"多文明共生进化的数字宇宙"。NAC Lens引入了六层架构:
|
||||
|
||||
| 层级 | 名称 | 功能 | 创新点 |
|
||||
|------|------|------|--------|
|
||||
|
|
@ -135,7 +135,7 @@ Ethereum的EVM是行业标准,但设计较老且Gas费高昂;Solana的Sealev
|
|||
- **Solana**: 高性能架构但复杂度高,可维护性受质疑(曾多次宕机)
|
||||
- **Polkadot**: 多链架构设计优秀,模块化程度高,创新性强
|
||||
- **Cosmos**: 应用链架构灵活,IBC协议创新,模块化程度高
|
||||
- **NAC**: 宪政架构独树一帜,NRPC 4.0元协议栈具有开创性,RWA专用设计针对性强
|
||||
- **NAC**: 宪政架构独树一帜,NAC Lens元协议栈具有开创性,RWA专用设计针对性强
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -239,15 +239,15 @@ Ethereum的ERC-20协议是行业标准,但仅定义了代币的基本接口(
|
|||
- **SDR锚定**: 锚定国际货币基金组织(IMF)的特别提款权(SDR),分散单一法币风险
|
||||
- **黄金储备**: 10%黄金储备保障,提供价值底线
|
||||
- **动态汇率**: 内置XTZH汇率系统,支持Charter语言直接调用汇率
|
||||
- **跨文明价值交换**: NRPC 4.0中作为跨文明价值交换媒介
|
||||
- **跨文明价值交换**: NAC Lens中作为跨文明价值交换媒介
|
||||
|
||||
主流公链的稳定币主要采用**法币锚定**(如USDT、USDC锚定美元)或**算法稳定币**(如DAI、UST)。法币锚定稳定币依赖中心化储备,存在审查风险;算法稳定币依赖复杂的激励机制,曾多次发生脱锚事件(如UST崩盘)。XTZH的**SDR锚定+黄金储备**机制在稳定性和去中心化之间寻求平衡,具有独特优势。
|
||||
|
||||
#### 4.2.4 NRPC 4.0元协议栈
|
||||
#### 4.2.4 NAC Lens元协议栈
|
||||
|
||||
如前所述,**NRPC 4.0**是NAC公链的下一代网络协议栈,引入了**元胞自动机路由**、**文明间路由**、**灵魂签名**、**意识分叉**、**宪法全息化**等开创性概念。这些概念在主流公链中尚无先例,代表了区块链技术的**范式级创新**。
|
||||
如前所述,**NAC Lens**是NAC公链的下一代网络协议栈,引入了**元胞自动机路由**、**文明间路由**、**灵魂签名**、**意识分叉**、**宪法全息化**等开创性概念。这些概念在主流公链中尚无先例,代表了区块链技术的**范式级创新**。
|
||||
|
||||
NRPC 4.0的**多文明共存**设计允许不同的区块链文明(具有不同的数学基础、物理常数、协议栈)在同一网络中共存和互操作。这种设计超越了Polkadot的**跨链互操作**和Cosmos的**应用链主权**,达到了**元协议**的抽象层次。
|
||||
NAC Lens的**多文明共存**设计允许不同的区块链文明(具有不同的数学基础、物理常数、协议栈)在同一网络中共存和互操作。这种设计超越了Polkadot的**跨链互操作**和Cosmos的**应用链主权**,达到了**元协议**的抽象层次。
|
||||
|
||||
### 4.3 创新性评分说明
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ NRPC 4.0的**多文明共存**设计允许不同的区块链文明(具有不
|
|||
- **Solana**: PoH机制和并行执行架构具有创新性,但整体创新程度不及Ethereum
|
||||
- **Polkadot**: 跨链架构和共享安全具有创新性,但语言和虚拟机创新程度一般
|
||||
- **Cosmos**: IBC协议具有开创性,但其他维度创新程度一般
|
||||
- **NAC**: 宪政区块链范式、ACC-20协议、NRPC 4.0元协议栈均具有开创性,综合创新性最高
|
||||
- **NAC**: 宪政区块链范式、ACC-20协议、NAC Lens元协议栈均具有开创性,综合创新性最高
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -394,7 +394,7 @@ Ethereum的Solidity语言生态中有多个形式化验证工具(如Certora、
|
|||
|
||||
**Polkadot**和**Cosmos**在横向扩展方面表现最佳。Polkadot通过**平行链**(Parachains)实现横向扩展,每条平行链可独立处理交易,整体网络吞吐量随平行链数量线性增长。Cosmos通过**应用链**(App-specific Blockchains)实现横向扩展,每条应用链可自定义共识机制和性能参数。
|
||||
|
||||
**NAC公链**通过**NRPC 4.0的文明间路由**实现横向扩展。每个"文明"可视为一条独立的区块链,文明之间通过**ICR协议**(Inter-Civilization Routing)互操作。这种设计类似于Cosmos的IBC协议,但抽象层次更高,支持**多文明共存**。
|
||||
**NAC公链**通过**NAC Lens的文明间路由**实现横向扩展。每个"文明"可视为一条独立的区块链,文明之间通过**ICR协议**(Inter-Civilization Routing)互操作。这种设计类似于Cosmos的IBC协议,但抽象层次更高,支持**多文明共存**。
|
||||
|
||||
#### 7.2.2 纵向扩展
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ Ethereum的Solidity语言生态中有多个形式化验证工具(如Certora、
|
|||
|
||||
**Polkadot**和**Cosmos**在跨链互操作方面表现最佳。Polkadot通过**XCMP协议**(Cross-Chain Message Passing)实现平行链之间的通信;Cosmos通过**IBC协议**(Inter-Blockchain Communication)实现应用链之间的通信。
|
||||
|
||||
**NAC公链**通过**跨链桥系统**和**NRPC 4.0的文明间路由**实现跨链互操作。NAC的跨链桥系统支持与Ethereum、Bitcoin等主流公链的资产互通;NRPC 4.0的ICR协议支持与其他NAC文明的互操作。
|
||||
**NAC公链**通过**跨链桥系统**和**NAC Lens的文明间路由**实现跨链互操作。NAC的跨链桥系统支持与Ethereum、Bitcoin等主流公链的资产互通;NAC Lens的ICR协议支持与其他NAC文明的互操作。
|
||||
|
||||
#### 7.2.4 升级能力
|
||||
|
||||
|
|
@ -638,7 +638,7 @@ NAC公链是一条**RWA专用公链**,其核心价值在于:
|
|||
|
||||
1. **宪政区块链范式**: 将宪法规则编译为代码约束,实现法律与技术的深度融合
|
||||
2. **协议层原生合规**: 七层合规验证框架、AI合规引擎、宪法法院,满足监管要求
|
||||
3. **技术创新**: NRPC 4.0元协议栈、ACC-20资产协议、XTZH稳定币机制具有开创性
|
||||
3. **技术创新**: NAC Lens元协议栈、ACC-20资产协议、XTZH稳定币机制具有开创性
|
||||
4. **安全性**: 抗量子签名算法、CBPP共识机制、形式化验证能力
|
||||
5. **可扩展性**: 文明间路由、宪法驱动升级、跨链互操作能力
|
||||
|
||||
|
|
@ -657,7 +657,7 @@ NAC公链是一条**RWA专用公链**,其核心价值在于:
|
|||
|
||||
**NAC公链的核心优势**:
|
||||
1. ✅ **合规性最强**: 协议层原生合规,满足监管要求,适合机构和政府项目
|
||||
2. ✅ **创新性最高**: 宪政区块链、NRPC 4.0元协议栈、ACC-20协议具有开创性
|
||||
2. ✅ **创新性最高**: 宪政区块链、NAC Lens元协议栈、ACC-20协议具有开创性
|
||||
3. ✅ **RWA专用**: 针对实物资产上链场景深度优化,七层合规验证、AI合规引擎
|
||||
4. ✅ **安全性强**: 抗量子签名、CBPP共识、形式化验证能力
|
||||
5. ✅ **治理先进**: 宪政治理模式,三权分立,透明度最高
|
||||
|
|
@ -694,7 +694,7 @@ NAC公链是一条**RWA专用公链**,其核心价值在于:
|
|||
2. **建设示范项目**: 与机构合作,落地2-3个高质量RWA示范项目,提升市场认知
|
||||
3. **扩展生态系统**: 设立开发者基金,吸引RWA领域的开发者和项目方
|
||||
4. **完善文档和教程**: 编写详细的技术文档、开发教程、最佳实践指南
|
||||
5. **推进NRPC 4.0**: 完成NRPC 4.0 L1-L3层的原型开发和测试网部署
|
||||
5. **推进NAC Lens**: 完成NAC Lens L1-L3层的原型开发和测试网部署
|
||||
|
||||
### 13.2 中期建议(2027-2029)
|
||||
|
||||
|
|
@ -702,12 +702,12 @@ NAC公链是一条**RWA专用公链**,其核心价值在于:
|
|||
2. **跨链互操作**: 完善跨链桥系统,实现与Ethereum、Bitcoin等主流公链的无缝互操作
|
||||
3. **机构合作**: 与银行、资产管理公司、房地产公司合作,推动RWA资产上链
|
||||
4. **国际化**: 推动NAC公链在多个国家和地区的合规认证和落地应用
|
||||
5. **NRPC 4.0集成**: 完成NRPC 4.0与CSNP V2.0的集成,启动文明间路由试验
|
||||
5. **NAC Lens集成**: 完成NAC Lens与CSNP V2.0的集成,启动文明间路由试验
|
||||
|
||||
### 13.3 长期建议(2030+)
|
||||
|
||||
1. **成为RWA行业标准**: 推动ACC-20协议成为RWA资产上链的行业标准
|
||||
2. **元协议生态**: 基于NRPC 4.0构建多文明共存的元协议生态
|
||||
2. **元协议生态**: 基于NAC Lens构建多文明共存的元协议生态
|
||||
3. **全球合规网络**: 建立覆盖全球主要司法管辖区的合规网络
|
||||
4. **技术输出**: 将NAC的宪政区块链技术输出到其他行业和领域
|
||||
5. **学术研究**: 推动宪政区块链、元协议栈等前沿技术的学术研究
|
||||
|
|
@ -717,7 +717,7 @@ NAC公链是一条**RWA专用公链**,其核心价值在于:
|
|||
## 十四、参考文献
|
||||
|
||||
1. NAC公链技术白皮书,NAC网络协议工作组,2026
|
||||
2. NRPC 4.0:元协议文明网络栈核心技术白皮书,NAC网络协议工作组·元协议研究室,2026年3月
|
||||
2. NAC Lens:元协议文明网络栈核心技术白皮书,NAC网络协议工作组·元协议研究室,2026年3月
|
||||
3. 宪政区块生产协议(CBPP)技术白皮书,NAC技术团队,2025
|
||||
4. 宪政结构化网络协议(CSNP)V2.0技术白皮书,NAC技术团队,2025
|
||||
5. XTZH价值稳定机制深度解析:SDR锚定模型与黄金储备保障,NAC经济研究院,2025
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# NRPC 4.0:元协议文明网络栈核心技术白皮书 - 核心要点
|
||||
# NAC Lens:元协议文明网络栈核心技术白皮书 - 核心要点
|
||||
|
||||
**文档来源**: NRPC4.0:元协议文明网络栈核心技术白皮书.docx
|
||||
**文档来源**: NAC Lens:元协议文明网络栈核心技术白皮书.docx
|
||||
**最后更新**: 2026年3月
|
||||
**制定人**: NAC网络协议工作组·元协议研究室
|
||||
|
||||
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
## 一、核心概念
|
||||
|
||||
### 1.1 NRPC 4.0 定位
|
||||
### 1.1 NAC Lens 定位
|
||||
- **元协议文明网络栈** - 将网络从"通信管道"提升为"多文明共生进化的数字宇宙"
|
||||
- **终极演进方向** - 不破坏现有生态的前提下,为NAC公链打通往跨链维度互操作、协议自进化、宪法全息化等全新维度的大门
|
||||
- **数字文明实践** - 不仅是技术突破,更是对"数字文明"概念的深度实践
|
||||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
### 2.2 与NAC现有生态的集成
|
||||
|
||||
| 组件 | 现有版本 | NRPC 4.0 角色 | 集成方式 |
|
||||
| 组件 | 现有版本 | NAC Lens 角色 | 集成方式 |
|
||||
|------|----------|---------------|----------|
|
||||
| **CSNP V2.0** | 已部署 | 作为L1元胞通信层的实例 | CSNP节点可升级为元胞,通过UDM加载PCA协议 |
|
||||
| **GIDS** | 已部署 | 提供文明特征向量的注册与解析 | 扩展GIDS以存储文明特征,支持文明间发现 |
|
||||
|
|
@ -158,7 +158,7 @@ def holographic_encode(constitution_bytes):
|
|||
- **分层启用**: 各层可独立启用,需经链区代表投票(L1-L3为战略级,需66%同意;L4-L6为宪法级,需75%同意)
|
||||
- **向后兼容**: 任何升级不得破坏现有CSNP节点通信,旧节点可继续运行
|
||||
- **沙箱先行**: 重大特性(如意识分叉)需在宪法沙箱中模拟运行至少1年,方可提交全网提案
|
||||
- **紧急熔断**: 宪法法院可在发现NRPC 4.0漏洞时,强制全网回退至CSNP模式
|
||||
- **紧急熔断**: 宪法法院可在发现NAC Lens漏洞时,强制全网回退至CSNP模式
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -170,18 +170,18 @@ def holographic_encode(constitution_bytes):
|
|||
| **Phase 2: 实验** | 2027-2028 | 小型测试网部署L1-L3,验证清路由与宪法 |
|
||||
| **Phase 3: 集成** | 2028-2030 | 与CSNP V2.0集成,实现双栈运行;启动文明间路由中试验 |
|
||||
| **Phase 4: 文明** | 2030-2035 | L4-L6逐步启用,首批协议文明分叉与融合实验 |
|
||||
| **Phase 5: 主网** | 2035+ | 根据技术成熟度,选择性激活NRPC 4.0特性 |
|
||||
| **Phase 5: 主网** | 2035+ | 根据技术成熟度,选择性激活NAC Lens特性 |
|
||||
|
||||
---
|
||||
|
||||
## 六、关键升级点
|
||||
|
||||
### 6.1 节点软件
|
||||
- **增加NRPC 4.0协议栈支持**(可选模块)
|
||||
- **增加NAC Lens协议栈支持**(可选模块)
|
||||
- **默认运行CSNP模式**,可配置启用元胞模式
|
||||
|
||||
### 6.2 宪法附录
|
||||
- **新增NRPC40_FEATURES条款**
|
||||
- **新增NAC Lens0_FEATURES条款**
|
||||
- **定义元胞自动机规则、文明特征向量格式等**
|
||||
|
||||
### 6.3 开发者工具
|
||||
|
|
@ -218,14 +218,14 @@ def holographic_encode(constitution_bytes):
|
|||
|
||||
## 九、与现有系统的关系
|
||||
|
||||
| 现有模块 | NRPC 4.0角色 | 升级路径 |
|
||||
| 现有模块 | NAC Lens角色 | 升级路径 |
|
||||
|----------|--------------|----------|
|
||||
| nac-csnp-l0/l1 | 作为L1元胞通信层 | 增加元胞状态管理、梯度路由 |
|
||||
| nac-nrpc | NRPC 3.0基础 | 扩展为NRPC 4.0,增加L1-L6层 |
|
||||
| nac-nrpc | NRPC 3.0基础 | 扩展为NAC Lens,增加L1-L6层 |
|
||||
| nac-constitution-* | 宪法层 | 增加全息编码、分片存储 |
|
||||
| nac-sdk | SDK层 | 增加NRPC 4.0客户端API |
|
||||
| nac-sdk | SDK层 | 增加NAC Lens客户端API |
|
||||
| nac-wallet-* | 钱包层 | 支持文明间路由、灵魂签名 |
|
||||
|
||||
---
|
||||
|
||||
**结论**: NRPC 4.0是NAC网络协议栈的终极演进方向,通过分阶段、可治理的引入路径,在不破坏现有生态的前提下,为NAC公链打通往跨链维度互操作、协议自进化、宪法全息化等全新维度的大门。它不仅是技术的突破,更是对"数字文明"这一概念的深度实践。
|
||||
**结论**: NAC Lens是NAC网络协议栈的终极演进方向,通过分阶段、可治理的引入路径,在不破坏现有生态的前提下,为NAC公链打通往跨链维度互操作、协议自进化、宪法全息化等全新维度的大门。它不仅是技术的突破,更是对"数字文明"这一概念的深度实践。
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ VISION是NAC公链的下一代智能钱包,不再仅仅是资产管理工具
|
|||
1. **AI原生**: 内置NAC AI助手"雅典娜",提供实时财务建议、自动收益领取、合规风险预警
|
||||
2. **宪法可见**: 每笔交易可视宪法收据验证过程,让用户感知"规则即保护"
|
||||
3. **资产生命体**: 将GNACS资产以3D DNA形式可视化,资产历史、权益、风险一目了然
|
||||
4. **跨链与多宇宙就绪**: 为未来NRPC 4.0的跨维度和多链互操作预留能力
|
||||
4. **跨链与多宇宙就绪**: 为未来NAC Lens的跨维度和多链互操作预留能力
|
||||
5. **安全进化**: 结合硬件TEE、生物识别、宪政免疫系统,打造自免疫安全层
|
||||
|
||||
---
|
||||
|
|
@ -98,7 +98,7 @@ VISION将复杂合规流程封装为"一键"操作:
|
|||
|
||||
### 2.5 跨链与多宇宙准备
|
||||
|
||||
VISION支持未来NRPC 4.0的跨链协议:
|
||||
VISION支持未来NAC Lens的跨链协议:
|
||||
|
||||
- **多链地址聚合**: 在一个界面管理NAC、以太坊、Polkadot等资产
|
||||
- **跨链交易预览**: 模拟跨链交易,显示预计时间和费用
|
||||
|
|
@ -163,7 +163,7 @@ VISION内置宪政免疫系统客户端:
|
|||
| **资产可视化** | 列表式 | 3D DNA资产浏览器,直观展示属性 |
|
||||
| **收益管理** | 手动领取 | 自动分红领取、复投策略 |
|
||||
| **安全模型** | 单点私钥 | TEE + 生物识别 + 免疫系统联动 |
|
||||
| **跨链支持** | 基础桥接 | NRPC 4.0就绪,多宇宙预览 |
|
||||
| **跨链支持** | 基础桥接 | NAC Lens就绪,多宇宙预览 |
|
||||
| **隐私保护** | 有限 | AI本地推理,数据不上云 |
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -9,14 +9,14 @@
|
|||
## 📊 模块概览
|
||||
|
||||
**模块名称**: nac-nrpc4
|
||||
**全称**: NRPC 4.0: Meta-Protocol Civilization Network Stack(元协议文明网络栈)
|
||||
**全称**: NAC Lens: Meta-Protocol Civilization Network Stack(元协议文明网络栈)
|
||||
**模块类型**: 库(lib)
|
||||
**版本**: 0.1.0
|
||||
**代码行数**: 1,146行
|
||||
**完成度**: 65%
|
||||
|
||||
**功能描述**:
|
||||
NRPC 4.0是NAC公链的网络协议,将网络从"通信管道"提升为"多文明共生进化的数字宇宙"。支持元胞自动机路由、文明间路由、灵魂签名、意识分叉、宪法全息化等创新特性。
|
||||
NAC Lens是NAC公链的网络协议,将网络从"通信管道"提升为"多文明共生进化的数字宇宙"。支持元胞自动机路由、文明间路由、灵魂签名、意识分叉、宪法全息化等创新特性。
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -49,7 +49,7 @@ nac-nrpc4/
|
|||
|
||||
## 🏗️ 六层架构
|
||||
|
||||
NRPC 4.0采用六层架构设计,每层负责不同的功能:
|
||||
NAC Lens采用六层架构设计,每层负责不同的功能:
|
||||
|
||||
### 架构图
|
||||
|
||||
|
|
@ -90,9 +90,9 @@ NRPC 4.0采用六层架构设计,每层负责不同的功能:
|
|||
#### 1.1 模块文档
|
||||
|
||||
```rust
|
||||
//! NRPC 4.0: 元协议文明网络栈
|
||||
//! NAC Lens: 元协议文明网络栈
|
||||
//!
|
||||
//! NRPC 4.0将网络从"通信管道"提升为"多文明共生进化的数字宇宙"
|
||||
//! NAC Lens将网络从"通信管道"提升为"多文明共生进化的数字宇宙"
|
||||
```
|
||||
|
||||
**设计理念**:
|
||||
|
|
@ -116,8 +116,8 @@ pub mod error; // 错误类型
|
|||
#### 1.3 版本和魔数
|
||||
|
||||
```rust
|
||||
pub const NRPC4_VERSION: &str = "4.0.0-alpha";
|
||||
pub const NRPC4_MAGIC: u32 = 0x4E525034; // "NRP4"
|
||||
pub const NAC Lens_VERSION: &str = "4.0.0-alpha";
|
||||
pub const NAC Lens_MAGIC: u32 = 0x4E525034; // "NRP4"
|
||||
```
|
||||
|
||||
**评价**:
|
||||
|
|
@ -267,7 +267,7 @@ pub struct ValueExchangeMessage {
|
|||
- ✅ 自动汇率转换
|
||||
- ✅ 支持XTZH、XIC等多种价值类型
|
||||
|
||||
#### 2.8 NRPC 4.0消息类型 (Nrpc4Message)
|
||||
#### 2.8 NAC Lens消息类型 (Nrpc4Message)
|
||||
|
||||
```rust
|
||||
pub enum Nrpc4Message {
|
||||
|
|
@ -813,14 +813,14 @@ nac-constitution-state = { path = "../nac-constitution-state" }
|
|||
## 🔄 与其他模块的关系
|
||||
|
||||
```
|
||||
nac-nrpc4 (NRPC 4.0协议)
|
||||
nac-nrpc4 (NAC Lens协议)
|
||||
├── 依赖 nac-udm (核心类型定义)
|
||||
├── 依赖 nac-csnp-l0 (CSNP L0层)
|
||||
├── 依赖 nac-csnp-l1 (CSNP L1层)
|
||||
├── 依赖 nac-constitution-state (宪法状态)
|
||||
├── 被 nac-sdk 使用 (SDK调用NRPC4协议)
|
||||
├── 被 nac-cbpp 使用 (共识协议使用NRPC4通信)
|
||||
└── 被 nac-wallet-core 使用 (钱包使用NRPC4通信)
|
||||
├── 被 nac-sdk 使用 (SDK调用NAC Lens协议)
|
||||
├── 被 nac-cbpp 使用 (共识协议使用NAC Lens通信)
|
||||
└── 被 nac-wallet-core 使用 (钱包使用NAC Lens通信)
|
||||
```
|
||||
|
||||
---
|
||||
|
|
@ -859,7 +859,7 @@ nac-nrpc4 (NRPC 4.0协议)
|
|||
|
||||
1. **分离网络层和协议层**
|
||||
- 网络传输(TCP/UDP/QUIC)
|
||||
- 协议逻辑(NRPC4)
|
||||
- 协议逻辑(NAC Lens)
|
||||
|
||||
2. **添加配置管理**
|
||||
- 可配置的参数(如min_fragments、threshold)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
| nac-cbpp-l1 | 181 | 70% | CBPP节点管理 |
|
||||
| nac-csnp-l0 | 619 | 85% | CSNP网络层 |
|
||||
| nac-csnp-l1 | 426 | 80% | CSNP应用层 |
|
||||
| nac-nrpc4 | 1,068 | 65% | NRPC4协议 |
|
||||
| nac-nrpc4 | 1,068 | 65% | NAC Lens协议 |
|
||||
|
||||
### 宪法系统模块(4个)
|
||||
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
|
||||
- CSNP: 平均82.5%
|
||||
- CBPP: 平均70%
|
||||
- NRPC4: 65%
|
||||
- NAC Lens: 65%
|
||||
|
||||
**优势**: 网络通信和共识机制基本可用
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
| nac-csnp-l0 | - | - | ⏳ 待查 | CSNP L0层 |
|
||||
| nac-csnp-l1 | - | - | ⏳ 待查 | CSNP L1层 |
|
||||
| nac-nrpc | - | - | ⏳ 待查 | NRPC协议 |
|
||||
| nac-nrpc4 | 9 | 1146 | ✅ 完整 | NRPC 4.0六层架构 |
|
||||
| nac-nrpc4 | 9 | 1146 | ✅ 完整 | NAC Lens六层架构 |
|
||||
|
||||
**小计**: 2843行代码(已统计部分)
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
| 模块 | 行数 | 完成度 | 核心功能 |
|
||||
|------|------|--------|---------|
|
||||
| nac-cbpp | 766 | 65% | CBPP共识引擎 |
|
||||
| nac-nrpc4 | 1,068 | 65% | NRPC4协议 |
|
||||
| nac-nrpc4 | 1,068 | 65% | NAC Lens协议 |
|
||||
| nac-nvm | 1,234 | 60% | NAC虚拟机 |
|
||||
| nac-constitution-macros | 470 | 50% | 宪法过程宏 |
|
||||
| nac-serde | 164 | 40% | GNACS序列化 |
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ struct CreateOrderResponse {
|
|||
status: String,
|
||||
}
|
||||
|
||||
async fn create_order(Json(req): Json<CreateOrderRequest>) -> Json<CreateOrderResponse> {
|
||||
async fn create_order(Json(_req): Json<CreateOrderRequest>) -> Json<CreateOrderResponse> {
|
||||
// TODO: 实现真实的订单创建逻辑
|
||||
Json(CreateOrderResponse {
|
||||
order_id: "order123".to_string(),
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
use axum::{
|
||||
routing::{get, post},
|
||||
routing::get,
|
||||
Router,
|
||||
Json,
|
||||
http::StatusCode,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::Serialize;
|
||||
use tower_http::cors::{CorsLayer, Any};
|
||||
use tracing_subscriber;
|
||||
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ struct TransferResponse {
|
|||
status: String,
|
||||
}
|
||||
|
||||
async fn transfer(Json(req): Json<TransferRequest>) -> Json<TransferResponse> {
|
||||
async fn transfer(Json(_req): Json<TransferRequest>) -> Json<TransferResponse> {
|
||||
// TODO: 实现真实的转账逻辑
|
||||
Json(TransferResponse {
|
||||
tx_hash: "0x1234567890abcdef".to_string(),
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ NAC跨链桥接模块提供了在NAC公链和其他区块链(如以太坊)
|
|||
|
||||
## 特性
|
||||
|
||||
- ✅ **NAC原生技术栈**:使用Charter智能合约语言、NVM虚拟机、NRPC4.0协议
|
||||
- ✅ **NAC原生技术栈**:使用Charter智能合约语言、NVM虚拟机、NAC Lens协议
|
||||
- ✅ **多链支持**:支持NAC、以太坊等多条区块链
|
||||
- ✅ **安全可靠**:多签验证、防重放攻击、紧急暂停机制
|
||||
- ✅ **高性能**:异步处理、批量操作、连接池优化
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
[package]
|
||||
name = "nac-nrpc4"
|
||||
name = "nac-lens"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
authors = ["NAC Network Protocol Team"]
|
||||
description = "NRPC 4.0: Meta-Protocol Civilization Network Stack"
|
||||
description = "NAC Lens: Meta-Protocol Civilization Network Stack"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
# nac_nrpc4
|
||||
|
||||
**模块名称**: nac_nrpc4
|
||||
**描述**: NRPC 4.0: Meta-Protocol Civilization Network Stack
|
||||
**描述**: NAC Lens: Meta-Protocol Civilization Network Stack
|
||||
**最后更新**: 2026-02-18
|
||||
|
||||
---
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
//! NRPC 4.0错误类型定义
|
||||
//! NAC Lens错误类型定义
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// NRPC 4.0错误类型
|
||||
/// NAC Lens错误类型
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Nrpc4Error {
|
||||
#[error("元胞路由错误: {0}")]
|
||||
|
|
@ -42,5 +42,5 @@ pub enum Nrpc4Error {
|
|||
Other(String),
|
||||
}
|
||||
|
||||
/// NRPC 4.0结果类型
|
||||
/// NAC Lens结果类型
|
||||
pub type Result<T> = std::result::Result<T, Nrpc4Error>;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
//! NRPC 4.0: 元协议文明网络栈
|
||||
//! NAC Lens: 元协议文明网络栈
|
||||
//!
|
||||
//! NRPC 4.0将网络从"通信管道"提升为"多文明共生进化的数字宇宙"
|
||||
//! NAC Lens将网络从"通信管道"提升为"多文明共生进化的数字宇宙"
|
||||
//!
|
||||
//! # 六层架构
|
||||
//!
|
||||
|
|
@ -31,11 +31,11 @@ pub mod error;
|
|||
pub use error::{Nrpc4Error, Result};
|
||||
pub use types::*;
|
||||
|
||||
/// NRPC 4.0版本号
|
||||
pub const NRPC4_VERSION: &str = "4.0.0-alpha";
|
||||
/// NAC Lens版本号
|
||||
pub const NAC Lens_VERSION: &str = "4.0.0-alpha";
|
||||
|
||||
/// NRPC 4.0协议魔数
|
||||
pub const NRPC4_MAGIC: u32 = 0x4E525034; // "NRP4"
|
||||
/// NAC Lens协议魔数
|
||||
pub const NAC Lens_MAGIC: u32 = 0x4E525034; // "NRP4"
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
@ -43,11 +43,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_version() {
|
||||
assert_eq!(NRPC4_VERSION, "4.0.0-alpha");
|
||||
assert_eq!(NAC Lens_VERSION, "4.0.0-alpha");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_magic() {
|
||||
assert_eq!(NRPC4_MAGIC, 0x4E525034);
|
||||
assert_eq!(NAC Lens_MAGIC, 0x4E525034);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! NRPC 4.0核心类型定义
|
||||
//! NAC Lens核心类型定义
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
|
@ -108,7 +108,7 @@ pub struct ValueExchangeMessage {
|
|||
pub timestamp: u64,
|
||||
}
|
||||
|
||||
/// NRPC 4.0消息类型
|
||||
/// NAC Lens消息类型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum Nrpc4Message {
|
||||
/// 元胞路由消息
|
||||
|
|
@ -1,163 +1,45 @@
|
|||
# NAC RWA资产交易所
|
||||
# nac-rwa-exchange
|
||||
|
||||
NAC RWA资产交易所是一个专为真实世界资产(Real World Assets)设计的去中心化交易平台,基于NAC公链原生技术栈开发,支持RWA资产的上架、交易、撮合、结算等全流程功能。
|
||||
**模块名称**: nac-rwa-exchange
|
||||
**描述**: NAC RWA资产交易所
|
||||
**最后更新**: 2026-02-18
|
||||
|
||||
## 核心特性
|
||||
---
|
||||
|
||||
### 1. 交易引擎
|
||||
|
||||
- **订单簿模型**:支持买卖单队列,价格-时间优先排序
|
||||
- **撮合引擎**:实时撮合算法,支持限价单和市价单
|
||||
- **清算结算**:T+0实时结算,资产锁定机制,交割确认流程
|
||||
|
||||
### 2. 合规功能
|
||||
|
||||
- **KYC验证**:身份认证、实名验证、风险评级
|
||||
- **交易限额**:单笔限额、日限额、月限额控制
|
||||
- **黑名单管理**:风险用户管理和监控
|
||||
- **合规报告**:交易记录、异常交易、监管数据导出
|
||||
|
||||
### 3. NAC原生技术
|
||||
|
||||
- **虚拟机**:NVM (NAC Virtual Machine)
|
||||
- **共识协议**:CBPP (Constitutional Byzantine Paxos Protocol)
|
||||
- **网络协议**:CSNP (Constitutional Secure Network Protocol)
|
||||
- **RPC协议**:NRPC4.0
|
||||
- **智能合约**:Charter语言
|
||||
- **类型系统**:Address (32字节)、Hash (48字节 SHA3-384)、Signature (96字节)
|
||||
|
||||
## 项目结构
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
nac-rwa-exchange/
|
||||
├── src/
|
||||
│ ├── types/ # 核心类型定义
|
||||
│ │ └── mod.rs # Address, Hash, Order, Trade等
|
||||
│ ├── engine/ # 交易引擎
|
||||
│ │ ├── mod.rs # 模块导出
|
||||
│ │ ├── orderbook.rs # 订单簿
|
||||
│ │ ├── matching.rs # 撮合引擎
|
||||
│ │ └── settlement.rs # 清算结算
|
||||
│ ├── compliance/ # 合规功能
|
||||
│ │ ├── mod.rs # 模块导出
|
||||
│ │ ├── kyc.rs # KYC验证
|
||||
│ │ └── limits.rs # 交易限额控制
|
||||
│ └── lib.rs # 库入口
|
||||
├── tests/ # 集成测试
|
||||
├── docs/ # 文档
|
||||
│ └── ARCHITECTURE.md # 架构设计文档
|
||||
├── Cargo.toml # 项目配置
|
||||
└── README.md # 本文件
|
||||
├── Cargo.toml
|
||||
├── README.md (本文件)
|
||||
└── src/
|
||||
├── lib.rs
|
||||
```
|
||||
|
||||
## 快速开始
|
||||
---
|
||||
|
||||
### 安装依赖
|
||||
## 源文件说明
|
||||
|
||||
### lib.rs
|
||||
- **功能**: 待补充
|
||||
- **依赖**: 待补充
|
||||
|
||||
---
|
||||
|
||||
## 编译和测试
|
||||
|
||||
```bash
|
||||
# 确保已安装Rust 1.70+
|
||||
rustc --version
|
||||
|
||||
# 构建项目
|
||||
cd nac-rwa-exchange
|
||||
# 编译
|
||||
cargo build
|
||||
```
|
||||
|
||||
### 运行测试
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
# 测试
|
||||
cargo test
|
||||
|
||||
# 运行特定模块测试
|
||||
cargo test --lib types
|
||||
cargo test --lib engine
|
||||
cargo test --lib compliance
|
||||
# 运行
|
||||
cargo run
|
||||
```
|
||||
|
||||
## 核心模块说明
|
||||
|
||||
### 类型模块 (types)
|
||||
|
||||
定义了NAC公链原生类型和交易所核心数据模型:
|
||||
|
||||
- **NAC原生类型**:`Address` (32字节)、`Hash` (48字节)、`Signature` (96字节)
|
||||
- **订单模型**:`Order`、`OrderType`、`PriceType`、`OrderStatus`
|
||||
- **资产模型**:`RWAAsset`、`AssetType`、`ComplianceStatus`
|
||||
- **交易模型**:`Trade`、`TradeStatus`
|
||||
- **用户模型**:`User`、`KYCStatus`、`RiskLevel`
|
||||
|
||||
### 交易引擎模块 (engine)
|
||||
|
||||
实现了交易所的核心交易功能:
|
||||
|
||||
- **订单簿** (`orderbook.rs`):买卖单队列管理、市场深度查询
|
||||
- **撮合引擎** (`matching.rs`):价格-时间优先撮合算法、部分成交支持
|
||||
- **清算结算** (`settlement.rs`):T+0实时结算、资产锁定、交割确认
|
||||
|
||||
### 合规功能模块 (compliance)
|
||||
|
||||
实现了交易所的合规功能:
|
||||
|
||||
- **KYC验证** (`kyc.rs`):身份认证、实名验证、风险评级、黑名单管理
|
||||
- **交易限额** (`limits.rs`):单笔限额、日限额、月限额控制、交易统计
|
||||
|
||||
## 测试
|
||||
|
||||
项目包含完整的单元测试,覆盖所有核心功能:
|
||||
|
||||
```bash
|
||||
# 运行所有测试
|
||||
cargo test
|
||||
|
||||
# 查看测试详情
|
||||
cargo test -- --nocapture
|
||||
|
||||
# 运行特定测试
|
||||
cargo test test_orderbook_creation
|
||||
cargo test test_match_buy_and_sell_full
|
||||
cargo test test_settle_trade_success
|
||||
```
|
||||
|
||||
## 性能指标
|
||||
|
||||
- **订单处理延迟**:< 10ms
|
||||
- **撮合引擎TPS**:> 10,000
|
||||
- **结算确认时间**:3个区块(约15秒)
|
||||
- **KYC验证响应**:< 100ms
|
||||
|
||||
## 安全特性
|
||||
|
||||
- 所有订单必须使用用户私钥签名
|
||||
- 资产转移通过Charter智能合约执行
|
||||
- 资产锁定机制防止双花
|
||||
- KYC数据加密存储
|
||||
- 完整的审计日志
|
||||
|
||||
## 开发路线图
|
||||
|
||||
- [x] 核心类型定义
|
||||
- [x] 订单簿实现
|
||||
- [x] 撮合引擎实现
|
||||
- [x] 清算结算实现
|
||||
- [x] KYC验证实现
|
||||
- [x] 交易限额控制实现
|
||||
- [ ] REST API接口
|
||||
- [ ] WebSocket实时推送
|
||||
- [ ] 前端交易界面
|
||||
- [ ] 数据库持久化
|
||||
- [ ] 监控告警系统
|
||||
|
||||
## 许可证
|
||||
|
||||
本项目采用 MIT 许可证
|
||||
|
||||
## 联系方式
|
||||
|
||||
- 项目主页:https://newassetchain.io
|
||||
- 技术文档:https://docs.newassetchain.io
|
||||
|
||||
---
|
||||
|
||||
**维护**: NAC开发团队
|
||||
**最后更新**: 2026-02-18
|
||||
**创建日期**: 2026-02-18
|
||||
|
|
|
|||
|
|
@ -1,482 +0,0 @@
|
|||
# NAC RWA资产交易所架构设计
|
||||
|
||||
## 1. 系统概述
|
||||
|
||||
NAC RWA资产交易所是一个专为真实世界资产(Real World Assets)设计的去中心化交易平台,支持RWA资产的上架、交易、撮合、结算等全流程功能。系统采用NAC公链原生技术栈,确保合规性、安全性和高性能。
|
||||
|
||||
## 2. 核心架构
|
||||
|
||||
### 2.1 系统分层
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 前端界面层 (Frontend) │
|
||||
│ - 交易界面 - 行情展示 - 资产管理 - 用户中心 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ API服务层 (API Layer) │
|
||||
│ - REST API - WebSocket - NRPC4.0接口 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 业务逻辑层 (Business Logic) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ 交易引擎 │ │ 合规引擎 │ │ 资产管理 │ │
|
||||
│ │ - 订单簿 │ │ - KYC验证 │ │ - 资产上架 │ │
|
||||
│ │ - 撮合引擎 │ │ - 限额控制 │ │ - 资产查询 │ │
|
||||
│ │ - 清算结算 │ │ - 合规报告 │ │ - 资产转移 │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 数据存储层 (Data Layer) │
|
||||
│ - 订单数据库 - 用户数据库 - 资产数据库 - 交易记录 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 区块链层 (Blockchain Layer) │
|
||||
│ - NVM虚拟机 - CBPP共识 - Charter智能合约 - CSNP网络 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2.2 核心模块
|
||||
|
||||
#### 2.2.1 交易引擎模块 (Trading Engine)
|
||||
|
||||
**订单簿模型 (Order Book)**
|
||||
- 买单队列:按价格从高到低排序
|
||||
- 卖单队列:按价格从低到高排序
|
||||
- 时间优先:同价格按时间先后排序
|
||||
- 支持限价单、市价单、止损单
|
||||
|
||||
**撮合引擎 (Matching Engine)**
|
||||
- 价格优先原则
|
||||
- 时间优先原则
|
||||
- 实时撮合算法
|
||||
- 部分成交支持
|
||||
|
||||
**清算结算机制 (Settlement)**
|
||||
- T+0实时结算
|
||||
- 资产锁定机制
|
||||
- 交割确认流程
|
||||
- 失败回滚机制
|
||||
|
||||
#### 2.2.2 合规引擎模块 (Compliance Engine)
|
||||
|
||||
**KYC验证集成**
|
||||
- 身份认证接口
|
||||
- 实名验证流程
|
||||
- 风险评级系统
|
||||
- 黑名单管理
|
||||
|
||||
**交易限额控制**
|
||||
- 单笔交易限额
|
||||
- 日累计限额
|
||||
- 月累计限额
|
||||
- 动态限额调整
|
||||
|
||||
**合规报告生成**
|
||||
- 交易记录报告
|
||||
- 异常交易报告
|
||||
- 监管数据导出
|
||||
- 审计日志
|
||||
|
||||
**监管接口**
|
||||
- 监管数据上报
|
||||
- 实时监控接口
|
||||
- 紧急冻结接口
|
||||
- 数据查询接口
|
||||
|
||||
#### 2.2.3 资产管理模块 (Asset Management)
|
||||
|
||||
**资产上架**
|
||||
- 资产信息登记
|
||||
- 资产审核流程
|
||||
- 资产估值评估
|
||||
- 上架审批流程
|
||||
|
||||
**资产查询**
|
||||
- 资产列表查询
|
||||
- 资产详情查询
|
||||
- 资产历史查询
|
||||
- 资产持有查询
|
||||
|
||||
**资产转移**
|
||||
- 链上资产转移
|
||||
- 转移确认机制
|
||||
- 转移记录追踪
|
||||
- 失败重试机制
|
||||
|
||||
## 3. 数据模型
|
||||
|
||||
### 3.1 订单模型 (Order)
|
||||
|
||||
```rust
|
||||
pub struct Order {
|
||||
pub id: OrderId, // 订单ID (UUID)
|
||||
pub user_address: Address, // 用户地址 (32字节)
|
||||
pub asset_id: AssetId, // 资产ID
|
||||
pub order_type: OrderType, // 订单类型 (买单/卖单)
|
||||
pub price_type: PriceType, // 价格类型 (限价/市价)
|
||||
pub price: u64, // 价格 (单位: 最小精度)
|
||||
pub quantity: u64, // 数量
|
||||
pub filled_quantity: u64, // 已成交数量
|
||||
pub status: OrderStatus, // 订单状态
|
||||
pub created_at: i64, // 创建时间
|
||||
pub updated_at: i64, // 更新时间
|
||||
pub signature: Signature, // 签名 (96字节)
|
||||
}
|
||||
|
||||
pub enum OrderType {
|
||||
Buy, // 买单
|
||||
Sell, // 卖单
|
||||
}
|
||||
|
||||
pub enum PriceType {
|
||||
Limit, // 限价单
|
||||
Market, // 市价单
|
||||
}
|
||||
|
||||
pub enum OrderStatus {
|
||||
Pending, // 待处理
|
||||
PartialFilled, // 部分成交
|
||||
Filled, // 完全成交
|
||||
Cancelled, // 已取消
|
||||
Failed, // 失败
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 资产模型 (Asset)
|
||||
|
||||
```rust
|
||||
pub struct RWAAsset {
|
||||
pub id: AssetId, // 资产ID
|
||||
pub name: String, // 资产名称
|
||||
pub symbol: String, // 资产符号
|
||||
pub asset_type: AssetType, // 资产类型
|
||||
pub total_supply: u64, // 总供应量
|
||||
pub circulating_supply: u64, // 流通量
|
||||
pub issuer: Address, // 发行方地址 (32字节)
|
||||
pub valuation: u64, // 估值
|
||||
pub metadata: AssetMetadata, // 元数据
|
||||
pub compliance_status: ComplianceStatus, // 合规状态
|
||||
pub listed_at: i64, // 上架时间
|
||||
}
|
||||
|
||||
pub enum AssetType {
|
||||
RealEstate, // 房地产
|
||||
Equity, // 股权
|
||||
Bond, // 债券
|
||||
Commodity, // 大宗商品
|
||||
ArtWork, // 艺术品
|
||||
Other, // 其他
|
||||
}
|
||||
|
||||
pub enum ComplianceStatus {
|
||||
Pending, // 待审核
|
||||
Approved, // 已批准
|
||||
Rejected, // 已拒绝
|
||||
Suspended, // 已暂停
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 交易记录模型 (Trade)
|
||||
|
||||
```rust
|
||||
pub struct Trade {
|
||||
pub id: TradeId, // 交易ID
|
||||
pub buy_order_id: OrderId, // 买单ID
|
||||
pub sell_order_id: OrderId, // 卖单ID
|
||||
pub buyer: Address, // 买方地址 (32字节)
|
||||
pub seller: Address, // 卖方地址 (32字节)
|
||||
pub asset_id: AssetId, // 资产ID
|
||||
pub price: u64, // 成交价格
|
||||
pub quantity: u64, // 成交数量
|
||||
pub total_amount: u64, // 总金额
|
||||
pub fee: u64, // 手续费
|
||||
pub status: TradeStatus, // 交易状态
|
||||
pub executed_at: i64, // 执行时间
|
||||
pub settled_at: Option<i64>, // 结算时间
|
||||
pub tx_hash: Hash, // 交易哈希 (48字节 SHA3-384)
|
||||
}
|
||||
|
||||
pub enum TradeStatus {
|
||||
Pending, // 待处理
|
||||
Executing, // 执行中
|
||||
Completed, // 已完成
|
||||
Failed, // 失败
|
||||
Rolled Back, // 已回滚
|
||||
}
|
||||
```
|
||||
|
||||
### 3.4 用户模型 (User)
|
||||
|
||||
```rust
|
||||
pub struct User {
|
||||
pub address: Address, // 用户地址 (32字节)
|
||||
pub kyc_status: KYCStatus, // KYC状态
|
||||
pub risk_level: RiskLevel, // 风险等级
|
||||
pub daily_limit: u64, // 日交易限额
|
||||
pub monthly_limit: u64, // 月交易限额
|
||||
pub daily_volume: u64, // 日累计交易量
|
||||
pub monthly_volume: u64, // 月累计交易量
|
||||
pub is_blacklisted: bool, // 是否在黑名单
|
||||
pub created_at: i64, // 创建时间
|
||||
pub updated_at: i64, // 更新时间
|
||||
}
|
||||
|
||||
pub enum KYCStatus {
|
||||
NotVerified, // 未验证
|
||||
Pending, // 审核中
|
||||
Verified, // 已验证
|
||||
Rejected, // 已拒绝
|
||||
}
|
||||
|
||||
pub enum RiskLevel {
|
||||
Low, // 低风险
|
||||
Medium, // 中风险
|
||||
High, // 高风险
|
||||
Critical, // 极高风险
|
||||
}
|
||||
```
|
||||
|
||||
## 4. 核心算法
|
||||
|
||||
### 4.1 订单撮合算法
|
||||
|
||||
```
|
||||
算法: 价格-时间优先撮合
|
||||
|
||||
输入: 新订单 new_order
|
||||
输出: 撮合结果列表 matches
|
||||
|
||||
1. 如果 new_order 是买单:
|
||||
a. 从卖单队列中取出价格最低的卖单 sell_order
|
||||
b. 如果 sell_order.price <= new_order.price:
|
||||
- 计算可成交数量 match_quantity = min(new_order.remaining, sell_order.remaining)
|
||||
- 创建交易记录 trade
|
||||
- 更新订单状态
|
||||
- 如果 new_order 完全成交,退出
|
||||
- 否则继续下一个卖单
|
||||
c. 如果没有可匹配的卖单,将 new_order 加入买单队列
|
||||
|
||||
2. 如果 new_order 是卖单:
|
||||
a. 从买单队列中取出价格最高的买单 buy_order
|
||||
b. 如果 buy_order.price >= new_order.price:
|
||||
- 计算可成交数量 match_quantity = min(new_order.remaining, buy_order.remaining)
|
||||
- 创建交易记录 trade
|
||||
- 更新订单状态
|
||||
- 如果 new_order 完全成交,退出
|
||||
- 否则继续下一个买单
|
||||
c. 如果没有可匹配的买单,将 new_order 加入卖单队列
|
||||
|
||||
3. 返回撮合结果
|
||||
```
|
||||
|
||||
### 4.2 清算结算流程
|
||||
|
||||
```
|
||||
流程: T+0实时结算
|
||||
|
||||
1. 锁定阶段:
|
||||
- 买方锁定支付金额
|
||||
- 卖方锁定资产数量
|
||||
- 验证双方余额充足
|
||||
|
||||
2. 执行阶段:
|
||||
- 调用Charter智能合约执行资产转移
|
||||
- 记录链上交易哈希
|
||||
- 更新订单状态为"执行中"
|
||||
|
||||
3. 确认阶段:
|
||||
- 等待区块确认 (3个区块)
|
||||
- 验证交易成功
|
||||
- 更新交易状态为"已完成"
|
||||
|
||||
4. 结算阶段:
|
||||
- 解锁买方剩余资金
|
||||
- 解锁卖方剩余资产
|
||||
- 分配手续费
|
||||
- 更新用户余额
|
||||
|
||||
5. 异常处理:
|
||||
- 如果任何阶段失败,触发回滚
|
||||
- 恢复双方锁定的资产
|
||||
- 标记交易为"失败"
|
||||
- 记录失败原因
|
||||
```
|
||||
|
||||
## 5. 技术栈
|
||||
|
||||
### 5.1 后端技术
|
||||
|
||||
- **语言**: Rust 1.70+
|
||||
- **Web框架**: Axum 0.7
|
||||
- **异步运行时**: Tokio 1.0
|
||||
- **序列化**: Serde + Serde JSON
|
||||
- **数据库**: Sled (嵌入式KV数据库)
|
||||
- **加密**: SHA3-384 (NAC原生哈希算法)
|
||||
- **智能合约**: Charter语言
|
||||
|
||||
### 5.2 前端技术
|
||||
|
||||
- **框架**: React 18 + TypeScript
|
||||
- **构建工具**: Vite
|
||||
- **样式**: TailwindCSS
|
||||
- **状态管理**: Zustand
|
||||
- **图表**: TradingView Lightweight Charts
|
||||
- **WebSocket**: Socket.io-client
|
||||
|
||||
### 5.3 区块链技术
|
||||
|
||||
- **虚拟机**: NVM (NAC Virtual Machine)
|
||||
- **共识协议**: CBPP (Constitutional Byzantine Paxos Protocol)
|
||||
- **网络协议**: CSNP (Constitutional Secure Network Protocol)
|
||||
- **RPC协议**: NRPC4.0
|
||||
- **类型系统**: Address (32字节), Hash (48字节), Signature (96字节)
|
||||
|
||||
## 6. 安全设计
|
||||
|
||||
### 6.1 订单安全
|
||||
|
||||
- 所有订单必须使用用户私钥签名
|
||||
- 订单签名验证使用NAC原生签名算法
|
||||
- 防止重放攻击:订单包含时间戳和nonce
|
||||
- 订单有效期限制:超时自动取消
|
||||
|
||||
### 6.2 资产安全
|
||||
|
||||
- 资产转移必须通过Charter智能合约
|
||||
- 资产锁定机制防止双花
|
||||
- 多重签名支持(可选)
|
||||
- 冷热钱包分离
|
||||
|
||||
### 6.3 合规安全
|
||||
|
||||
- KYC数据加密存储
|
||||
- 敏感信息脱敏处理
|
||||
- 访问权限控制
|
||||
- 审计日志完整记录
|
||||
|
||||
## 7. 性能优化
|
||||
|
||||
### 7.1 撮合引擎优化
|
||||
|
||||
- 使用优先队列(BinaryHeap)实现订单簿
|
||||
- 订单索引优化:HashMap快速查找
|
||||
- 批量撮合:一次处理多个订单
|
||||
- 异步处理:撮合与结算并行
|
||||
|
||||
### 7.2 数据库优化
|
||||
|
||||
- 订单数据分片存储
|
||||
- 热数据内存缓存
|
||||
- 冷数据归档压缩
|
||||
- 索引优化:按资产ID、用户地址、时间建立索引
|
||||
|
||||
### 7.3 网络优化
|
||||
|
||||
- WebSocket推送实时行情
|
||||
- HTTP/2支持
|
||||
- 数据压缩传输
|
||||
- CDN加速静态资源
|
||||
|
||||
## 8. 监控与运维
|
||||
|
||||
### 8.1 监控指标
|
||||
|
||||
- 订单处理延迟
|
||||
- 撮合引擎TPS
|
||||
- 系统资源使用率
|
||||
- 错误率和成功率
|
||||
- 用户活跃度
|
||||
|
||||
### 8.2 告警机制
|
||||
|
||||
- 系统异常告警
|
||||
- 性能下降告警
|
||||
- 安全事件告警
|
||||
- 合规风险告警
|
||||
|
||||
### 8.3 日志管理
|
||||
|
||||
- 结构化日志
|
||||
- 日志分级:DEBUG, INFO, WARN, ERROR
|
||||
- 日志归档和清理
|
||||
- 日志分析和查询
|
||||
|
||||
## 9. 部署架构
|
||||
|
||||
### 9.1 服务部署
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 负载均衡器 (Nginx) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ API网关 (API Gateway) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌────────────────┬────────────────┬────────────────┐
|
||||
↓ ↓ ↓ ↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 交易服务实例1 │ │ 交易服务实例2 │ │ 交易服务实例3 │ │ 交易服务实例N │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘
|
||||
↓ ↓ ↓ ↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ 数据库集群 (Sled) │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
↓
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ NAC区块链节点集群 │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 9.2 容灾备份
|
||||
|
||||
- 主从数据库复制
|
||||
- 定期数据备份
|
||||
- 异地灾备
|
||||
- 快速故障切换
|
||||
|
||||
## 10. 开发计划
|
||||
|
||||
### 阶段1: 核心交易功能 (第1-2周)
|
||||
- 实现订单簿数据结构
|
||||
- 实现撮合引擎
|
||||
- 实现清算结算机制
|
||||
- 单元测试覆盖
|
||||
|
||||
### 阶段2: 合规功能 (第3周)
|
||||
- 实现KYC验证接口
|
||||
- 实现交易限额控制
|
||||
- 实现合规报告生成
|
||||
- 实现监管接口
|
||||
|
||||
### 阶段3: 前端界面 (第4周)
|
||||
- 设计交易界面
|
||||
- 实现行情展示
|
||||
- 实现交易操作
|
||||
- 实现用户资产管理
|
||||
|
||||
### 阶段4: 测试与文档 (第5周)
|
||||
- 集成测试
|
||||
- 性能测试
|
||||
- API文档
|
||||
- 用户手册
|
||||
|
||||
### 阶段5: 部署上线 (第6周)
|
||||
- 生产环境部署
|
||||
- 监控配置
|
||||
- 安全审计
|
||||
- 正式上线
|
||||
|
||||
## 11. 参考资料
|
||||
|
||||
- NAC公链技术白皮书
|
||||
- Charter智能合约语言规范
|
||||
- CBPP共识协议文档
|
||||
- NRPC4.0协议规范
|
||||
- ACC-20资产协议标准
|
||||
|
|
@ -1,475 +0,0 @@
|
|||
// NAC RWA Exchange - KYC验证模块
|
||||
|
||||
use crate::types::{Address, KYCStatus, RiskLevel, User};
|
||||
use chrono::Utc;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
|
||||
/// KYC错误
|
||||
#[derive(Error, Debug)]
|
||||
pub enum KYCError {
|
||||
#[error("User not found: {0}")]
|
||||
UserNotFound(Address),
|
||||
|
||||
#[error("KYC verification failed: {0}")]
|
||||
VerificationFailed(String),
|
||||
|
||||
#[error("User is blacklisted: {0}")]
|
||||
Blacklisted(Address),
|
||||
|
||||
#[error("KYC not verified: {0}")]
|
||||
NotVerified(Address),
|
||||
|
||||
#[error("Invalid KYC data: {0}")]
|
||||
InvalidData(String),
|
||||
}
|
||||
|
||||
/// KYC数据
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct KYCData {
|
||||
/// 用户地址
|
||||
pub address: Address,
|
||||
/// 真实姓名
|
||||
pub full_name: String,
|
||||
/// 身份证号
|
||||
pub id_number: String,
|
||||
/// 国籍
|
||||
pub nationality: String,
|
||||
/// 出生日期
|
||||
pub date_of_birth: String,
|
||||
/// 联系电话
|
||||
pub phone: String,
|
||||
/// 电子邮箱
|
||||
pub email: String,
|
||||
/// 居住地址
|
||||
pub residential_address: String,
|
||||
/// 身份证照片URL
|
||||
pub id_photo_url: Option<String>,
|
||||
/// 人脸识别照片URL
|
||||
pub face_photo_url: Option<String>,
|
||||
/// 提交时间
|
||||
pub submitted_at: i64,
|
||||
}
|
||||
|
||||
impl KYCData {
|
||||
/// 验证KYC数据完整性
|
||||
pub fn validate(&self) -> Result<(), KYCError> {
|
||||
if self.full_name.is_empty() {
|
||||
return Err(KYCError::InvalidData("Full name is required".to_string()));
|
||||
}
|
||||
if self.id_number.is_empty() {
|
||||
return Err(KYCError::InvalidData("ID number is required".to_string()));
|
||||
}
|
||||
if self.nationality.is_empty() {
|
||||
return Err(KYCError::InvalidData("Nationality is required".to_string()));
|
||||
}
|
||||
if self.phone.is_empty() {
|
||||
return Err(KYCError::InvalidData("Phone is required".to_string()));
|
||||
}
|
||||
if self.email.is_empty() {
|
||||
return Err(KYCError::InvalidData("Email is required".to_string()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// KYC审核结果
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct KYCReviewResult {
|
||||
/// 用户地址
|
||||
pub address: Address,
|
||||
/// 审核状态
|
||||
pub status: KYCStatus,
|
||||
/// 风险等级
|
||||
pub risk_level: RiskLevel,
|
||||
/// 审核意见
|
||||
pub comments: Option<String>,
|
||||
/// 审核时间
|
||||
pub reviewed_at: i64,
|
||||
/// 审核人
|
||||
pub reviewer: Option<String>,
|
||||
}
|
||||
|
||||
/// KYC验证引擎
|
||||
pub struct KYCEngine {
|
||||
/// 用户KYC数据
|
||||
kyc_data: HashMap<Address, KYCData>,
|
||||
/// 用户信息
|
||||
users: HashMap<Address, User>,
|
||||
/// 黑名单
|
||||
blacklist: HashMap<Address, String>, // 地址 -> 原因
|
||||
/// 默认日交易限额
|
||||
default_daily_limit: u64,
|
||||
/// 默认月交易限额
|
||||
default_monthly_limit: u64,
|
||||
}
|
||||
|
||||
impl KYCEngine {
|
||||
/// 创建新的KYC引擎
|
||||
pub fn new(default_daily_limit: u64, default_monthly_limit: u64) -> Self {
|
||||
Self {
|
||||
kyc_data: HashMap::new(),
|
||||
users: HashMap::new(),
|
||||
blacklist: HashMap::new(),
|
||||
default_daily_limit,
|
||||
default_monthly_limit,
|
||||
}
|
||||
}
|
||||
|
||||
/// 提交KYC数据
|
||||
pub fn submit_kyc(&mut self, kyc_data: KYCData) -> Result<(), KYCError> {
|
||||
// 验证数据完整性
|
||||
kyc_data.validate()?;
|
||||
|
||||
// 检查是否在黑名单
|
||||
if self.blacklist.contains_key(&kyc_data.address) {
|
||||
return Err(KYCError::Blacklisted(kyc_data.address));
|
||||
}
|
||||
|
||||
// 保存KYC数据
|
||||
self.kyc_data.insert(kyc_data.address, kyc_data.clone());
|
||||
|
||||
// 创建或更新用户
|
||||
let user = self.users.entry(kyc_data.address).or_insert_with(|| User {
|
||||
address: kyc_data.address,
|
||||
kyc_status: KYCStatus::NotVerified,
|
||||
risk_level: RiskLevel::Medium,
|
||||
daily_limit: self.default_daily_limit,
|
||||
monthly_limit: self.default_monthly_limit,
|
||||
daily_volume: 0,
|
||||
monthly_volume: 0,
|
||||
is_blacklisted: false,
|
||||
created_at: Utc::now().timestamp(),
|
||||
updated_at: Utc::now().timestamp(),
|
||||
});
|
||||
|
||||
// 更新KYC状态为审核中
|
||||
user.kyc_status = KYCStatus::Pending;
|
||||
user.updated_at = Utc::now().timestamp();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 审核KYC
|
||||
pub fn review_kyc(&mut self, result: KYCReviewResult) -> Result<User, KYCError> {
|
||||
// 检查KYC数据是否存在
|
||||
if !self.kyc_data.contains_key(&result.address) {
|
||||
return Err(KYCError::UserNotFound(result.address));
|
||||
}
|
||||
|
||||
// 获取用户
|
||||
let user = self
|
||||
.users
|
||||
.get_mut(&result.address)
|
||||
.ok_or(KYCError::UserNotFound(result.address))?;
|
||||
|
||||
// 更新KYC状态
|
||||
user.kyc_status = result.status;
|
||||
user.risk_level = result.risk_level;
|
||||
user.updated_at = Utc::now().timestamp();
|
||||
|
||||
// 根据风险等级调整交易限额
|
||||
match result.risk_level {
|
||||
RiskLevel::Low => {
|
||||
user.daily_limit = self.default_daily_limit * 2;
|
||||
user.monthly_limit = self.default_monthly_limit * 2;
|
||||
}
|
||||
RiskLevel::Medium => {
|
||||
user.daily_limit = self.default_daily_limit;
|
||||
user.monthly_limit = self.default_monthly_limit;
|
||||
}
|
||||
RiskLevel::High => {
|
||||
user.daily_limit = self.default_daily_limit / 2;
|
||||
user.monthly_limit = self.default_monthly_limit / 2;
|
||||
}
|
||||
RiskLevel::Critical => {
|
||||
user.daily_limit = 0;
|
||||
user.monthly_limit = 0;
|
||||
// 加入黑名单
|
||||
self.blacklist.insert(
|
||||
result.address,
|
||||
result.comments.unwrap_or_else(|| "High risk user".to_string()),
|
||||
);
|
||||
user.is_blacklisted = true;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(user.clone())
|
||||
}
|
||||
|
||||
/// 验证用户KYC状态
|
||||
pub fn verify_user(&self, address: &Address) -> Result<&User, KYCError> {
|
||||
let user = self
|
||||
.users
|
||||
.get(address)
|
||||
.ok_or(KYCError::UserNotFound(*address))?;
|
||||
|
||||
// 检查黑名单
|
||||
if user.is_blacklisted {
|
||||
return Err(KYCError::Blacklisted(*address));
|
||||
}
|
||||
|
||||
// 检查KYC状态
|
||||
if user.kyc_status != KYCStatus::Verified {
|
||||
return Err(KYCError::NotVerified(*address));
|
||||
}
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
/// 获取用户信息
|
||||
pub fn get_user(&self, address: &Address) -> Option<&User> {
|
||||
self.users.get(address)
|
||||
}
|
||||
|
||||
/// 获取KYC数据
|
||||
pub fn get_kyc_data(&self, address: &Address) -> Option<&KYCData> {
|
||||
self.kyc_data.get(address)
|
||||
}
|
||||
|
||||
/// 添加到黑名单
|
||||
pub fn add_to_blacklist(&mut self, address: Address, reason: String) -> Result<(), KYCError> {
|
||||
self.blacklist.insert(address, reason);
|
||||
|
||||
if let Some(user) = self.users.get_mut(&address) {
|
||||
user.is_blacklisted = true;
|
||||
user.daily_limit = 0;
|
||||
user.monthly_limit = 0;
|
||||
user.updated_at = Utc::now().timestamp();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 从黑名单移除
|
||||
pub fn remove_from_blacklist(&mut self, address: &Address) -> Result<(), KYCError> {
|
||||
self.blacklist.remove(address);
|
||||
|
||||
if let Some(user) = self.users.get_mut(address) {
|
||||
user.is_blacklisted = false;
|
||||
user.daily_limit = self.default_daily_limit;
|
||||
user.monthly_limit = self.default_monthly_limit;
|
||||
user.updated_at = Utc::now().timestamp();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 检查是否在黑名单
|
||||
pub fn is_blacklisted(&self, address: &Address) -> bool {
|
||||
self.blacklist.contains_key(address)
|
||||
}
|
||||
|
||||
/// 获取黑名单原因
|
||||
pub fn get_blacklist_reason(&self, address: &Address) -> Option<&String> {
|
||||
self.blacklist.get(address)
|
||||
}
|
||||
|
||||
/// 获取所有待审核的KYC
|
||||
pub fn get_pending_kyc(&self) -> Vec<(Address, KYCData)> {
|
||||
self.users
|
||||
.iter()
|
||||
.filter(|(_, user)| user.kyc_status == KYCStatus::Pending)
|
||||
.filter_map(|(addr, _)| {
|
||||
self.kyc_data
|
||||
.get(addr)
|
||||
.map(|data| (*addr, data.clone()))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn create_test_kyc_data(address: Address) -> KYCData {
|
||||
KYCData {
|
||||
address,
|
||||
full_name: "Zhang San".to_string(),
|
||||
id_number: "110101199001011234".to_string(),
|
||||
nationality: "CN".to_string(),
|
||||
date_of_birth: "1990-01-01".to_string(),
|
||||
phone: "+86 138 0000 0000".to_string(),
|
||||
email: "zhangsan@example.com".to_string(),
|
||||
residential_address: "Beijing, China".to_string(),
|
||||
id_photo_url: Some("https://example.com/id.jpg".to_string()),
|
||||
face_photo_url: Some("https://example.com/face.jpg".to_string()),
|
||||
submitted_at: Utc::now().timestamp(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kyc_engine_creation() {
|
||||
let engine = KYCEngine::new(100000, 1000000);
|
||||
assert_eq!(engine.default_daily_limit, 100000);
|
||||
assert_eq!(engine.default_monthly_limit, 1000000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_submit_kyc() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
assert!(engine.submit_kyc(kyc_data.clone()).is_ok());
|
||||
|
||||
let user = engine.get_user(&address).unwrap();
|
||||
assert_eq!(user.kyc_status, KYCStatus::Pending);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_review_kyc_approved() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
|
||||
let review_result = KYCReviewResult {
|
||||
address,
|
||||
status: KYCStatus::Verified,
|
||||
risk_level: RiskLevel::Low,
|
||||
comments: Some("Approved".to_string()),
|
||||
reviewed_at: Utc::now().timestamp(),
|
||||
reviewer: Some("Admin".to_string()),
|
||||
};
|
||||
|
||||
let user = engine.review_kyc(review_result).unwrap();
|
||||
assert_eq!(user.kyc_status, KYCStatus::Verified);
|
||||
assert_eq!(user.risk_level, RiskLevel::Low);
|
||||
assert_eq!(user.daily_limit, 200000); // 低风险用户限额翻倍
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_review_kyc_rejected() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
|
||||
let review_result = KYCReviewResult {
|
||||
address,
|
||||
status: KYCStatus::Rejected,
|
||||
risk_level: RiskLevel::High,
|
||||
comments: Some("Invalid documents".to_string()),
|
||||
reviewed_at: Utc::now().timestamp(),
|
||||
reviewer: Some("Admin".to_string()),
|
||||
};
|
||||
|
||||
let user = engine.review_kyc(review_result).unwrap();
|
||||
assert_eq!(user.kyc_status, KYCStatus::Rejected);
|
||||
assert_eq!(user.risk_level, RiskLevel::High);
|
||||
assert_eq!(user.daily_limit, 50000); // 高风险用户限额减半
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_review_kyc_critical_risk() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
|
||||
let review_result = KYCReviewResult {
|
||||
address,
|
||||
status: KYCStatus::Rejected,
|
||||
risk_level: RiskLevel::Critical,
|
||||
comments: Some("Fraud detected".to_string()),
|
||||
reviewed_at: Utc::now().timestamp(),
|
||||
reviewer: Some("Admin".to_string()),
|
||||
};
|
||||
|
||||
let user = engine.review_kyc(review_result).unwrap();
|
||||
assert_eq!(user.daily_limit, 0); // 极高风险用户限额为0
|
||||
assert!(user.is_blacklisted);
|
||||
assert!(engine.is_blacklisted(&address));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_user_success() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
|
||||
let review_result = KYCReviewResult {
|
||||
address,
|
||||
status: KYCStatus::Verified,
|
||||
risk_level: RiskLevel::Low,
|
||||
comments: None,
|
||||
reviewed_at: Utc::now().timestamp(),
|
||||
reviewer: None,
|
||||
};
|
||||
|
||||
engine.review_kyc(review_result).unwrap();
|
||||
|
||||
let result = engine.verify_user(&address);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_verify_user_not_verified() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
|
||||
let result = engine.verify_user(&address);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_blacklist_operations() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
|
||||
// 添加到黑名单
|
||||
engine
|
||||
.add_to_blacklist(address, "Test reason".to_string())
|
||||
.unwrap();
|
||||
assert!(engine.is_blacklisted(&address));
|
||||
assert_eq!(
|
||||
engine.get_blacklist_reason(&address).unwrap(),
|
||||
"Test reason"
|
||||
);
|
||||
|
||||
// 从黑名单移除
|
||||
engine.remove_from_blacklist(&address).unwrap();
|
||||
assert!(!engine.is_blacklisted(&address));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_pending_kyc() {
|
||||
let mut engine = KYCEngine::new(100000, 1000000);
|
||||
|
||||
// 提交3个KYC
|
||||
for i in 0..3 {
|
||||
let mut address_bytes = [0u8; 32];
|
||||
address_bytes[0] = i + 1;
|
||||
let address = Address::new(address_bytes);
|
||||
let kyc_data = create_test_kyc_data(address);
|
||||
engine.submit_kyc(kyc_data).unwrap();
|
||||
}
|
||||
|
||||
let pending = engine.get_pending_kyc();
|
||||
assert_eq!(pending.len(), 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_kyc_data_validation() {
|
||||
let address = Address::new([1u8; 32]);
|
||||
let mut kyc_data = create_test_kyc_data(address);
|
||||
|
||||
// 有效数据
|
||||
assert!(kyc_data.validate().is_ok());
|
||||
|
||||
// 缺少姓名
|
||||
kyc_data.full_name = String::new();
|
||||
assert!(kyc_data.validate().is_err());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,485 +0,0 @@
|
|||
// NAC RWA Exchange - 交易限额控制模块
|
||||
|
||||
use crate::types::{Address, Trade, User};
|
||||
use chrono::{DateTime, Datelike, Utc};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
|
||||
/// 限额错误
|
||||
#[derive(Error, Debug)]
|
||||
pub enum LimitError {
|
||||
#[error("Daily limit exceeded for {0}: limit {1}, current {2}, attempted {3}")]
|
||||
DailyLimitExceeded(Address, u64, u64, u64),
|
||||
|
||||
#[error("Monthly limit exceeded for {0}: limit {1}, current {2}, attempted {3}")]
|
||||
MonthlyLimitExceeded(Address, u64, u64, u64),
|
||||
|
||||
#[error("Single transaction limit exceeded: limit {0}, attempted {1}")]
|
||||
SingleTransactionLimitExceeded(u64, u64),
|
||||
|
||||
#[error("User not found: {0}")]
|
||||
UserNotFound(Address),
|
||||
|
||||
#[error("User is suspended: {0}")]
|
||||
UserSuspended(Address),
|
||||
}
|
||||
|
||||
/// 交易统计
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct TradingStats {
|
||||
/// 用户地址
|
||||
pub address: Address,
|
||||
/// 日累计交易量
|
||||
pub daily_volume: u64,
|
||||
/// 月累计交易量
|
||||
pub monthly_volume: u64,
|
||||
/// 日交易次数
|
||||
pub daily_count: u64,
|
||||
/// 月交易次数
|
||||
pub monthly_count: u64,
|
||||
/// 最后交易时间
|
||||
pub last_trade_time: i64,
|
||||
/// 统计日期(YYYYMMDD)
|
||||
pub stats_date: i32,
|
||||
/// 统计月份(YYYYMM)
|
||||
pub stats_month: i32,
|
||||
}
|
||||
|
||||
impl TradingStats {
|
||||
pub fn new(address: Address) -> Self {
|
||||
let now = Utc::now();
|
||||
Self {
|
||||
address,
|
||||
daily_volume: 0,
|
||||
monthly_volume: 0,
|
||||
daily_count: 0,
|
||||
monthly_count: 0,
|
||||
last_trade_time: now.timestamp(),
|
||||
stats_date: Self::get_date_key(&now),
|
||||
stats_month: Self::get_month_key(&now),
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取日期键(YYYYMMDD)
|
||||
fn get_date_key(dt: &DateTime<Utc>) -> i32 {
|
||||
dt.year() * 10000 + dt.month() as i32 * 100 + dt.day() as i32
|
||||
}
|
||||
|
||||
/// 获取月份键(YYYYMM)
|
||||
fn get_month_key(dt: &DateTime<Utc>) -> i32 {
|
||||
dt.year() * 100 + dt.month() as i32
|
||||
}
|
||||
|
||||
/// 检查是否需要重置日统计
|
||||
pub fn should_reset_daily(&self) -> bool {
|
||||
let now = Utc::now();
|
||||
Self::get_date_key(&now) != self.stats_date
|
||||
}
|
||||
|
||||
/// 检查是否需要重置月统计
|
||||
pub fn should_reset_monthly(&self) -> bool {
|
||||
let now = Utc::now();
|
||||
Self::get_month_key(&now) != self.stats_month
|
||||
}
|
||||
|
||||
/// 重置日统计
|
||||
pub fn reset_daily(&mut self) {
|
||||
let now = Utc::now();
|
||||
self.daily_volume = 0;
|
||||
self.daily_count = 0;
|
||||
self.stats_date = Self::get_date_key(&now);
|
||||
}
|
||||
|
||||
/// 重置月统计
|
||||
pub fn reset_monthly(&mut self) {
|
||||
let now = Utc::now();
|
||||
self.monthly_volume = 0;
|
||||
self.monthly_count = 0;
|
||||
self.stats_month = Self::get_month_key(&now);
|
||||
}
|
||||
|
||||
/// 更新统计
|
||||
pub fn update(&mut self, amount: u64) {
|
||||
// 检查是否需要重置
|
||||
if self.should_reset_daily() {
|
||||
self.reset_daily();
|
||||
}
|
||||
if self.should_reset_monthly() {
|
||||
self.reset_monthly();
|
||||
}
|
||||
|
||||
// 更新统计
|
||||
self.daily_volume += amount;
|
||||
self.monthly_volume += amount;
|
||||
self.daily_count += 1;
|
||||
self.monthly_count += 1;
|
||||
self.last_trade_time = Utc::now().timestamp();
|
||||
}
|
||||
}
|
||||
|
||||
/// 限额控制引擎
|
||||
pub struct LimitEngine {
|
||||
/// 用户信息
|
||||
users: HashMap<Address, User>,
|
||||
/// 交易统计
|
||||
stats: HashMap<Address, TradingStats>,
|
||||
/// 单笔交易限额
|
||||
single_transaction_limit: u64,
|
||||
/// 是否启用限额控制
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
impl LimitEngine {
|
||||
/// 创建新的限额控制引擎
|
||||
pub fn new(single_transaction_limit: u64) -> Self {
|
||||
Self {
|
||||
users: HashMap::new(),
|
||||
stats: HashMap::new(),
|
||||
single_transaction_limit,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置用户信息
|
||||
pub fn set_user(&mut self, user: User) {
|
||||
self.users.insert(user.address, user);
|
||||
}
|
||||
|
||||
/// 获取用户信息
|
||||
pub fn get_user(&self, address: &Address) -> Option<&User> {
|
||||
self.users.get(address)
|
||||
}
|
||||
|
||||
/// 获取交易统计
|
||||
pub fn get_stats(&mut self, address: &Address) -> &mut TradingStats {
|
||||
self.stats
|
||||
.entry(*address)
|
||||
.or_insert_with(|| TradingStats::new(*address))
|
||||
}
|
||||
|
||||
/// 启用限额控制
|
||||
pub fn enable(&mut self) {
|
||||
self.enabled = true;
|
||||
}
|
||||
|
||||
/// 禁用限额控制
|
||||
pub fn disable(&mut self) {
|
||||
self.enabled = false;
|
||||
}
|
||||
|
||||
/// 检查交易是否超过限额
|
||||
pub fn check_trade(&mut self, address: &Address, amount: u64) -> Result<(), LimitError> {
|
||||
// 如果禁用限额控制,直接通过
|
||||
if !self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// 获取用户信息
|
||||
let user = self
|
||||
.users
|
||||
.get(address)
|
||||
.ok_or(LimitError::UserNotFound(*address))?;
|
||||
|
||||
// 检查用户是否被暂停
|
||||
if user.is_blacklisted {
|
||||
return Err(LimitError::UserSuspended(*address));
|
||||
}
|
||||
|
||||
// 检查单笔交易限额
|
||||
if amount > self.single_transaction_limit {
|
||||
return Err(LimitError::SingleTransactionLimitExceeded(
|
||||
self.single_transaction_limit,
|
||||
amount,
|
||||
));
|
||||
}
|
||||
|
||||
// 复制限额值
|
||||
let daily_limit = user.daily_limit;
|
||||
let monthly_limit = user.monthly_limit;
|
||||
|
||||
// 获取交易统计
|
||||
let stats = self.get_stats(address);
|
||||
|
||||
// 检查日限额
|
||||
if stats.daily_volume + amount > daily_limit {
|
||||
return Err(LimitError::DailyLimitExceeded(
|
||||
*address,
|
||||
daily_limit,
|
||||
stats.daily_volume,
|
||||
amount,
|
||||
));
|
||||
}
|
||||
|
||||
// 检查月限额
|
||||
if stats.monthly_volume + amount > monthly_limit {
|
||||
return Err(LimitError::MonthlyLimitExceeded(
|
||||
*address,
|
||||
monthly_limit,
|
||||
stats.monthly_volume,
|
||||
amount,
|
||||
));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 记录交易
|
||||
pub fn record_trade(&mut self, address: &Address, amount: u64) {
|
||||
let stats = self.get_stats(address);
|
||||
stats.update(amount);
|
||||
}
|
||||
|
||||
/// 检查并记录交易
|
||||
pub fn check_and_record_trade(
|
||||
&mut self,
|
||||
address: &Address,
|
||||
amount: u64,
|
||||
) -> Result<(), LimitError> {
|
||||
self.check_trade(address, amount)?;
|
||||
self.record_trade(address, amount);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 检查交易双方限额
|
||||
pub fn check_trade_parties(&mut self, trade: &Trade) -> Result<(), LimitError> {
|
||||
// 检查买方限额
|
||||
self.check_trade(&trade.buyer, trade.total_amount + trade.fee)?;
|
||||
|
||||
// 检查卖方限额
|
||||
self.check_trade(&trade.seller, trade.total_amount)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 记录交易双方
|
||||
pub fn record_trade_parties(&mut self, trade: &Trade) {
|
||||
// 记录买方交易
|
||||
self.record_trade(&trade.buyer, trade.total_amount + trade.fee);
|
||||
|
||||
// 记录卖方交易
|
||||
self.record_trade(&trade.seller, trade.total_amount);
|
||||
}
|
||||
|
||||
/// 更新用户限额
|
||||
pub fn update_user_limits(
|
||||
&mut self,
|
||||
address: &Address,
|
||||
daily_limit: u64,
|
||||
monthly_limit: u64,
|
||||
) -> Result<(), LimitError> {
|
||||
let user = self
|
||||
.users
|
||||
.get_mut(address)
|
||||
.ok_or(LimitError::UserNotFound(*address))?;
|
||||
|
||||
user.daily_limit = daily_limit;
|
||||
user.monthly_limit = monthly_limit;
|
||||
user.updated_at = Utc::now().timestamp();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 重置用户统计
|
||||
pub fn reset_user_stats(&mut self, address: &Address) {
|
||||
if let Some(stats) = self.stats.get_mut(address) {
|
||||
stats.reset_daily();
|
||||
stats.reset_monthly();
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取所有用户统计
|
||||
pub fn get_all_stats(&self) -> Vec<(&Address, &TradingStats)> {
|
||||
self.stats.iter().collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::{KYCStatus, RiskLevel};
|
||||
|
||||
fn create_test_user(address: Address, daily_limit: u64, monthly_limit: u64) -> User {
|
||||
User {
|
||||
address,
|
||||
kyc_status: KYCStatus::Verified,
|
||||
risk_level: RiskLevel::Low,
|
||||
daily_limit,
|
||||
monthly_limit,
|
||||
daily_volume: 0,
|
||||
monthly_volume: 0,
|
||||
is_blacklisted: false,
|
||||
created_at: Utc::now().timestamp(),
|
||||
updated_at: Utc::now().timestamp(),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_limit_engine_creation() {
|
||||
let engine = LimitEngine::new(100000);
|
||||
assert_eq!(engine.single_transaction_limit, 100000);
|
||||
assert!(engine.enabled);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_success() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
let result = engine.check_trade(&address, 50000);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_single_limit_exceeded() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
let result = engine.check_trade(&address, 150000);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_daily_limit_exceeded() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 200000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
// 第一笔交易
|
||||
engine.check_and_record_trade(&address, 100000).unwrap();
|
||||
|
||||
// 第二笔交易
|
||||
engine.check_and_record_trade(&address, 50000).unwrap();
|
||||
|
||||
// 第三笔交易应该超过日限额
|
||||
let result = engine.check_trade(&address, 60000);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_monthly_limit_exceeded() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 200000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
// 第一笔交易
|
||||
engine.check_and_record_trade(&address, 100000).unwrap();
|
||||
|
||||
// 第二笔交易
|
||||
engine.check_and_record_trade(&address, 50000).unwrap();
|
||||
|
||||
// 第三笔交易应该超过月限额
|
||||
let result = engine.check_trade(&address, 60000);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_user_suspended() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let mut user = create_test_user(address, 500000, 5000000);
|
||||
user.is_blacklisted = true;
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
let result = engine.check_trade(&address, 50000);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_check_trade_disabled() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
|
||||
// 禁用限额控制
|
||||
engine.disable();
|
||||
|
||||
// 即使没有用户信息,也应该通过
|
||||
let result = engine.check_trade(&address, 50000);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_record_trade() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
// 记录交易
|
||||
engine.record_trade(&address, 50000);
|
||||
|
||||
let stats = engine.get_stats(&address);
|
||||
assert_eq!(stats.daily_volume, 50000);
|
||||
assert_eq!(stats.monthly_volume, 50000);
|
||||
assert_eq!(stats.daily_count, 1);
|
||||
assert_eq!(stats.monthly_count, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_user_limits() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
// 更新限额
|
||||
engine
|
||||
.update_user_limits(&address, 1000000, 10000000)
|
||||
.unwrap();
|
||||
|
||||
let user = engine.get_user(&address).unwrap();
|
||||
assert_eq!(user.daily_limit, 1000000);
|
||||
assert_eq!(user.monthly_limit, 10000000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trading_stats_reset() {
|
||||
let address = Address::new([1u8; 32]);
|
||||
let mut stats = TradingStats::new(address);
|
||||
|
||||
// 更新统计
|
||||
stats.update(50000);
|
||||
assert_eq!(stats.daily_volume, 50000);
|
||||
assert_eq!(stats.monthly_volume, 50000);
|
||||
|
||||
// 重置日统计
|
||||
stats.reset_daily();
|
||||
assert_eq!(stats.daily_volume, 0);
|
||||
assert_eq!(stats.monthly_volume, 50000); // 月统计不变
|
||||
|
||||
// 重置月统计
|
||||
stats.reset_monthly();
|
||||
assert_eq!(stats.monthly_volume, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_reset_user_stats() {
|
||||
let mut engine = LimitEngine::new(100000);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let user = create_test_user(address, 500000, 5000000);
|
||||
|
||||
engine.set_user(user);
|
||||
|
||||
// 记录交易
|
||||
engine.record_trade(&address, 50000);
|
||||
|
||||
// 重置统计
|
||||
engine.reset_user_stats(&address);
|
||||
|
||||
let stats = engine.get_stats(&address);
|
||||
assert_eq!(stats.daily_volume, 0);
|
||||
assert_eq!(stats.monthly_volume, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
// NAC RWA Exchange - 合规模块
|
||||
|
||||
pub mod kyc;
|
||||
pub mod limits;
|
||||
|
||||
pub use kyc::{KYCData, KYCEngine, KYCError, KYCReviewResult};
|
||||
pub use limits::{LimitEngine, LimitError, TradingStats};
|
||||
|
|
@ -1,559 +0,0 @@
|
|||
// NAC RWA Exchange - 撮合引擎模块
|
||||
|
||||
use crate::engine::orderbook::OrderBook;
|
||||
use crate::types::{
|
||||
Address, AssetId, Hash, Order, OrderId, OrderStatus, OrderType, PriceType, Trade, TradeId,
|
||||
TradeStatus,
|
||||
};
|
||||
use chrono::Utc;
|
||||
use std::collections::HashMap;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// 撮合结果
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MatchResult {
|
||||
/// 成交记录列表
|
||||
pub trades: Vec<Trade>,
|
||||
/// 更新的订单列表
|
||||
pub updated_orders: Vec<Order>,
|
||||
}
|
||||
|
||||
/// 撮合引擎
|
||||
pub struct MatchingEngine {
|
||||
/// 订单簿集合(按资产ID索引)
|
||||
orderbooks: HashMap<AssetId, OrderBook>,
|
||||
/// 手续费率(基点,1基点=0.01%)
|
||||
fee_rate_bps: u64,
|
||||
}
|
||||
|
||||
impl MatchingEngine {
|
||||
/// 创建新的撮合引擎
|
||||
pub fn new(fee_rate_bps: u64) -> Self {
|
||||
Self {
|
||||
orderbooks: HashMap::new(),
|
||||
fee_rate_bps,
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取或创建订单簿
|
||||
fn get_or_create_orderbook(&mut self, asset_id: AssetId) -> &mut OrderBook {
|
||||
self.orderbooks
|
||||
.entry(asset_id)
|
||||
.or_insert_with(|| OrderBook::new(asset_id))
|
||||
}
|
||||
|
||||
/// 获取订单簿
|
||||
pub fn get_orderbook(&self, asset_id: &AssetId) -> Option<&OrderBook> {
|
||||
self.orderbooks.get(asset_id)
|
||||
}
|
||||
|
||||
/// 添加订单并尝试撮合
|
||||
pub fn add_order(&mut self, order: Order) -> Result<MatchResult, String> {
|
||||
// 验证订单
|
||||
self.validate_order(&order)?;
|
||||
|
||||
let asset_id = order.asset_id;
|
||||
let order_type = order.order_type;
|
||||
|
||||
// 获取或创建订单簿
|
||||
self.get_or_create_orderbook(asset_id);
|
||||
|
||||
// 尝试撒合
|
||||
let fee_rate_bps = self.fee_rate_bps;
|
||||
let result = match order_type {
|
||||
OrderType::Buy => {
|
||||
let orderbook = self.orderbooks.get_mut(&asset_id).unwrap();
|
||||
Self::match_buy_order(orderbook, order, fee_rate_bps)?
|
||||
}
|
||||
OrderType::Sell => {
|
||||
let orderbook = self.orderbooks.get_mut(&asset_id).unwrap();
|
||||
Self::match_sell_order(orderbook, order, fee_rate_bps)?
|
||||
}
|
||||
};
|
||||
|
||||
// 清理订单簿
|
||||
let orderbook = self.orderbooks.get_mut(&asset_id).unwrap();
|
||||
orderbook.cleanup();
|
||||
|
||||
// 如果订单未完全成交,添加到订单簿
|
||||
if let Some(remaining_order) = result
|
||||
.updated_orders
|
||||
.iter()
|
||||
.find(|o| o.is_matchable())
|
||||
.cloned()
|
||||
{
|
||||
let orderbook = self.orderbooks.get_mut(&asset_id).unwrap();
|
||||
orderbook.add_order(remaining_order)?;
|
||||
}
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// 撒合买单
|
||||
fn match_buy_order(
|
||||
orderbook: &mut OrderBook,
|
||||
mut buy_order: Order,
|
||||
fee_rate_bps: u64,
|
||||
) -> Result<MatchResult, String> {
|
||||
let mut trades = Vec::new();
|
||||
let mut updated_orders = Vec::new();
|
||||
|
||||
// 持续撮合直到买单完全成交或没有可匹配的卖单
|
||||
while buy_order.is_matchable() {
|
||||
// 获取最优卖单
|
||||
let best_sell = match orderbook.best_sell_order() {
|
||||
Some(order) => order.clone(),
|
||||
None => break, // 没有卖单,退出
|
||||
};
|
||||
|
||||
// 检查价格是否匹配
|
||||
let can_match = match buy_order.price_type {
|
||||
PriceType::Limit => buy_order.price >= best_sell.price,
|
||||
PriceType::Market => true, // 市价单总是匹配
|
||||
};
|
||||
|
||||
if !can_match {
|
||||
break; // 价格不匹配,退出
|
||||
}
|
||||
|
||||
// 计算成交数量
|
||||
let buy_remaining = buy_order.remaining_quantity();
|
||||
let sell_remaining = best_sell.remaining_quantity();
|
||||
let match_quantity = buy_remaining.min(sell_remaining);
|
||||
|
||||
// 计算成交价格(使用卖单价格)
|
||||
let match_price = best_sell.price;
|
||||
|
||||
// 创建交易记录
|
||||
let trade = Self::create_trade_with_fee(
|
||||
&buy_order,
|
||||
&best_sell,
|
||||
match_price,
|
||||
match_quantity,
|
||||
fee_rate_bps,
|
||||
);
|
||||
trades.push(trade);
|
||||
|
||||
// 更新买单
|
||||
buy_order.filled_quantity += match_quantity;
|
||||
if buy_order.is_fully_filled() {
|
||||
buy_order.status = OrderStatus::Filled;
|
||||
} else {
|
||||
buy_order.status = OrderStatus::PartialFilled;
|
||||
}
|
||||
buy_order.updated_at = Utc::now().timestamp();
|
||||
|
||||
// 更新卖单
|
||||
let mut updated_sell = best_sell.clone();
|
||||
updated_sell.filled_quantity += match_quantity;
|
||||
if updated_sell.is_fully_filled() {
|
||||
updated_sell.status = OrderStatus::Filled;
|
||||
} else {
|
||||
updated_sell.status = OrderStatus::PartialFilled;
|
||||
}
|
||||
updated_sell.updated_at = Utc::now().timestamp();
|
||||
|
||||
// 从订单簿中移除卖单
|
||||
orderbook.remove_order(&updated_sell.id)?;
|
||||
|
||||
// 如果卖单未完全成交,重新添加到订单簿
|
||||
if updated_sell.is_matchable() {
|
||||
orderbook.add_order(updated_sell.clone())?;
|
||||
}
|
||||
|
||||
updated_orders.push(updated_sell);
|
||||
}
|
||||
|
||||
updated_orders.push(buy_order);
|
||||
|
||||
Ok(MatchResult {
|
||||
trades,
|
||||
updated_orders,
|
||||
})
|
||||
}
|
||||
|
||||
/// 撒合卖单
|
||||
fn match_sell_order(
|
||||
orderbook: &mut OrderBook,
|
||||
mut sell_order: Order,
|
||||
fee_rate_bps: u64,
|
||||
) -> Result<MatchResult, String> {
|
||||
let mut trades = Vec::new();
|
||||
let mut updated_orders = Vec::new();
|
||||
|
||||
// 持续撮合直到卖单完全成交或没有可匹配的买单
|
||||
while sell_order.is_matchable() {
|
||||
// 获取最优买单
|
||||
let best_buy = match orderbook.best_buy_order() {
|
||||
Some(order) => order.clone(),
|
||||
None => break, // 没有买单,退出
|
||||
};
|
||||
|
||||
// 检查价格是否匹配
|
||||
let can_match = match sell_order.price_type {
|
||||
PriceType::Limit => best_buy.price >= sell_order.price,
|
||||
PriceType::Market => true, // 市价单总是匹配
|
||||
};
|
||||
|
||||
if !can_match {
|
||||
break; // 价格不匹配,退出
|
||||
}
|
||||
|
||||
// 计算成交数量
|
||||
let sell_remaining = sell_order.remaining_quantity();
|
||||
let buy_remaining = best_buy.remaining_quantity();
|
||||
let match_quantity = sell_remaining.min(buy_remaining);
|
||||
|
||||
// 计算成交价格(使用买单价格)
|
||||
let match_price = best_buy.price;
|
||||
|
||||
// 创建交易记录
|
||||
let trade = Self::create_trade_with_fee(
|
||||
&best_buy,
|
||||
&sell_order,
|
||||
match_price,
|
||||
match_quantity,
|
||||
fee_rate_bps,
|
||||
);
|
||||
trades.push(trade);
|
||||
|
||||
// 更新卖单
|
||||
sell_order.filled_quantity += match_quantity;
|
||||
if sell_order.is_fully_filled() {
|
||||
sell_order.status = OrderStatus::Filled;
|
||||
} else {
|
||||
sell_order.status = OrderStatus::PartialFilled;
|
||||
}
|
||||
sell_order.updated_at = Utc::now().timestamp();
|
||||
|
||||
// 更新买单
|
||||
let mut updated_buy = best_buy.clone();
|
||||
updated_buy.filled_quantity += match_quantity;
|
||||
if updated_buy.is_fully_filled() {
|
||||
updated_buy.status = OrderStatus::Filled;
|
||||
} else {
|
||||
updated_buy.status = OrderStatus::PartialFilled;
|
||||
}
|
||||
updated_buy.updated_at = Utc::now().timestamp();
|
||||
|
||||
// 从订单簿中移除买单
|
||||
orderbook.remove_order(&updated_buy.id)?;
|
||||
|
||||
// 如果买单未完全成交,重新添加到订单簿
|
||||
if updated_buy.is_matchable() {
|
||||
orderbook.add_order(updated_buy.clone())?;
|
||||
}
|
||||
|
||||
updated_orders.push(updated_buy);
|
||||
}
|
||||
|
||||
updated_orders.push(sell_order);
|
||||
|
||||
Ok(MatchResult {
|
||||
trades,
|
||||
updated_orders,
|
||||
})
|
||||
}
|
||||
|
||||
/// 创建交易记录
|
||||
fn create_trade_with_fee(
|
||||
buy_order: &Order,
|
||||
sell_order: &Order,
|
||||
price: u64,
|
||||
quantity: u64,
|
||||
fee_rate_bps: u64,
|
||||
) -> Trade {
|
||||
let total_amount = price * quantity;
|
||||
let fee = Self::calculate_fee_static(total_amount, fee_rate_bps);
|
||||
|
||||
Trade {
|
||||
id: Uuid::new_v4(),
|
||||
buy_order_id: buy_order.id,
|
||||
sell_order_id: sell_order.id,
|
||||
buyer: buy_order.user_address,
|
||||
seller: sell_order.user_address,
|
||||
asset_id: buy_order.asset_id,
|
||||
price,
|
||||
quantity,
|
||||
total_amount,
|
||||
fee,
|
||||
status: TradeStatus::Pending,
|
||||
executed_at: Utc::now().timestamp(),
|
||||
settled_at: None,
|
||||
tx_hash: Hash::new([0u8; 48]), // 待链上确认后更新
|
||||
}
|
||||
}
|
||||
|
||||
/// 计算手续费
|
||||
fn calculate_fee(&self, amount: u64) -> u64 {
|
||||
Self::calculate_fee_static(amount, self.fee_rate_bps)
|
||||
}
|
||||
|
||||
/// 静态计算手续费
|
||||
fn calculate_fee_static(amount: u64, fee_rate_bps: u64) -> u64 {
|
||||
// 手续费 = 金额 * 费率 / 10000
|
||||
amount * fee_rate_bps / 10000
|
||||
}
|
||||
|
||||
/// 验证订单
|
||||
fn validate_order(&self, order: &Order) -> Result<(), String> {
|
||||
// 验证数量
|
||||
if order.quantity == 0 {
|
||||
return Err("Order quantity must be greater than 0".to_string());
|
||||
}
|
||||
|
||||
// 验证价格(限价单)
|
||||
if order.price_type == PriceType::Limit && order.price == 0 {
|
||||
return Err("Limit order price must be greater than 0".to_string());
|
||||
}
|
||||
|
||||
// 验证状态
|
||||
if !order.is_matchable() {
|
||||
return Err("Order is not matchable".to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 取消订单
|
||||
pub fn cancel_order(&mut self, asset_id: &AssetId, order_id: &OrderId) -> Result<Order, String> {
|
||||
let orderbook = self
|
||||
.orderbooks
|
||||
.get_mut(asset_id)
|
||||
.ok_or_else(|| "Order book not found".to_string())?;
|
||||
|
||||
let mut order = orderbook.remove_order(order_id)?;
|
||||
order.status = OrderStatus::Cancelled;
|
||||
order.updated_at = Utc::now().timestamp();
|
||||
|
||||
Ok(order)
|
||||
}
|
||||
|
||||
/// 获取订单
|
||||
pub fn get_order(&self, asset_id: &AssetId, order_id: &OrderId) -> Option<&Order> {
|
||||
self.orderbooks
|
||||
.get(asset_id)
|
||||
.and_then(|ob| ob.get_order(order_id))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::{Address, Signature};
|
||||
|
||||
fn create_test_order(
|
||||
order_type: OrderType,
|
||||
price: u64,
|
||||
quantity: u64,
|
||||
asset_id: AssetId,
|
||||
) -> Order {
|
||||
Order {
|
||||
id: Uuid::new_v4(),
|
||||
user_address: Address::new([0u8; 32]),
|
||||
asset_id,
|
||||
order_type,
|
||||
price_type: PriceType::Limit,
|
||||
price,
|
||||
quantity,
|
||||
filled_quantity: 0,
|
||||
status: OrderStatus::Pending,
|
||||
created_at: Utc::now().timestamp(),
|
||||
updated_at: Utc::now().timestamp(),
|
||||
signature: Signature::new([0u8; 96]),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_matching_engine_creation() {
|
||||
let engine = MatchingEngine::new(30); // 0.3% 手续费
|
||||
assert_eq!(engine.fee_rate_bps, 30);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calculate_fee() {
|
||||
let engine = MatchingEngine::new(30); // 0.3% 手续费
|
||||
let fee = engine.calculate_fee(10000);
|
||||
assert_eq!(fee, 30); // 10000 * 30 / 10000 = 30
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_buy_order_no_match() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
let order = create_test_order(OrderType::Buy, 100, 1000, asset_id);
|
||||
|
||||
let result = engine.add_order(order.clone()).unwrap();
|
||||
assert_eq!(result.trades.len(), 0); // 没有匹配
|
||||
assert_eq!(result.updated_orders.len(), 1);
|
||||
|
||||
// 订单应该在订单簿中
|
||||
let orderbook = engine.get_orderbook(&asset_id).unwrap();
|
||||
assert_eq!(orderbook.buy_order_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_sell_order_no_match() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
let order = create_test_order(OrderType::Sell, 100, 1000, asset_id);
|
||||
|
||||
let result = engine.add_order(order.clone()).unwrap();
|
||||
assert_eq!(result.trades.len(), 0); // 没有匹配
|
||||
assert_eq!(result.updated_orders.len(), 1);
|
||||
|
||||
// 订单应该在订单簿中
|
||||
let orderbook = engine.get_orderbook(&asset_id).unwrap();
|
||||
assert_eq!(orderbook.sell_order_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_match_buy_and_sell_full() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 先添加卖单
|
||||
let sell_order = create_test_order(OrderType::Sell, 100, 1000, asset_id);
|
||||
engine.add_order(sell_order.clone()).unwrap();
|
||||
|
||||
// 再添加买单(价格相同,数量相同)
|
||||
let buy_order = create_test_order(OrderType::Buy, 100, 1000, asset_id);
|
||||
let result = engine.add_order(buy_order.clone()).unwrap();
|
||||
|
||||
// 应该完全成交
|
||||
assert_eq!(result.trades.len(), 1);
|
||||
let trade = &result.trades[0];
|
||||
assert_eq!(trade.quantity, 1000);
|
||||
assert_eq!(trade.price, 100);
|
||||
|
||||
// 两个订单都应该完全成交
|
||||
assert_eq!(result.updated_orders.len(), 2);
|
||||
for order in &result.updated_orders {
|
||||
assert_eq!(order.status, OrderStatus::Filled);
|
||||
assert_eq!(order.filled_quantity, 1000);
|
||||
}
|
||||
|
||||
// 订单簿应该为空
|
||||
let orderbook = engine.get_orderbook(&asset_id).unwrap();
|
||||
assert_eq!(orderbook.buy_order_count(), 0);
|
||||
assert_eq!(orderbook.sell_order_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_match_buy_and_sell_partial() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 先添加卖单(数量1000)
|
||||
let sell_order = create_test_order(OrderType::Sell, 100, 1000, asset_id);
|
||||
engine.add_order(sell_order.clone()).unwrap();
|
||||
|
||||
// 再添加买单(数量500)
|
||||
let buy_order = create_test_order(OrderType::Buy, 100, 500, asset_id);
|
||||
let result = engine.add_order(buy_order.clone()).unwrap();
|
||||
|
||||
// 应该部分成交
|
||||
assert_eq!(result.trades.len(), 1);
|
||||
let trade = &result.trades[0];
|
||||
assert_eq!(trade.quantity, 500);
|
||||
|
||||
// 买单应该完全成交,卖单应该部分成交
|
||||
assert_eq!(result.updated_orders.len(), 2);
|
||||
let buy = result
|
||||
.updated_orders
|
||||
.iter()
|
||||
.find(|o| o.order_type == OrderType::Buy)
|
||||
.unwrap();
|
||||
let sell = result
|
||||
.updated_orders
|
||||
.iter()
|
||||
.find(|o| o.order_type == OrderType::Sell)
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(buy.status, OrderStatus::Filled);
|
||||
assert_eq!(buy.filled_quantity, 500);
|
||||
|
||||
assert_eq!(sell.status, OrderStatus::PartialFilled);
|
||||
assert_eq!(sell.filled_quantity, 500);
|
||||
|
||||
// 订单簿中应该还有剩余的卖单
|
||||
let orderbook = engine.get_orderbook(&asset_id).unwrap();
|
||||
assert_eq!(orderbook.sell_order_count(), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_match_multiple_orders() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 添加多个卖单
|
||||
engine
|
||||
.add_order(create_test_order(OrderType::Sell, 100, 300, asset_id))
|
||||
.unwrap();
|
||||
engine
|
||||
.add_order(create_test_order(OrderType::Sell, 101, 400, asset_id))
|
||||
.unwrap();
|
||||
engine
|
||||
.add_order(create_test_order(OrderType::Sell, 102, 500, asset_id))
|
||||
.unwrap();
|
||||
|
||||
// 添加一个大买单
|
||||
let buy_order = create_test_order(OrderType::Buy, 105, 1000, asset_id);
|
||||
let result = engine.add_order(buy_order).unwrap();
|
||||
|
||||
// 应该匹配3个卖单
|
||||
assert_eq!(result.trades.len(), 3);
|
||||
|
||||
// 验证成交数量
|
||||
let total_matched: u64 = result.trades.iter().map(|t| t.quantity).sum();
|
||||
assert_eq!(total_matched, 1000); // 300 + 400 + 300
|
||||
|
||||
// 买单应该完全成交
|
||||
let buy = result
|
||||
.updated_orders
|
||||
.iter()
|
||||
.find(|o| o.order_type == OrderType::Buy)
|
||||
.unwrap();
|
||||
assert_eq!(buy.status, OrderStatus::Filled);
|
||||
assert_eq!(buy.filled_quantity, 1000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_cancel_order() {
|
||||
let mut engine = MatchingEngine::new(30);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
let order = create_test_order(OrderType::Buy, 100, 1000, asset_id);
|
||||
let order_id = order.id;
|
||||
|
||||
engine.add_order(order).unwrap();
|
||||
|
||||
// 取消订单
|
||||
let cancelled = engine.cancel_order(&asset_id, &order_id).unwrap();
|
||||
assert_eq!(cancelled.status, OrderStatus::Cancelled);
|
||||
|
||||
// 订单应该不在订单簿中
|
||||
assert!(engine.get_order(&asset_id, &order_id).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_order_zero_quantity() {
|
||||
let engine = MatchingEngine::new(30);
|
||||
let mut order = create_test_order(OrderType::Buy, 100, 0, Uuid::new_v4());
|
||||
order.quantity = 0;
|
||||
|
||||
let result = engine.validate_order(&order);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_validate_order_zero_price_limit() {
|
||||
let engine = MatchingEngine::new(30);
|
||||
let mut order = create_test_order(OrderType::Buy, 0, 1000, Uuid::new_v4());
|
||||
order.price = 0;
|
||||
order.price_type = PriceType::Limit;
|
||||
|
||||
let result = engine.validate_order(&order);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
// NAC RWA Exchange - 交易引擎模块
|
||||
|
||||
pub mod matching;
|
||||
pub mod orderbook;
|
||||
pub mod settlement;
|
||||
|
||||
pub use matching::{MatchResult, MatchingEngine};
|
||||
pub use orderbook::{MarketDepth, OrderBook};
|
||||
pub use settlement::{AssetHolding, Balance, SettlementEngine, SettlementError};
|
||||
|
|
@ -1,433 +0,0 @@
|
|||
// NAC RWA Exchange - 订单簿模块
|
||||
|
||||
use crate::types::{AssetId, Order, OrderId, OrderStatus, OrderType};
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BinaryHeap, HashMap};
|
||||
|
||||
/// 订单包装器,用于优先队列排序
|
||||
#[derive(Clone)]
|
||||
struct OrderWrapper {
|
||||
order: Order,
|
||||
}
|
||||
|
||||
impl PartialEq for OrderWrapper {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.order.id == other.order.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for OrderWrapper {}
|
||||
|
||||
impl PartialOrd for OrderWrapper {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for OrderWrapper {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
// 买单:价格从高到低,时间从早到晚
|
||||
// 卖单:价格从低到高,时间从早到晚
|
||||
match self.order.order_type {
|
||||
OrderType::Buy => {
|
||||
// 价格高的优先(反向比较)
|
||||
match other.order.price.cmp(&self.order.price) {
|
||||
Ordering::Equal => {
|
||||
// 时间早的优先(正向比较)
|
||||
self.order.created_at.cmp(&other.order.created_at)
|
||||
}
|
||||
ord => ord,
|
||||
}
|
||||
}
|
||||
OrderType::Sell => {
|
||||
// 价格低的优先(正向比较)
|
||||
match self.order.price.cmp(&other.order.price) {
|
||||
Ordering::Equal => {
|
||||
// 时间早的优先(正向比较)
|
||||
self.order.created_at.cmp(&other.order.created_at)
|
||||
}
|
||||
ord => ord,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 订单簿
|
||||
pub struct OrderBook {
|
||||
/// 资产ID
|
||||
asset_id: AssetId,
|
||||
/// 买单队列(价格从高到低)
|
||||
buy_orders: BinaryHeap<OrderWrapper>,
|
||||
/// 卖单队列(价格从低到高)
|
||||
sell_orders: BinaryHeap<OrderWrapper>,
|
||||
/// 订单索引(快速查找)
|
||||
order_index: HashMap<OrderId, Order>,
|
||||
}
|
||||
|
||||
impl OrderBook {
|
||||
/// 创建新的订单簿
|
||||
pub fn new(asset_id: AssetId) -> Self {
|
||||
Self {
|
||||
asset_id,
|
||||
buy_orders: BinaryHeap::new(),
|
||||
sell_orders: BinaryHeap::new(),
|
||||
order_index: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取资产ID
|
||||
pub fn asset_id(&self) -> AssetId {
|
||||
self.asset_id
|
||||
}
|
||||
|
||||
/// 添加订单到订单簿
|
||||
pub fn add_order(&mut self, order: Order) -> Result<(), String> {
|
||||
// 验证订单资产ID
|
||||
if order.asset_id != self.asset_id {
|
||||
return Err("Order asset ID does not match order book".to_string());
|
||||
}
|
||||
|
||||
// 验证订单状态
|
||||
if !order.is_matchable() {
|
||||
return Err("Order is not matchable".to_string());
|
||||
}
|
||||
|
||||
// 添加到索引
|
||||
self.order_index.insert(order.id, order.clone());
|
||||
|
||||
// 添加到对应队列
|
||||
let wrapper = OrderWrapper { order };
|
||||
match wrapper.order.order_type {
|
||||
OrderType::Buy => self.buy_orders.push(wrapper),
|
||||
OrderType::Sell => self.sell_orders.push(wrapper),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 移除订单
|
||||
pub fn remove_order(&mut self, order_id: &OrderId) -> Result<Order, String> {
|
||||
self.order_index
|
||||
.remove(order_id)
|
||||
.ok_or_else(|| "Order not found".to_string())
|
||||
}
|
||||
|
||||
/// 更新订单
|
||||
pub fn update_order(&mut self, order: Order) -> Result<(), String> {
|
||||
if !self.order_index.contains_key(&order.id) {
|
||||
return Err("Order not found".to_string());
|
||||
}
|
||||
self.order_index.insert(order.id, order);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 获取订单
|
||||
pub fn get_order(&self, order_id: &OrderId) -> Option<&Order> {
|
||||
self.order_index.get(order_id)
|
||||
}
|
||||
|
||||
/// 获取最优买单(价格最高)
|
||||
pub fn best_buy_order(&self) -> Option<&Order> {
|
||||
self.buy_orders.peek().map(|w| &w.order)
|
||||
}
|
||||
|
||||
/// 获取最优卖单(价格最低)
|
||||
pub fn best_sell_order(&self) -> Option<&Order> {
|
||||
self.sell_orders.peek().map(|w| &w.order)
|
||||
}
|
||||
|
||||
/// 获取买单数量
|
||||
pub fn buy_order_count(&self) -> usize {
|
||||
self.buy_orders.len()
|
||||
}
|
||||
|
||||
/// 获取卖单数量
|
||||
pub fn sell_order_count(&self) -> usize {
|
||||
self.sell_orders.len()
|
||||
}
|
||||
|
||||
/// 获取所有买单(按价格从高到低)
|
||||
pub fn get_buy_orders(&self, limit: usize) -> Vec<Order> {
|
||||
let mut orders: Vec<_> = self
|
||||
.buy_orders
|
||||
.iter()
|
||||
.filter(|w| {
|
||||
self.order_index
|
||||
.get(&w.order.id)
|
||||
.map(|o| o.is_matchable())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.take(limit)
|
||||
.map(|w| w.order.clone())
|
||||
.collect();
|
||||
orders.sort_by(|a, b| b.price.cmp(&a.price));
|
||||
orders
|
||||
}
|
||||
|
||||
/// 获取所有卖单(按价格从低到高)
|
||||
pub fn get_sell_orders(&self, limit: usize) -> Vec<Order> {
|
||||
let mut orders: Vec<_> = self
|
||||
.sell_orders
|
||||
.iter()
|
||||
.filter(|w| {
|
||||
self.order_index
|
||||
.get(&w.order.id)
|
||||
.map(|o| o.is_matchable())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.take(limit)
|
||||
.map(|w| w.order.clone())
|
||||
.collect();
|
||||
orders.sort_by(|a, b| a.price.cmp(&b.price));
|
||||
orders
|
||||
}
|
||||
|
||||
/// 清理已完成的订单
|
||||
pub fn cleanup(&mut self) {
|
||||
// 移除已完成或已取消的订单
|
||||
let to_remove: Vec<OrderId> = self
|
||||
.order_index
|
||||
.iter()
|
||||
.filter(|(_, order)| !order.is_matchable())
|
||||
.map(|(id, _)| *id)
|
||||
.collect();
|
||||
|
||||
for id in to_remove {
|
||||
self.order_index.remove(&id);
|
||||
}
|
||||
|
||||
// 重建队列(移除无效订单)
|
||||
self.rebuild_queues();
|
||||
}
|
||||
|
||||
/// 重建队列
|
||||
fn rebuild_queues(&mut self) {
|
||||
// 重建买单队列
|
||||
let buy_orders: Vec<_> = self
|
||||
.order_index
|
||||
.values()
|
||||
.filter(|o| o.order_type == OrderType::Buy && o.is_matchable())
|
||||
.cloned()
|
||||
.map(|order| OrderWrapper { order })
|
||||
.collect();
|
||||
self.buy_orders = BinaryHeap::from(buy_orders);
|
||||
|
||||
// 重建卖单队列
|
||||
let sell_orders: Vec<_> = self
|
||||
.order_index
|
||||
.values()
|
||||
.filter(|o| o.order_type == OrderType::Sell && o.is_matchable())
|
||||
.cloned()
|
||||
.map(|order| OrderWrapper { order })
|
||||
.collect();
|
||||
self.sell_orders = BinaryHeap::from(sell_orders);
|
||||
}
|
||||
|
||||
/// 获取市场深度
|
||||
pub fn get_market_depth(&self, levels: usize) -> MarketDepth {
|
||||
MarketDepth {
|
||||
asset_id: self.asset_id,
|
||||
bids: self.get_buy_orders(levels),
|
||||
asks: self.get_sell_orders(levels),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 市场深度
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MarketDepth {
|
||||
/// 资产ID
|
||||
pub asset_id: AssetId,
|
||||
/// 买单列表(价格从高到低)
|
||||
pub bids: Vec<Order>,
|
||||
/// 卖单列表(价格从低到高)
|
||||
pub asks: Vec<Order>,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::{Address, PriceType, Signature};
|
||||
use chrono::Utc;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn create_test_order(
|
||||
order_type: OrderType,
|
||||
price: u64,
|
||||
quantity: u64,
|
||||
created_at: i64,
|
||||
) -> Order {
|
||||
Order {
|
||||
id: Uuid::new_v4(),
|
||||
user_address: Address::new([0u8; 32]),
|
||||
asset_id: Uuid::new_v4(),
|
||||
order_type,
|
||||
price_type: PriceType::Limit,
|
||||
price,
|
||||
quantity,
|
||||
filled_quantity: 0,
|
||||
status: OrderStatus::Pending,
|
||||
created_at,
|
||||
updated_at: created_at,
|
||||
signature: Signature::new([0u8; 96]),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_orderbook_creation() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let orderbook = OrderBook::new(asset_id);
|
||||
assert_eq!(orderbook.asset_id(), asset_id);
|
||||
assert_eq!(orderbook.buy_order_count(), 0);
|
||||
assert_eq!(orderbook.sell_order_count(), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_buy_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let mut order = create_test_order(OrderType::Buy, 100, 1000, Utc::now().timestamp());
|
||||
order.asset_id = asset_id;
|
||||
|
||||
assert!(orderbook.add_order(order.clone()).is_ok());
|
||||
assert_eq!(orderbook.buy_order_count(), 1);
|
||||
assert_eq!(orderbook.sell_order_count(), 0);
|
||||
assert!(orderbook.get_order(&order.id).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_sell_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let mut order = create_test_order(OrderType::Sell, 100, 1000, Utc::now().timestamp());
|
||||
order.asset_id = asset_id;
|
||||
|
||||
assert!(orderbook.add_order(order.clone()).is_ok());
|
||||
assert_eq!(orderbook.buy_order_count(), 0);
|
||||
assert_eq!(orderbook.sell_order_count(), 1);
|
||||
assert!(orderbook.get_order(&order.id).is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_best_buy_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let now = Utc::now().timestamp();
|
||||
let mut order1 = create_test_order(OrderType::Buy, 100, 1000, now);
|
||||
let mut order2 = create_test_order(OrderType::Buy, 150, 500, now + 1);
|
||||
let mut order3 = create_test_order(OrderType::Buy, 120, 800, now + 2);
|
||||
|
||||
order1.asset_id = asset_id;
|
||||
order2.asset_id = asset_id;
|
||||
order3.asset_id = asset_id;
|
||||
|
||||
orderbook.add_order(order1).unwrap();
|
||||
orderbook.add_order(order2.clone()).unwrap();
|
||||
orderbook.add_order(order3).unwrap();
|
||||
|
||||
// 最优买单应该是价格最高的
|
||||
let best = orderbook.best_buy_order().unwrap();
|
||||
assert_eq!(best.price, 150);
|
||||
assert_eq!(best.id, order2.id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_best_sell_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let now = Utc::now().timestamp();
|
||||
let mut order1 = create_test_order(OrderType::Sell, 100, 1000, now);
|
||||
let mut order2 = create_test_order(OrderType::Sell, 80, 500, now + 1);
|
||||
let mut order3 = create_test_order(OrderType::Sell, 90, 800, now + 2);
|
||||
|
||||
order1.asset_id = asset_id;
|
||||
order2.asset_id = asset_id;
|
||||
order3.asset_id = asset_id;
|
||||
|
||||
orderbook.add_order(order1).unwrap();
|
||||
orderbook.add_order(order2.clone()).unwrap();
|
||||
orderbook.add_order(order3).unwrap();
|
||||
|
||||
// 最优卖单应该是价格最低的
|
||||
let best = orderbook.best_sell_order().unwrap();
|
||||
assert_eq!(best.price, 80);
|
||||
assert_eq!(best.id, order2.id);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let mut order = create_test_order(OrderType::Buy, 100, 1000, Utc::now().timestamp());
|
||||
order.asset_id = asset_id;
|
||||
let order_id = order.id;
|
||||
|
||||
orderbook.add_order(order).unwrap();
|
||||
assert!(orderbook.get_order(&order_id).is_some());
|
||||
|
||||
let removed = orderbook.remove_order(&order_id);
|
||||
assert!(removed.is_ok());
|
||||
assert!(orderbook.get_order(&order_id).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_order() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let mut order = create_test_order(OrderType::Buy, 100, 1000, Utc::now().timestamp());
|
||||
order.asset_id = asset_id;
|
||||
let order_id = order.id;
|
||||
|
||||
orderbook.add_order(order.clone()).unwrap();
|
||||
|
||||
// 更新订单
|
||||
order.filled_quantity = 300;
|
||||
order.status = OrderStatus::PartialFilled;
|
||||
orderbook.update_order(order.clone()).unwrap();
|
||||
|
||||
let updated = orderbook.get_order(&order_id).unwrap();
|
||||
assert_eq!(updated.filled_quantity, 300);
|
||||
assert_eq!(updated.status, OrderStatus::PartialFilled);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_market_depth() {
|
||||
let asset_id = Uuid::new_v4();
|
||||
let mut orderbook = OrderBook::new(asset_id);
|
||||
|
||||
let now = Utc::now().timestamp();
|
||||
|
||||
// 添加买单
|
||||
for i in 0..5 {
|
||||
let mut order = create_test_order(OrderType::Buy, 100 - i * 5, 1000, now + i as i64);
|
||||
order.asset_id = asset_id;
|
||||
orderbook.add_order(order).unwrap();
|
||||
}
|
||||
|
||||
// 添加卖单
|
||||
for i in 0..5 {
|
||||
let mut order = create_test_order(OrderType::Sell, 110 + i * 5, 1000, now + i as i64);
|
||||
order.asset_id = asset_id;
|
||||
orderbook.add_order(order).unwrap();
|
||||
}
|
||||
|
||||
let depth = orderbook.get_market_depth(3);
|
||||
assert_eq!(depth.bids.len(), 3);
|
||||
assert_eq!(depth.asks.len(), 3);
|
||||
|
||||
// 验证买单按价格从高到低排序
|
||||
assert!(depth.bids[0].price >= depth.bids[1].price);
|
||||
assert!(depth.bids[1].price >= depth.bids[2].price);
|
||||
|
||||
// 验证卖单按价格从低到高排序
|
||||
assert!(depth.asks[0].price <= depth.asks[1].price);
|
||||
assert!(depth.asks[1].price <= depth.asks[2].price);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,589 +0,0 @@
|
|||
// NAC RWA Exchange - 清算结算模块
|
||||
|
||||
use crate::types::{Address, AssetId, Hash, Trade, TradeId, TradeStatus};
|
||||
use chrono::Utc;
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
|
||||
/// 结算错误
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SettlementError {
|
||||
#[error("Trade not found: {0}")]
|
||||
TradeNotFound(TradeId),
|
||||
|
||||
#[error("Insufficient balance for {0}: required {1}, available {2}")]
|
||||
InsufficientBalance(Address, u64, u64),
|
||||
|
||||
#[error("Insufficient asset for {0}: required {1}, available {2}")]
|
||||
InsufficientAsset(Address, u64, u64),
|
||||
|
||||
#[error("Trade already settled: {0}")]
|
||||
AlreadySettled(TradeId),
|
||||
|
||||
#[error("Trade execution failed: {0}")]
|
||||
ExecutionFailed(String),
|
||||
|
||||
#[error("Blockchain confirmation failed: {0}")]
|
||||
ConfirmationFailed(String),
|
||||
|
||||
#[error("Settlement timeout: {0}")]
|
||||
Timeout(TradeId),
|
||||
}
|
||||
|
||||
/// 账户余额
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Balance {
|
||||
/// 可用余额
|
||||
pub available: u64,
|
||||
/// 锁定余额
|
||||
pub locked: u64,
|
||||
}
|
||||
|
||||
impl Balance {
|
||||
pub fn new(available: u64) -> Self {
|
||||
Self {
|
||||
available,
|
||||
locked: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// 总余额
|
||||
pub fn total(&self) -> u64 {
|
||||
self.available + self.locked
|
||||
}
|
||||
|
||||
/// 锁定资金
|
||||
pub fn lock(&mut self, amount: u64) -> Result<(), SettlementError> {
|
||||
if self.available < amount {
|
||||
return Err(SettlementError::InsufficientBalance(
|
||||
Address::new([0u8; 32]),
|
||||
amount,
|
||||
self.available,
|
||||
));
|
||||
}
|
||||
self.available -= amount;
|
||||
self.locked += amount;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 解锁资金
|
||||
pub fn unlock(&mut self, amount: u64) {
|
||||
let unlock_amount = amount.min(self.locked);
|
||||
self.locked -= unlock_amount;
|
||||
self.available += unlock_amount;
|
||||
}
|
||||
|
||||
/// 扣除锁定资金
|
||||
pub fn deduct_locked(&mut self, amount: u64) -> Result<(), SettlementError> {
|
||||
if self.locked < amount {
|
||||
return Err(SettlementError::InsufficientBalance(
|
||||
Address::new([0u8; 32]),
|
||||
amount,
|
||||
self.locked,
|
||||
));
|
||||
}
|
||||
self.locked -= amount;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 增加可用余额
|
||||
pub fn add_available(&mut self, amount: u64) {
|
||||
self.available += amount;
|
||||
}
|
||||
}
|
||||
|
||||
/// 资产持仓
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AssetHolding {
|
||||
/// 可用数量
|
||||
pub available: u64,
|
||||
/// 锁定数量
|
||||
pub locked: u64,
|
||||
}
|
||||
|
||||
impl AssetHolding {
|
||||
pub fn new(available: u64) -> Self {
|
||||
Self {
|
||||
available,
|
||||
locked: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// 总数量
|
||||
pub fn total(&self) -> u64 {
|
||||
self.available + self.locked
|
||||
}
|
||||
|
||||
/// 锁定资产
|
||||
pub fn lock(&mut self, quantity: u64) -> Result<(), SettlementError> {
|
||||
if self.available < quantity {
|
||||
return Err(SettlementError::InsufficientAsset(
|
||||
Address::new([0u8; 32]),
|
||||
quantity,
|
||||
self.available,
|
||||
));
|
||||
}
|
||||
self.available -= quantity;
|
||||
self.locked += quantity;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 解锁资产
|
||||
pub fn unlock(&mut self, quantity: u64) {
|
||||
let unlock_quantity = quantity.min(self.locked);
|
||||
self.locked -= unlock_quantity;
|
||||
self.available += unlock_quantity;
|
||||
}
|
||||
|
||||
/// 扣除锁定资产
|
||||
pub fn deduct_locked(&mut self, quantity: u64) -> Result<(), SettlementError> {
|
||||
if self.locked < quantity {
|
||||
return Err(SettlementError::InsufficientAsset(
|
||||
Address::new([0u8; 32]),
|
||||
quantity,
|
||||
self.locked,
|
||||
));
|
||||
}
|
||||
self.locked -= quantity;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 增加可用资产
|
||||
pub fn add_available(&mut self, quantity: u64) {
|
||||
self.available += quantity;
|
||||
}
|
||||
}
|
||||
|
||||
/// 结算引擎
|
||||
pub struct SettlementEngine {
|
||||
/// 用户余额(地址 -> 余额)
|
||||
balances: HashMap<Address, Balance>,
|
||||
/// 用户资产持仓(地址 -> 资产ID -> 持仓)
|
||||
holdings: HashMap<Address, HashMap<AssetId, AssetHolding>>,
|
||||
/// 交易记录
|
||||
trades: HashMap<TradeId, Trade>,
|
||||
/// 区块确认数
|
||||
confirmation_blocks: u64,
|
||||
}
|
||||
|
||||
impl SettlementEngine {
|
||||
/// 创建新的结算引擎
|
||||
pub fn new(confirmation_blocks: u64) -> Self {
|
||||
Self {
|
||||
balances: HashMap::new(),
|
||||
holdings: HashMap::new(),
|
||||
trades: HashMap::new(),
|
||||
confirmation_blocks,
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置用户余额
|
||||
pub fn set_balance(&mut self, address: Address, balance: Balance) {
|
||||
self.balances.insert(address, balance);
|
||||
}
|
||||
|
||||
/// 获取用户余额
|
||||
pub fn get_balance(&self, address: &Address) -> Balance {
|
||||
self.balances
|
||||
.get(address)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| Balance::new(0))
|
||||
}
|
||||
|
||||
/// 设置用户资产持仓
|
||||
pub fn set_holding(&mut self, address: Address, asset_id: AssetId, holding: AssetHolding) {
|
||||
self.holdings
|
||||
.entry(address)
|
||||
.or_insert_with(HashMap::new)
|
||||
.insert(asset_id, holding);
|
||||
}
|
||||
|
||||
/// 获取用户资产持仓
|
||||
pub fn get_holding(&self, address: &Address, asset_id: &AssetId) -> AssetHolding {
|
||||
self.holdings
|
||||
.get(address)
|
||||
.and_then(|h| h.get(asset_id))
|
||||
.cloned()
|
||||
.unwrap_or_else(|| AssetHolding::new(0))
|
||||
}
|
||||
|
||||
/// 执行交易结算
|
||||
pub fn settle_trade(&mut self, mut trade: Trade) -> Result<Trade, SettlementError> {
|
||||
// 1. 锁定阶段
|
||||
self.lock_funds(&trade)?;
|
||||
|
||||
// 2. 执行阶段
|
||||
trade.status = TradeStatus::Executing;
|
||||
trade = self.execute_trade(trade)?;
|
||||
|
||||
// 3. 确认阶段
|
||||
trade = self.confirm_trade(trade)?;
|
||||
|
||||
// 4. 结算阶段
|
||||
trade = self.finalize_trade(trade)?;
|
||||
|
||||
// 保存交易记录
|
||||
self.trades.insert(trade.id, trade.clone());
|
||||
|
||||
Ok(trade)
|
||||
}
|
||||
|
||||
/// 锁定资金和资产
|
||||
fn lock_funds(&mut self, trade: &Trade) -> Result<(), SettlementError> {
|
||||
// 锁定买方资金
|
||||
let buyer_balance = self.get_balance(&trade.buyer);
|
||||
let required_amount = trade.total_amount + trade.fee;
|
||||
|
||||
if buyer_balance.available < required_amount {
|
||||
return Err(SettlementError::InsufficientBalance(
|
||||
trade.buyer,
|
||||
required_amount,
|
||||
buyer_balance.available,
|
||||
));
|
||||
}
|
||||
|
||||
let mut buyer_balance = buyer_balance;
|
||||
buyer_balance.lock(required_amount)?;
|
||||
self.set_balance(trade.buyer, buyer_balance);
|
||||
|
||||
// 锁定卖方资产
|
||||
let seller_holding = self.get_holding(&trade.seller, &trade.asset_id);
|
||||
|
||||
if seller_holding.available < trade.quantity {
|
||||
// 回滚买方资金锁定
|
||||
let mut buyer_balance = self.get_balance(&trade.buyer);
|
||||
buyer_balance.unlock(required_amount);
|
||||
self.set_balance(trade.buyer, buyer_balance);
|
||||
|
||||
return Err(SettlementError::InsufficientAsset(
|
||||
trade.seller,
|
||||
trade.quantity,
|
||||
seller_holding.available,
|
||||
));
|
||||
}
|
||||
|
||||
let mut seller_holding = seller_holding;
|
||||
seller_holding.lock(trade.quantity)?;
|
||||
self.set_holding(trade.seller, trade.asset_id, seller_holding);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 执行交易(调用Charter智能合约)
|
||||
fn execute_trade(&mut self, mut trade: Trade) -> Result<Trade, SettlementError> {
|
||||
// 模拟调用Charter智能合约执行资产转移
|
||||
// 实际实现中应该调用NVM执行智能合约
|
||||
|
||||
// 生成模拟交易哈希
|
||||
trade.tx_hash = self.generate_tx_hash(&trade);
|
||||
|
||||
Ok(trade)
|
||||
}
|
||||
|
||||
/// 确认交易(等待区块确认)
|
||||
fn confirm_trade(&mut self, mut trade: Trade) -> Result<Trade, SettlementError> {
|
||||
// 模拟等待区块确认
|
||||
// 实际实现中应该查询区块链节点确认交易状态
|
||||
|
||||
// 这里简化处理,直接标记为已确认
|
||||
trade.status = TradeStatus::Completed;
|
||||
|
||||
Ok(trade)
|
||||
}
|
||||
|
||||
/// 完成结算
|
||||
fn finalize_trade(&mut self, mut trade: Trade) -> Result<Trade, SettlementError> {
|
||||
// 扣除买方锁定资金
|
||||
let mut buyer_balance = self.get_balance(&trade.buyer);
|
||||
buyer_balance.deduct_locked(trade.total_amount + trade.fee)?;
|
||||
self.set_balance(trade.buyer, buyer_balance);
|
||||
|
||||
// 扣除卖方锁定资产
|
||||
let mut seller_holding = self.get_holding(&trade.seller, &trade.asset_id);
|
||||
seller_holding.deduct_locked(trade.quantity)?;
|
||||
self.set_holding(trade.seller, trade.asset_id, seller_holding);
|
||||
|
||||
// 增加买方资产
|
||||
let mut buyer_holding = self.get_holding(&trade.buyer, &trade.asset_id);
|
||||
buyer_holding.add_available(trade.quantity);
|
||||
self.set_holding(trade.buyer, trade.asset_id, buyer_holding);
|
||||
|
||||
// 增加卖方资金(扣除手续费)
|
||||
let mut seller_balance = self.get_balance(&trade.seller);
|
||||
seller_balance.add_available(trade.total_amount);
|
||||
self.set_balance(trade.seller, seller_balance);
|
||||
|
||||
// 记录结算时间
|
||||
trade.settled_at = Some(Utc::now().timestamp());
|
||||
|
||||
Ok(trade)
|
||||
}
|
||||
|
||||
/// 回滚交易
|
||||
pub fn rollback_trade(&mut self, trade: &Trade) -> Result<(), SettlementError> {
|
||||
// 解锁买方资金
|
||||
let mut buyer_balance = self.get_balance(&trade.buyer);
|
||||
buyer_balance.unlock(trade.total_amount + trade.fee);
|
||||
self.set_balance(trade.buyer, buyer_balance);
|
||||
|
||||
// 解锁卖方资产
|
||||
let mut seller_holding = self.get_holding(&trade.seller, &trade.asset_id);
|
||||
seller_holding.unlock(trade.quantity);
|
||||
self.set_holding(trade.seller, trade.asset_id, seller_holding);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 生成交易哈希(模拟)
|
||||
fn generate_tx_hash(&self, trade: &Trade) -> Hash {
|
||||
// 实际实现中应该使用SHA3-384计算交易哈希
|
||||
// 这里简化处理,使用模拟哈希
|
||||
let mut hash_bytes = [0u8; 48];
|
||||
let trade_id_bytes = trade.id.as_bytes();
|
||||
hash_bytes[..16].copy_from_slice(trade_id_bytes);
|
||||
Hash::new(hash_bytes)
|
||||
}
|
||||
|
||||
/// 获取交易记录
|
||||
pub fn get_trade(&self, trade_id: &TradeId) -> Option<&Trade> {
|
||||
self.trades.get(trade_id)
|
||||
}
|
||||
|
||||
/// 获取用户所有交易记录
|
||||
pub fn get_user_trades(&self, address: &Address) -> Vec<Trade> {
|
||||
self.trades
|
||||
.values()
|
||||
.filter(|t| t.buyer == *address || t.seller == *address)
|
||||
.cloned()
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::types::OrderId;
|
||||
use uuid::Uuid;
|
||||
|
||||
fn create_test_trade(
|
||||
buyer: Address,
|
||||
seller: Address,
|
||||
asset_id: AssetId,
|
||||
price: u64,
|
||||
quantity: u64,
|
||||
fee: u64,
|
||||
) -> Trade {
|
||||
Trade {
|
||||
id: Uuid::new_v4(),
|
||||
buy_order_id: Uuid::new_v4(),
|
||||
sell_order_id: Uuid::new_v4(),
|
||||
buyer,
|
||||
seller,
|
||||
asset_id,
|
||||
price,
|
||||
quantity,
|
||||
total_amount: price * quantity,
|
||||
fee,
|
||||
status: TradeStatus::Pending,
|
||||
executed_at: Utc::now().timestamp(),
|
||||
settled_at: None,
|
||||
tx_hash: Hash::new([0u8; 48]),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_balance_operations() {
|
||||
let mut balance = Balance::new(1000);
|
||||
assert_eq!(balance.available, 1000);
|
||||
assert_eq!(balance.locked, 0);
|
||||
assert_eq!(balance.total(), 1000);
|
||||
|
||||
// 锁定资金
|
||||
balance.lock(300).unwrap();
|
||||
assert_eq!(balance.available, 700);
|
||||
assert_eq!(balance.locked, 300);
|
||||
|
||||
// 解锁资金
|
||||
balance.unlock(100);
|
||||
assert_eq!(balance.available, 800);
|
||||
assert_eq!(balance.locked, 200);
|
||||
|
||||
// 扣除锁定资金
|
||||
balance.deduct_locked(200).unwrap();
|
||||
assert_eq!(balance.available, 800);
|
||||
assert_eq!(balance.locked, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_asset_holding_operations() {
|
||||
let mut holding = AssetHolding::new(1000);
|
||||
assert_eq!(holding.available, 1000);
|
||||
assert_eq!(holding.locked, 0);
|
||||
assert_eq!(holding.total(), 1000);
|
||||
|
||||
// 锁定资产
|
||||
holding.lock(300).unwrap();
|
||||
assert_eq!(holding.available, 700);
|
||||
assert_eq!(holding.locked, 300);
|
||||
|
||||
// 解锁资产
|
||||
holding.unlock(100);
|
||||
assert_eq!(holding.available, 800);
|
||||
assert_eq!(holding.locked, 200);
|
||||
|
||||
// 扣除锁定资产
|
||||
holding.deduct_locked(200).unwrap();
|
||||
assert_eq!(holding.available, 800);
|
||||
assert_eq!(holding.locked, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settlement_engine_creation() {
|
||||
let engine = SettlementEngine::new(3);
|
||||
assert_eq!(engine.confirmation_blocks, 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_and_get_balance() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let balance = Balance::new(10000);
|
||||
|
||||
engine.set_balance(address, balance.clone());
|
||||
let retrieved = engine.get_balance(&address);
|
||||
assert_eq!(retrieved.available, 10000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_and_get_holding() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
let address = Address::new([1u8; 32]);
|
||||
let asset_id = Uuid::new_v4();
|
||||
let holding = AssetHolding::new(5000);
|
||||
|
||||
engine.set_holding(address, asset_id, holding.clone());
|
||||
let retrieved = engine.get_holding(&address, &asset_id);
|
||||
assert_eq!(retrieved.available, 5000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settle_trade_success() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
|
||||
let buyer = Address::new([1u8; 32]);
|
||||
let seller = Address::new([2u8; 32]);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 设置买方余额
|
||||
engine.set_balance(buyer, Balance::new(100000));
|
||||
|
||||
// 设置卖方资产
|
||||
engine.set_holding(seller, asset_id, AssetHolding::new(1000));
|
||||
|
||||
// 创建交易
|
||||
let trade = create_test_trade(buyer, seller, asset_id, 100, 500, 30);
|
||||
|
||||
// 执行结算
|
||||
let settled_trade = engine.settle_trade(trade.clone()).unwrap();
|
||||
assert_eq!(settled_trade.status, TradeStatus::Completed);
|
||||
assert!(settled_trade.settled_at.is_some());
|
||||
|
||||
// 验证买方余额
|
||||
let buyer_balance = engine.get_balance(&buyer);
|
||||
assert_eq!(buyer_balance.available, 49970); // 100000 - 50000 - 30
|
||||
|
||||
// 验证卖方余额
|
||||
let seller_balance = engine.get_balance(&seller);
|
||||
assert_eq!(seller_balance.available, 50000); // 收到50000
|
||||
|
||||
// 验证买方资产
|
||||
let buyer_holding = engine.get_holding(&buyer, &asset_id);
|
||||
assert_eq!(buyer_holding.available, 500);
|
||||
|
||||
// 验证卖方资产
|
||||
let seller_holding = engine.get_holding(&seller, &asset_id);
|
||||
assert_eq!(seller_holding.available, 500); // 1000 - 500
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settle_trade_insufficient_balance() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
|
||||
let buyer = Address::new([1u8; 32]);
|
||||
let seller = Address::new([2u8; 32]);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 设置买方余额不足
|
||||
engine.set_balance(buyer, Balance::new(1000));
|
||||
|
||||
// 设置卖方资产
|
||||
engine.set_holding(seller, asset_id, AssetHolding::new(1000));
|
||||
|
||||
// 创建交易
|
||||
let trade = create_test_trade(buyer, seller, asset_id, 100, 500, 30);
|
||||
|
||||
// 执行结算应该失败
|
||||
let result = engine.settle_trade(trade);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_settle_trade_insufficient_asset() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
|
||||
let buyer = Address::new([1u8; 32]);
|
||||
let seller = Address::new([2u8; 32]);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 设置买方余额
|
||||
engine.set_balance(buyer, Balance::new(100000));
|
||||
|
||||
// 设置卖方资产不足
|
||||
engine.set_holding(seller, asset_id, AssetHolding::new(100));
|
||||
|
||||
// 创建交易
|
||||
let trade = create_test_trade(buyer, seller, asset_id, 100, 500, 30);
|
||||
|
||||
// 执行结算应该失败
|
||||
let result = engine.settle_trade(trade);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rollback_trade() {
|
||||
let mut engine = SettlementEngine::new(3);
|
||||
|
||||
let buyer = Address::new([1u8; 32]);
|
||||
let seller = Address::new([2u8; 32]);
|
||||
let asset_id = Uuid::new_v4();
|
||||
|
||||
// 设置初始状态
|
||||
engine.set_balance(buyer, Balance::new(100000));
|
||||
engine.set_holding(seller, asset_id, AssetHolding::new(1000));
|
||||
|
||||
// 创建交易
|
||||
let trade = create_test_trade(buyer, seller, asset_id, 100, 500, 30);
|
||||
|
||||
// 锁定资金
|
||||
engine.lock_funds(&trade).unwrap();
|
||||
|
||||
// 验证资金已锁定
|
||||
let buyer_balance = engine.get_balance(&buyer);
|
||||
assert_eq!(buyer_balance.locked, 50030);
|
||||
|
||||
let seller_holding = engine.get_holding(&seller, &asset_id);
|
||||
assert_eq!(seller_holding.locked, 500);
|
||||
|
||||
// 回滚交易
|
||||
engine.rollback_trade(&trade).unwrap();
|
||||
|
||||
// 验证资金已解锁
|
||||
let buyer_balance = engine.get_balance(&buyer);
|
||||
assert_eq!(buyer_balance.available, 100000);
|
||||
assert_eq!(buyer_balance.locked, 0);
|
||||
|
||||
let seller_holding = engine.get_holding(&seller, &asset_id);
|
||||
assert_eq!(seller_holding.available, 1000);
|
||||
assert_eq!(seller_holding.locked, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,33 +1,14 @@
|
|||
// NAC RWA Exchange - RWA资产交易所核心库
|
||||
|
||||
pub mod compliance;
|
||||
pub mod engine;
|
||||
pub mod types;
|
||||
|
||||
// 重新导出核心类型和模块
|
||||
pub use compliance::{KYCData, KYCEngine, KYCError, KYCReviewResult, LimitEngine, LimitError, TradingStats};
|
||||
pub use engine::{AssetHolding, Balance, MatchResult, MatchingEngine, MarketDepth, OrderBook, SettlementEngine, SettlementError};
|
||||
pub use types::{
|
||||
Address, AssetId, AssetMetadata, AssetType, ComplianceStatus, Hash, KYCStatus, Order,
|
||||
OrderId, OrderStatus, OrderType, PriceType, RWAAsset, RiskLevel, Signature, Trade, TradeId,
|
||||
TradeStatus, User,
|
||||
};
|
||||
pub fn add(left: u64, right: u64) -> u64 {
|
||||
left + right
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_library_exports() {
|
||||
// 测试类型导出
|
||||
let _address = Address::new([0u8; 32]);
|
||||
let _hash = Hash::new([0u8; 48]);
|
||||
let _signature = Signature::new([0u8; 96]);
|
||||
|
||||
// 测试引擎导出
|
||||
let _matching_engine = MatchingEngine::new(30);
|
||||
let _settlement_engine = SettlementEngine::new(3);
|
||||
let _kyc_engine = KYCEngine::new(100000, 1000000);
|
||||
let _limit_engine = LimitEngine::new(100000);
|
||||
fn it_works() {
|
||||
let result = add(2, 2);
|
||||
assert_eq!(result, 4);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,593 +0,0 @@
|
|||
// NAC RWA Exchange - 类型定义模块
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// NAC原生地址类型 (32字节)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Address(pub [u8; 32]);
|
||||
|
||||
impl serde::Serialize for Address {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for Address {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Address::from_hex(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl Address {
|
||||
pub fn new(bytes: [u8; 32]) -> Self {
|
||||
Address(bytes)
|
||||
}
|
||||
|
||||
pub fn from_hex(hex: &str) -> Result<Self, String> {
|
||||
if hex.len() != 64 {
|
||||
return Err("Address must be 64 hex characters (32 bytes)".to_string());
|
||||
}
|
||||
let mut bytes = [0u8; 32];
|
||||
for i in 0..32 {
|
||||
bytes[i] = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16)
|
||||
.map_err(|e| format!("Invalid hex: {}", e))?;
|
||||
}
|
||||
Ok(Address(bytes))
|
||||
}
|
||||
|
||||
pub fn to_hex(&self) -> String {
|
||||
self.0.iter().map(|b| format!("{:02x}", b)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Address {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "0x{}", self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
/// NAC原生哈希类型 (48字节 SHA3-384)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Hash(pub [u8; 48]);
|
||||
|
||||
impl serde::Serialize for Hash {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for Hash {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Hash::from_hex(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash {
|
||||
pub fn new(bytes: [u8; 48]) -> Self {
|
||||
Hash(bytes)
|
||||
}
|
||||
|
||||
pub fn from_hex(hex: &str) -> Result<Self, String> {
|
||||
if hex.len() != 96 {
|
||||
return Err("Hash must be 96 hex characters (48 bytes)".to_string());
|
||||
}
|
||||
let mut bytes = [0u8; 48];
|
||||
for i in 0..48 {
|
||||
bytes[i] = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16)
|
||||
.map_err(|e| format!("Invalid hex: {}", e))?;
|
||||
}
|
||||
Ok(Hash(bytes))
|
||||
}
|
||||
|
||||
pub fn to_hex(&self) -> String {
|
||||
self.0.iter().map(|b| format!("{:02x}", b)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Hash {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "0x{}", self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
/// NAC原生签名类型 (96字节)
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Signature(pub [u8; 96]);
|
||||
|
||||
impl serde::Serialize for Signature {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_hex())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for Signature {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Signature::from_hex(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl Signature {
|
||||
pub fn new(bytes: [u8; 96]) -> Self {
|
||||
Signature(bytes)
|
||||
}
|
||||
|
||||
pub fn from_hex(hex: &str) -> Result<Self, String> {
|
||||
if hex.len() != 192 {
|
||||
return Err("Signature must be 192 hex characters (96 bytes)".to_string());
|
||||
}
|
||||
let mut bytes = [0u8; 96];
|
||||
for i in 0..96 {
|
||||
bytes[i] = u8::from_str_radix(&hex[i * 2..i * 2 + 2], 16)
|
||||
.map_err(|e| format!("Invalid hex: {}", e))?;
|
||||
}
|
||||
Ok(Signature(bytes))
|
||||
}
|
||||
|
||||
pub fn to_hex(&self) -> String {
|
||||
self.0.iter().map(|b| format!("{:02x}", b)).collect()
|
||||
}
|
||||
}
|
||||
|
||||
/// 订单ID
|
||||
pub type OrderId = Uuid;
|
||||
|
||||
/// 资产ID
|
||||
pub type AssetId = Uuid;
|
||||
|
||||
/// 交易ID
|
||||
pub type TradeId = Uuid;
|
||||
|
||||
/// 订单类型
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum OrderType {
|
||||
/// 买单
|
||||
Buy,
|
||||
/// 卖单
|
||||
Sell,
|
||||
}
|
||||
|
||||
impl fmt::Display for OrderType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
OrderType::Buy => write!(f, "Buy"),
|
||||
OrderType::Sell => write!(f, "Sell"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 价格类型
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum PriceType {
|
||||
/// 限价单
|
||||
Limit,
|
||||
/// 市价单
|
||||
Market,
|
||||
}
|
||||
|
||||
impl fmt::Display for PriceType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
PriceType::Limit => write!(f, "Limit"),
|
||||
PriceType::Market => write!(f, "Market"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 订单状态
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum OrderStatus {
|
||||
/// 待处理
|
||||
Pending,
|
||||
/// 部分成交
|
||||
PartialFilled,
|
||||
/// 完全成交
|
||||
Filled,
|
||||
/// 已取消
|
||||
Cancelled,
|
||||
/// 失败
|
||||
Failed,
|
||||
}
|
||||
|
||||
impl fmt::Display for OrderStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
OrderStatus::Pending => write!(f, "Pending"),
|
||||
OrderStatus::PartialFilled => write!(f, "PartialFilled"),
|
||||
OrderStatus::Filled => write!(f, "Filled"),
|
||||
OrderStatus::Cancelled => write!(f, "Cancelled"),
|
||||
OrderStatus::Failed => write!(f, "Failed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 订单模型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Order {
|
||||
/// 订单ID
|
||||
pub id: OrderId,
|
||||
/// 用户地址 (32字节)
|
||||
pub user_address: Address,
|
||||
/// 资产ID
|
||||
pub asset_id: AssetId,
|
||||
/// 订单类型 (买单/卖单)
|
||||
pub order_type: OrderType,
|
||||
/// 价格类型 (限价/市价)
|
||||
pub price_type: PriceType,
|
||||
/// 价格 (单位: 最小精度)
|
||||
pub price: u64,
|
||||
/// 数量
|
||||
pub quantity: u64,
|
||||
/// 已成交数量
|
||||
pub filled_quantity: u64,
|
||||
/// 订单状态
|
||||
pub status: OrderStatus,
|
||||
/// 创建时间 (Unix时间戳)
|
||||
pub created_at: i64,
|
||||
/// 更新时间 (Unix时间戳)
|
||||
pub updated_at: i64,
|
||||
/// 签名 (96字节)
|
||||
pub signature: Signature,
|
||||
}
|
||||
|
||||
impl Order {
|
||||
/// 获取剩余未成交数量
|
||||
pub fn remaining_quantity(&self) -> u64 {
|
||||
self.quantity.saturating_sub(self.filled_quantity)
|
||||
}
|
||||
|
||||
/// 检查订单是否完全成交
|
||||
pub fn is_fully_filled(&self) -> bool {
|
||||
self.filled_quantity >= self.quantity
|
||||
}
|
||||
|
||||
/// 检查订单是否可以撮合
|
||||
pub fn is_matchable(&self) -> bool {
|
||||
matches!(
|
||||
self.status,
|
||||
OrderStatus::Pending | OrderStatus::PartialFilled
|
||||
) && self.remaining_quantity() > 0
|
||||
}
|
||||
}
|
||||
|
||||
/// 资产类型
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum AssetType {
|
||||
/// 房地产
|
||||
RealEstate,
|
||||
/// 股权
|
||||
Equity,
|
||||
/// 债券
|
||||
Bond,
|
||||
/// 大宗商品
|
||||
Commodity,
|
||||
/// 艺术品
|
||||
ArtWork,
|
||||
/// 其他
|
||||
Other,
|
||||
}
|
||||
|
||||
impl fmt::Display for AssetType {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
AssetType::RealEstate => write!(f, "RealEstate"),
|
||||
AssetType::Equity => write!(f, "Equity"),
|
||||
AssetType::Bond => write!(f, "Bond"),
|
||||
AssetType::Commodity => write!(f, "Commodity"),
|
||||
AssetType::ArtWork => write!(f, "ArtWork"),
|
||||
AssetType::Other => write!(f, "Other"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 合规状态
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum ComplianceStatus {
|
||||
/// 待审核
|
||||
Pending,
|
||||
/// 已批准
|
||||
Approved,
|
||||
/// 已拒绝
|
||||
Rejected,
|
||||
/// 已暂停
|
||||
Suspended,
|
||||
}
|
||||
|
||||
impl fmt::Display for ComplianceStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ComplianceStatus::Pending => write!(f, "Pending"),
|
||||
ComplianceStatus::Approved => write!(f, "Approved"),
|
||||
ComplianceStatus::Rejected => write!(f, "Rejected"),
|
||||
ComplianceStatus::Suspended => write!(f, "Suspended"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 资产元数据
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AssetMetadata {
|
||||
/// 描述
|
||||
pub description: String,
|
||||
/// 图片URL
|
||||
pub image_url: Option<String>,
|
||||
/// 文档URL
|
||||
pub document_url: Option<String>,
|
||||
/// 额外属性
|
||||
pub attributes: std::collections::HashMap<String, String>,
|
||||
}
|
||||
|
||||
/// RWA资产模型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct RWAAsset {
|
||||
/// 资产ID
|
||||
pub id: AssetId,
|
||||
/// 资产名称
|
||||
pub name: String,
|
||||
/// 资产符号
|
||||
pub symbol: String,
|
||||
/// 资产类型
|
||||
pub asset_type: AssetType,
|
||||
/// 总供应量
|
||||
pub total_supply: u64,
|
||||
/// 流通量
|
||||
pub circulating_supply: u64,
|
||||
/// 发行方地址 (32字节)
|
||||
pub issuer: Address,
|
||||
/// 估值
|
||||
pub valuation: u64,
|
||||
/// 元数据
|
||||
pub metadata: AssetMetadata,
|
||||
/// 合规状态
|
||||
pub compliance_status: ComplianceStatus,
|
||||
/// 上架时间
|
||||
pub listed_at: i64,
|
||||
}
|
||||
|
||||
/// 交易状态
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum TradeStatus {
|
||||
/// 待处理
|
||||
Pending,
|
||||
/// 执行中
|
||||
Executing,
|
||||
/// 已完成
|
||||
Completed,
|
||||
/// 失败
|
||||
Failed,
|
||||
/// 已回滚
|
||||
RolledBack,
|
||||
}
|
||||
|
||||
impl fmt::Display for TradeStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
TradeStatus::Pending => write!(f, "Pending"),
|
||||
TradeStatus::Executing => write!(f, "Executing"),
|
||||
TradeStatus::Completed => write!(f, "Completed"),
|
||||
TradeStatus::Failed => write!(f, "Failed"),
|
||||
TradeStatus::RolledBack => write!(f, "RolledBack"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 交易记录模型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct Trade {
|
||||
/// 交易ID
|
||||
pub id: TradeId,
|
||||
/// 买单ID
|
||||
pub buy_order_id: OrderId,
|
||||
/// 卖单ID
|
||||
pub sell_order_id: OrderId,
|
||||
/// 买方地址 (32字节)
|
||||
pub buyer: Address,
|
||||
/// 卖方地址 (32字节)
|
||||
pub seller: Address,
|
||||
/// 资产ID
|
||||
pub asset_id: AssetId,
|
||||
/// 成交价格
|
||||
pub price: u64,
|
||||
/// 成交数量
|
||||
pub quantity: u64,
|
||||
/// 总金额
|
||||
pub total_amount: u64,
|
||||
/// 手续费
|
||||
pub fee: u64,
|
||||
/// 交易状态
|
||||
pub status: TradeStatus,
|
||||
/// 执行时间
|
||||
pub executed_at: i64,
|
||||
/// 结算时间
|
||||
pub settled_at: Option<i64>,
|
||||
/// 交易哈希 (48字节 SHA3-384)
|
||||
pub tx_hash: Hash,
|
||||
}
|
||||
|
||||
/// KYC状态
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum KYCStatus {
|
||||
/// 未验证
|
||||
NotVerified,
|
||||
/// 审核中
|
||||
Pending,
|
||||
/// 已验证
|
||||
Verified,
|
||||
/// 已拒绝
|
||||
Rejected,
|
||||
}
|
||||
|
||||
impl fmt::Display for KYCStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
KYCStatus::NotVerified => write!(f, "NotVerified"),
|
||||
KYCStatus::Pending => write!(f, "Pending"),
|
||||
KYCStatus::Verified => write!(f, "Verified"),
|
||||
KYCStatus::Rejected => write!(f, "Rejected"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 风险等级
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum RiskLevel {
|
||||
/// 低风险
|
||||
Low,
|
||||
/// 中风险
|
||||
Medium,
|
||||
/// 高风险
|
||||
High,
|
||||
/// 极高风险
|
||||
Critical,
|
||||
}
|
||||
|
||||
impl fmt::Display for RiskLevel {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
RiskLevel::Low => write!(f, "Low"),
|
||||
RiskLevel::Medium => write!(f, "Medium"),
|
||||
RiskLevel::High => write!(f, "High"),
|
||||
RiskLevel::Critical => write!(f, "Critical"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 用户模型
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct User {
|
||||
/// 用户地址 (32字节)
|
||||
pub address: Address,
|
||||
/// KYC状态
|
||||
pub kyc_status: KYCStatus,
|
||||
/// 风险等级
|
||||
pub risk_level: RiskLevel,
|
||||
/// 日交易限额
|
||||
pub daily_limit: u64,
|
||||
/// 月交易限额
|
||||
pub monthly_limit: u64,
|
||||
/// 日累计交易量
|
||||
pub daily_volume: u64,
|
||||
/// 月累计交易量
|
||||
pub monthly_volume: u64,
|
||||
/// 是否在黑名单
|
||||
pub is_blacklisted: bool,
|
||||
/// 创建时间
|
||||
pub created_at: i64,
|
||||
/// 更新时间
|
||||
pub updated_at: i64,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_address_creation() {
|
||||
let bytes = [1u8; 32];
|
||||
let addr = Address::new(bytes);
|
||||
assert_eq!(addr.0, bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_address_hex_conversion() {
|
||||
let hex = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef";
|
||||
let addr = Address::from_hex(hex).unwrap();
|
||||
assert_eq!(addr.to_hex(), hex);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_creation() {
|
||||
let bytes = [2u8; 48];
|
||||
let hash = Hash::new(bytes);
|
||||
assert_eq!(hash.0, bytes);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_order_remaining_quantity() {
|
||||
let order = Order {
|
||||
id: Uuid::new_v4(),
|
||||
user_address: Address::new([0u8; 32]),
|
||||
asset_id: Uuid::new_v4(),
|
||||
order_type: OrderType::Buy,
|
||||
price_type: PriceType::Limit,
|
||||
price: 100,
|
||||
quantity: 1000,
|
||||
filled_quantity: 300,
|
||||
status: OrderStatus::PartialFilled,
|
||||
created_at: 0,
|
||||
updated_at: 0,
|
||||
signature: Signature::new([0u8; 96]),
|
||||
};
|
||||
assert_eq!(order.remaining_quantity(), 700);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_order_is_fully_filled() {
|
||||
let mut order = Order {
|
||||
id: Uuid::new_v4(),
|
||||
user_address: Address::new([0u8; 32]),
|
||||
asset_id: Uuid::new_v4(),
|
||||
order_type: OrderType::Buy,
|
||||
price_type: PriceType::Limit,
|
||||
price: 100,
|
||||
quantity: 1000,
|
||||
filled_quantity: 1000,
|
||||
status: OrderStatus::Filled,
|
||||
created_at: 0,
|
||||
updated_at: 0,
|
||||
signature: Signature::new([0u8; 96]),
|
||||
};
|
||||
assert!(order.is_fully_filled());
|
||||
|
||||
order.filled_quantity = 999;
|
||||
assert!(!order.is_fully_filled());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_order_is_matchable() {
|
||||
let order = Order {
|
||||
id: Uuid::new_v4(),
|
||||
user_address: Address::new([0u8; 32]),
|
||||
asset_id: Uuid::new_v4(),
|
||||
order_type: OrderType::Buy,
|
||||
price_type: PriceType::Limit,
|
||||
price: 100,
|
||||
quantity: 1000,
|
||||
filled_quantity: 300,
|
||||
status: OrderStatus::PartialFilled,
|
||||
created_at: 0,
|
||||
updated_at: 0,
|
||||
signature: Signature::new([0u8; 96]),
|
||||
};
|
||||
assert!(order.is_matchable());
|
||||
|
||||
let filled_order = Order {
|
||||
status: OrderStatus::Filled,
|
||||
filled_quantity: 1000,
|
||||
..order
|
||||
};
|
||||
assert!(!filled_order.is_matchable());
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue