Exchange Ledger Manager Backend 是一个交易所账本管理系统的后端服务,负责处理和管理与加密货币和法币相关的各类交易操作,包括充值、提现、退款等流程。该系统集成了多种服务和组件,提供了完整的交易所资金管理解决方案。
1.1 主要功能
- 加密货币充值处理
- 加密货币提现处理
- 法币充值处理
- 法币提现处理
- 加密货币退款流程
- OTC交易结算
- 白名单地址管理
- 费用管理和利润分配
1.2 目标用户
- 交易所运营团队
- 交易所财务管理人员
- 系统管理员和开发人员
2. 系统架构
2.1 架构图
┌─────────────────────────────────────────────┐
│ Exchange Ledger Manager │
└───────────────────────┬─────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Service Layer │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Token │ │ Fiat │ │ OTC │ │
│ │ Service │ │ Service │ │ Service │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└───────────────────────┬─────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Integration Layer │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Blockchain│ │ Bank │ │ Camunda │ │
│ │ Bridge │ │ Bridge │ │ Workflow │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└───────────────────────┬─────────────────────┘
│
▼
┌─────────────────────────────────────────────┐
│ Storage Layer │
│ │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Database │ │ Cache │ │ Queue │ │
│ │ (MySQL) │ │ (Redis) │ │ (RabbitMQ)│ │
│ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────┘
2.2 组件说明
- Service Layer: 包含业务逻辑实现的核心服务层
- Integration Layer: 与外部系统集成的层,如区块链、银行和工作流引擎
- Storage Layer: 存储层,负责数据存储、缓存和消息队列
3. 技术栈
3.1 编程语言和框架
- 主要语言: Go (v1.21.1+)
- Web框架: 自定义框架
- 数据库ORM: GORM
- 工作流引擎: Camunda (使用其Go客户端)
3.2 存储和消息
- 数据库: MySQL/PostgreSQL/SQLite
- 缓存: Redis
- 消息队列: RabbitMQ
3.3 其他工具和库
- 配置管理: Viper
- 日志记录: Zerolog
- 远程调用: gRPC
- 定时任务: gocron
4. 环境要求
- 操作系统: Linux / MacOS / Windows
- Go 版本: 1.21.1 或更高
- 数据库: MySQL 5.7+/PostgreSQL 11+/SQLite 3
- 消息队列: RabbitMQ 3.8+
- Redis: 6.0+(可选,用于缓存)
- Camunda 工作流引擎: 8.x
5. 项目结构
项目采用模块化设计,主要目录结构如下:
exchange-ledger-manager-backend/
├── app/ # 应用程序主要入口和初始化逻辑
├── clients/ # 外部服务的客户端实现
├── cmd/ # 命令行工具
├── config/ # 配置文件和配置加载逻辑
├── consts/ # 常量定义
├── consumers/ # 消息队列消费者实现
├── docs/ # 文档
├── grpc/ # gRPC 服务定义和实现
├── jobworkers/ # 工作流任务处理程序
├── logger/ # 日志相关代码
├── model/ # 数据模型定义
├── modules/ # 核心模块实现
├── otc_provider/ # OTC 服务提供商相关代码
├── service/ # 业务服务实现
├── test/ # 测试代码
├── types/ # 类型定义
├── utils/ # 工具函数
├── go.mod # Go 模块定义
└── main.go # 程序入口
6. 核心功能
6.1 代币充值流程
6.1.1 流程概述
- 用户注册需要充值的币种和数量
- 用户通过钱包转账到指定地址
- 系统通过RabbitMQ接收充值消息
- 开启Camunda流程处理充值请求
- 处理流程包括验证、审核、确认等步骤
- 区块确认达到要求后,资金入账到用户账户
6.1.2 关键代码路径
- 充值消息处理:
consumers/TokenDepositHandler() - 工作流处理:
jobworkers/token_deposit.go - 定时入账任务:
consumers/Deposit() - 冷钱包处理:
service/HandleEnterColdWallet()
6.1.3 特殊情况处理
- 充值救回:当充值金额不匹配注册金额时,系统会等待地址进入白名单状态
- 退款处理:有三种情况会触发退款:其他收入类型、金额不匹配、管理员拒绝
6.2 代币提现流程
提现流程主要处理用户提出的加密货币提现请求,涉及多级审核和链上交易确认。
6.2.1 流程概述
- 用户提交提现请求
- 系统创建提现订单并启动Camunda工作流
- 风控和财务审核流程
- 发起链上提现交易
- 监控交易确认状态
- 更新提现订单状态
6.2.2 关键代码路径
- 提现消息处理:
consumers/TokenWithdrawHandler() - 工作流处理:
jobworkers/token_withdraw.go - 定时任务:
service/HandleAbnormalTokenWithdrawOrders()
6.3 法币充值流程
法币充值处理用户通过银行转账等方式进行的法币充值操作。
6.3.1 流程概述
- 用户提交法币充值请求
- 系统分配唯一参考号
- 用户完成银行转账
- 系统接收银行回调或管理员手动确认
- 处理充值请求并更新用户账户
6.3.2 关键代码路径
- 充值消息处理:
consumers/FiatDepositHandler() - 未验证充值处理:
service/HandleNotVerifiedFiatDepositOrders()
6.4 法币提现流程
法币提现处理用户的法币提现请求,包括审核和银行转账操作。
6.4.1 流程概述
- 用户提交法币提现请求
- 系统创建提现订单并启动工作流
- 进行风控和财务审核
- 发起银行转账
- 更新提现订单状态
6.4.2 关键代码路径
- 提现消息处理:
consumers/FiatWithdrawHandler() - 异常订单处理:
service/HandleAbnormalFiatWithdrawOrders()
6.5 OTC交易结算
处理场外交易的结算流程。
6.5.1 流程概述
- 接收OTC交易结算请求
- 验证交易信息
- 处理资产转移
- 更新交易状态
6.5.2 关键代码路径
- OTC提现处理:
consumers/OtcWithdrawHandler() - OTC结算处理:
service/HandleOTCWithdrawSettleTx()
6.6 白名单管理
管理区块链地址白名单,确保安全和合规。
6.6.1 流程概述
- 用户请求添加白名单地址
- 审核和验证地址
- 添加到白名单
- 定期清理过期白名单
6.6.2 关键代码路径
- 过期白名单处理:
service/HandleExpiredBlockchainWhiteList() - 重新添加处理:
service/HandleExpiredBlockchainWhiteListReadded()
7. 业务流程
7.1 代币充值业务流程
7.2 代币提现业务流程
7.3 法币充值业务流程
7.4 法币提现业务流程
7.5 Token退款业务流程
7.6 OTC结算交易业务流程
7.7 白名单管理业务流程
8. 数据库设计
项目使用GORM作为ORM框架,支持MySQL、PostgreSQL和SQLite数据库。主要数据表设计如下:
8.1 核心数据表
8.1.1 资产表 (assets)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| name | varchar | 资产名称 |
| type | varchar | 资产类型: TOKEN FIAT |
| icon | varchar | 币种 |
| status | varchar | 状态: ENABLE DISABLE |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.2 区块链表 (blockchains)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| blockchain_id | bigint | 区块链id(取自blockchain bridge服务中的blockchians表中的id字段) |
| blockchain_name | varchar | 区块链名称 |
| blockchain_full_name | varchar | 区块链全称 |
| explorer | varchar | 区块链浏览器url |
| is_evm | bool | 是否是以太坊兼容链 |
| is_bitcoin | bool | 是否是比特币兼容链 |
| elliptic_blockchain_name | varchar | 用于在KYT/KYA时给传递给risk服务的区块链名称 参考这里 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.3 资产映射表 (asset_tokens)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| asset_name | varchar | 资产名称 |
| token_id | bigint | 取自blockchain bridge服务中tokens表中的id字段 |
| asset_type | varchar | 资产类型: TOKEN FIAT |
| blockchain_id | bigint | 资产所在的区块链id |
| blockchain_name | varchar | 资产所在区块链名称 |
| explorer | varchar | 区块链浏览器url |
| is_evm | bool | 资产所在区块链是否是以太坊兼容链 |
| status | varchar | 状态: ENABLE DISABLE |
| is_bitcoin | bool | 是否为比特币兼容链 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.4 用户钱包表 (user_wallets)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| user_id | varchar | 用户id |
| wallet_type | varchar | 钱包类型: BLOCKCHAIN BANK |
| wallet_id | bigint | 取自blockchain_bridge 中wallets表里的id字段,用户获取充值地址后从blockchain bridge服务获取,不需要手动配置 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.5 提现配置表 (withdraw_configs)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| asset_name | varchar | 资产名称 |
| blockchain_name | varchar | 区块链名称 (数字币时使用) |
| fee | decimal | 提现手续费 |
| minimum_amount | decimal | 最小提现数量 |
| blockchain_confirmations | bigint | 区块链确认数 (数字币时使用) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.6 充值配置表 (deposit_configs)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| asset_name | varchar | 资产名称 |
| blockchain_name | varchar | 区块链名称 (数字币时使用) |
| minimum_amount | decimal | 最小充值数量 |
| blockchain_confirmations | bigint | 区块链确认数 (数字币时使用) |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.7 充值限额表 (deposit_limits)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| asset_name | varchar | 资产名称 |
| limit | decimal | 最大充值数量 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.8 提现限额表 (withdraw_limits)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| asset_name | varchar | 资产名称 |
| limit | decimal | 最大提现数量 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.9 OTC供应商表 (otc_providers)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| name | varchar | 供应商名称 |
| api | varchar | 暂不使用 |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.10 OTC币对供应商配置(otc_provider_symbol_configs)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| provider_name | varchar | 供应商名称 |
| symbol | varchar | OTC 币对,格式: BTC_USD |
| base_asset_name | varchar | base 资产 |
| quote_asset_name | varchar | quote 资产 |
| status | varchar | 状态: OPEN CLOSED |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
8.1.11 OTC供应商限额配置表(otc_provider_limit_configs)
| 字段名 | 类型 | 描述 |
|---|---|---|
| id | bigint | 主键ID |
| provider_name | varchar | 供应商名称 |
| quote_asset_name | varchar | quote资产名称:USD |
| quote_total_limit | decimal | 以quote资产计价的供应商总额度 |
| quote_used_limit | decimal | 以quote资产计价的供应商已使用额度 |
| is_in_settle | bool | 状态: OPEN CLOSED |
| created_at | datetime | 创建时间 |
| updated_at | datetime | 更新时间 |
9. API接口
系统采用gRPC作为主要接口方式,提供以下服务接口:
9.1 Ledger Manager gRPC服务
所有的gRPC接口都在grpc目录下的go文件中定义并实现
10. 部署指南
10.1 环境准备
- 安装Go 1.21.1或更高版本
- 安装并配置MySQL/PostgreSQL数据库
- 安装并配置RabbitMQ
- 安装并配置Camunda工作流引擎
10.2 配置文件
项目使用TOML格式的配置文件,主要配置项如下:
toml
[log]
level = "debug"
# json, console
format = "console"
[common]
tosLink = "https://www.894569.com/en-US"
privacyLink = "https://www.894569.com/en-US"
# user服务的api key
userApiKey = "business-key-1234"
[duration]
#白名单有效期
BlockchainWhiteListExpireDuration = "4320h"
[limit]
#用户最大充值白名单个数
maxTokenDepositWhiteList = 20
#用户最大提现白名单个数
maxTokenWithdrawWhiteList = 20
#用户最大法币白名单个数(法币不区分充值和提现)
maxFiatWhiteList = 10
[db]
enable = true
# silent info warn error
logLevel = "info"
driver = "mysql"
dsn = ""
[camunda]
enable = true
gateway = "10.1.9.88:26501"
# unit: minute
# job worker失败后重试间隔
retryInterval = 5
[grpc]
enable = true
host = "0.0.0.0"
port = 9098
[rabbitmq]
enable = true
url = ""
# 数字币充值提现exchange
exchangeCrypto = "topic.exchange.wallet_bridge.transaction"
# 数字币充值topic
topicDeposit = "DEPOSIT"
# 数字币充值其他收入topic
topicDepositOtherIncome = "OTHER_INCOME"
# 数字币提现topic
topicWithdraw = "WITHDRAW"
# 数字币otc提现topic
topicOtcWithdraw = "OTC_OUTCOME"
# 数字币退款topic
topicRefund = "REFUND"
# 法币充值提现exchange
exchangeFiat = "exchange"
# 法币充值topic
topicFiatDeposit = "fo.ex.bank-bridge.callBack.Transaction"
# 法币提现topic
topicFiatWithdraw = "fo.ex.bank-bridge.callBack.Withdrawal"
# 法币利润提现topic
topicProfitWithdraw = "PROFIT_WITHDRAW"
[grpcClient]
enable = true
blockchainBridgeUrl = "10.1.9.119:9000"
notifyUrl = "10.1.9.121:9093"
fundingUrl = "10.1.9.112:9088"
spotUrl = "10.1.9.115:9083"
bankBridgeUrl = "10.1.9.121:9011"
riskUrl = "10.1.9.121:9015"
userQueryUrl = "10.1.9.115:9082"
currencyUrl = "10.1.9.121:9094"
quoteUrl = "10.1.9.112:5000"
otcUrl = "10.1.9.112:9200"
statisUrl = "10.1.9.121:"
userAttributeUrl = ""
quotaUrl = ""
quoter2Url = ""
[httpClient]
blockchainVerifierUrl = ""
[otc]
enable = true
# LP 最少个数(当可用LP报价数小于该值后不向客户提供报价)
minProvider = 1
# 用户确认报价后是否真实调用LP接口,用于测试
execute = false
# OTC Liquid Provider 配置
[otc.falconx]
baseUrl = "https://api.falconx.io"
secret = ""
apiKey = ""
passphrase = ""
[otc.virgocx]
# wealth.sandbox.virgocx.ca in sandbox, and wealth.virgocx.ca in production
websocketUrl = "wealth.sandbox.virgocx.ca"
secret = ""
apiKey = ""
# 弃用
[yahoo]
# 弃用
apiKey = ""
# 弃用
fiatList = "USD,CAD,EUR,GBP,JPY,AUD,CNY"
[format]
# 显示用户资产折合成usdt时的精度
usdtPrecision = 2
[cache]
expiration = "60m"
cleanUpInterval = "10m"10.3 环境变量覆盖默认配置
以上配置可以通过环境变量进行覆盖,环境变量的格式为LEDGER_XX_YY
比如log下面的level可以通过环境变量LEDGER_LOG_LEVEL来覆盖,这也是在Nomad中配置参数的方式。
10.3 数据库配置
10.4 编译和运行
10.4.1 本地编译
bash
cd exchange-ledger-manager-backend
# 编译
make build-linux
# 配置文件
cp config.toml <dest_dir>
cp ledger-manager <dest_dir>
# 运行
cd <dest_dir>
./ledger-manager10.4.2 Docker部署
bash
# 构建Docker镜像
docker build -t ledger-manager:latest .
# 运行容器
docker run -d --name ledger-manager \
-v $(pwd)/config.toml:/app/config.toml \
-p 9098:9098 \
ledger-manager:latest11. 常见问题
11.1 流程排查
对于所有使用camunda流程的功能,都可以在camunda operate 中查看状态,在里面可以查看流程走到哪里以及是否有错误。
附录: 主要依赖库
- github.com/ethereum/go-ethereum: 以太坊客户端库
- github.com/go-co-op/gocron/v2: 定时任务库
- github.com/go-redis/redis/v8: Redis客户端
- github.com/gorilla/websocket: WebSocket支持
- github.com/latifrons/latigo: 通用工具库
- github.com/rs/zerolog: 结构化日志库
- github.com/spf13/viper: 配置管理库
- github.com/camunda/zeebe/clients/go/v8: Camunda Zeebe客户端
- github.com/rabbitmq/amqp091-go: RabbitMQ客户端
- gorm.io/gorm: ORM库
- google.golang.org/grpc: gRPC库
