diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..cabc17c
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,24 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 4
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.{yml,yaml}]
+indent_size = 2
+
+[*.{json,xml}]
+indent_size = 2
+
+[*.md]
+trim_trailing_whitespace = false
+
+[*.gradle]
+indent_size = 4
+
+[Dockerfile]
+indent_size = 4
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..e735967
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,25 @@
+# Database
+DB_URL=jdbc:mysql://127.0.0.1:3306/wallet_db?allowMultiQueries=true&useSSL=false&characterEncoding=UTF-8&autoReconnect=true
+DB_USERNAME=root
+DB_PASSWORD=your_secure_password
+
+# RabbitMQ
+RABBITMQ_HOST=127.0.0.1
+RABBITMQ_PORT=5672
+RABBITMQ_USERNAME=guest
+RABBITMQ_PASSWORD=guest
+
+# XXL-Job
+XXL_JOB_ADMIN_ADDRESSES=http://127.0.0.1:8099/xxl-job-admin
+XXL_JOB_PORT=9999
+XXL_JOB_ACCESS_TOKEN=your_access_token
+
+# HSM Keystore
+KEYSTORE_DIR=/data/keystores
+KEYSTORE_PASSWORD=your_keystore_password
+
+# Encryption
+WALLET_CRYPTO_PUSH_KEY=your_32_char_encryption_key_here
+
+# Logging
+LOG_LEVEL=INFO
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..1ba381c
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,75 @@
+name: CI
+
+on:
+ push:
+ branches: [ master, develop ]
+ pull_request:
+ branches: [ master ]
+
+permissions:
+ contents: read
+
+jobs:
+ build:
+ name: Build & Test
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+
+ - name: Setup Gradle
+ uses: gradle/actions/setup-gradle@v3
+ with:
+ cache-read-only: ${{ github.ref != 'refs/heads/master' }}
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Build
+ run: ./gradlew build -x test --no-daemon
+
+ - name: Run tests
+ run: ./gradlew test --no-daemon
+ continue-on-error: true
+
+ - name: Upload build artifacts
+ uses: actions/upload-artifact@v4
+ with:
+ name: build-artifacts
+ path: |
+ wallet-webapi/build/libs/*.jar
+ wallet-task/build/libs/*.jar
+ wallet-hsm/build/libs/*.jar
+ retention-days: 7
+
+ docker:
+ name: Docker Build
+ runs-on: ubuntu-latest
+ needs: build
+ if: github.ref == 'refs/heads/master'
+
+ strategy:
+ matrix:
+ service: [wallet-webapi, wallet-task, wallet-hsm]
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+
+ - name: Build Docker image
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ file: ./${{ matrix.service }}/Dockerfile
+ push: false
+ tags: ${{ matrix.service }}:${{ github.sha }}
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
diff --git a/.gitignore b/.gitignore
index c451244..011d811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,20 +1,41 @@
+# Gradle
.gradle/
build/
+!gradle/wrapper/gradle-wrapper.jar
+
+# IDE
.settings/
.project
.classpath
-*.class
-.idea
+.idea/
*.iml
-.gradle
-/local.properties
-.DS_Store
-/build
+*.iws
+*.ipr
+
+# Compiled
+*.class
+out/
/*/out/
-out
-/wallets
-/task-logs
-shell
-nginx
-docker
+# OS
+.DS_Store
+Thumbs.db
+
+# Local config
+/local.properties
+*.env
+!.env.example
+
+# Application data
+/wallets/
+/task-logs/
+/logs/
+
+# Docker local
+shell/
+nginx/
+
+# Secrets - never commit
+*.p12
+*.jks
+*.keystore
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ebc9352..0bb389e 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,6 @@
variables:
DOCKER_DRIVER: overlay2
+ GRADLE_OPTS: "-Dorg.gradle.daemon=false"
stages:
- build
@@ -9,62 +10,85 @@ cache:
key: ${CI_BUILD_STAGE}
paths:
- .gradle
+ - build
-build for all:
- image: openjdk:8-jdk-alpine
+build:
+ image: eclipse-temurin:17-jdk-alpine
tags:
- wallet-dev
stage: build
script:
- - pwd
- - ./gradlew wallet-webapi:bootRepackage
- - ./gradlew wallet-task:bootRepackage
- - ./gradlew wallet-hsm:bootRepackage
+ - chmod +x ./gradlew
+ - ./gradlew wallet-webapi:bootJar --no-daemon -x test
+ - ./gradlew wallet-task:bootJar --no-daemon -x test
+ - ./gradlew wallet-hsm:bootJar --no-daemon -x test
artifacts:
paths:
- wallet-webapi/build/libs/*.jar
- wallet-hsm/build/libs/*.jar
- wallet-task/build/libs/*.jar
- expire_in: 20min
+ expire_in: 1 hour
-deploy for cl-webapi:
- image: gitlab/dind:latest
+deploy wallet-webapi:
+ image: docker:latest
+ services:
+ - docker:dind
tags:
- wallet-dev
stage: deploy
script:
- - docker stop -f wallet-webapi ||true
- - docker rm -f wallet-webapi ||true
- - docker rmi wallet-webapi ||true
- - docker build -t wallet-webapi wallet-webapi/.
- - docker run -d --name wallet-webapi -p 10001:10001 -v /etc/localtime:/etc/localtime cl-webapi
+ - docker stop wallet-webapi || true
+ - docker rm wallet-webapi || true
+ - docker rmi wallet-webapi || true
+ - docker build -t wallet-webapi -f wallet-webapi/Dockerfile .
+ - docker run -d --name wallet-webapi
+ --restart unless-stopped
+ -p 10001:10001
+ -v /etc/localtime:/etc/localtime:ro
+ --env-file /etc/wallet/webapi.env
+ wallet-webapi
when: manual
-deploy for cl-task:
- image: gitlab/dind:latest
+deploy wallet-task:
+ image: docker:latest
+ services:
+ - docker:dind
tags:
- wallet-dev
stage: deploy
script:
- - docker stop -f wallet-task ||true
- - docker rm -f wallet-task ||true
- - docker rmi wallet-task ||true
- - docker build -t wallet-task wallet-task/.
- - docker run -d --name wallet-task -p 10033:10033 -v /etc/localtime:/etc/localtime wallet-task
+ - docker stop wallet-task || true
+ - docker rm wallet-task || true
+ - docker rmi wallet-task || true
+ - docker build -t wallet-task -f wallet-task/Dockerfile .
+ - docker run -d --name wallet-task
+ --restart unless-stopped
+ -p 10033:10033
+ -v /etc/localtime:/etc/localtime:ro
+ --env-file /etc/wallet/task.env
+ wallet-task
when: manual
-deploy for cl-hsm:
- image: gitlab/dind:latest
+deploy wallet-hsm:
+ image: docker:latest
+ services:
+ - docker:dind
tags:
- wallet-dev
stage: deploy
script:
- - docker stop -f wallet-hsm ||true
- - docker rm -f wallet-hsm ||true
- - docker rmi wallet-hsm ||true
- - docker build -t wallet-hsm wallet-hsm/.
- - docker run -d --name wallet-hsm -p 10888:10888 -v /etc/localtime:/etc/localtime -v /mnt/wallets:/mnt/wallets cl-hsm
+ - docker stop wallet-hsm || true
+ - docker rm wallet-hsm || true
+ - docker rmi wallet-hsm || true
+ - docker build -t wallet-hsm -f wallet-hsm/Dockerfile .
+ - docker run -d --name wallet-hsm
+ --restart unless-stopped
+ -p 10888:10888
+ -v /etc/localtime:/etc/localtime:ro
+ -v /mnt/wallets:/data/keystores
+ --env-file /etc/wallet/hsm.env
+ wallet-hsm
when: manual
after_script:
- - echo "End CI"
\ No newline at end of file
+ - echo "End CI"
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 4aa893f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-sudo: required
-dist: trusty
-
-matrix:
- include:
- - os: linux
- jdk: openjdk8
- - os: osx
- osx_image: xcode8
-
-language: java
-
-install: unset _JAVA_OPTIONS
-script:
-- chmod +x ./gradlew
-- ./gradlew build
-
-before_cache:
-- rm -f $HOME/.gradle/caches/{modules-2,transforms-1}/*.lock
-- rm -rf $HOME/.gradle/caches/*/{file-changes,fileHashes,plugin-resolution,scripts,scripts-remapped,gradle-script-kotlin}/
-cache:
- directories:
- - $HOME/.gradle/caches/
- - $HOME/.gradle/wrapper/
-
-notifications:
- email: false
\ No newline at end of file
diff --git a/README.md b/README.md
index 8d8ec2b..c5e8da1 100644
--- a/README.md
+++ b/README.md
@@ -1,52 +1,209 @@
Java-Wallet
-
-
-
-
+ Production-grade multi-chain cryptocurrency wallet backend
-## Demo Access
+
+
+
+
+
+
+
+
+
+
-- **Backend Management:** [Link](http://34.152.57.199:10001)
-
- *For account access, please contact me via Telegram.*
-
-- **Scheduled Task Management:** [Link](http://34.152.57.199:8081/xxl-job-admin)
+
+ 中文文档 ·
+ Telegram ·
+ Issues ·
+ Quick Start
+
- *For account access, please contact me via Telegram.*
+---
## Introduction
-Java-Wallet is a powerful business system built upon the functional components of digital currency. It's designed to obtain blockchain addresses from various public chains, offering deposit and withdrawal functionalities for multiple currencies including BTC, OMNI, ETH, ERC20, TRX, TRC20, BCH, BSV, DOGE, DASH, and LTC.
+Java-Wallet is a battle-tested multi-chain cryptocurrency wallet backend that has safely managed hundreds of millions of dollars in transactions in production. It provides blockchain address generation, deposit detection, withdrawal processing, and automated fund sweeping across all major public chains.
+
+The core signing component [tokencore](https://github.com/GalaxySciTech/tokencore) performs all cryptographic operations locally — private keys never leave the process.
+
+### Supported Chains
+
+| Chain | Native | Token |
+|:------|:------:|:-----:|
+| Bitcoin | BTC | OMNI (USDT) |
+| Ethereum | ETH | ERC-20 |
+| Tron | TRX | TRC-20 |
+| Bitcoin Cash | BCH | — |
+| Bitcoin SV | BSV | — |
+| Litecoin | LTC | — |
+| Dogecoin | DOGE | — |
+| Dash | DASH | — |
+
+## Architecture
+
+```
+ ┌──────────────────────────────────────────────┐
+ │ Client / Admin UI │
+ └──────────────────┬───────────────────────────┘
+ │ HTTP
+ ┌───────────────────────────┼───────────────────────────┐
+ │ │ │
+ ┌───────▼────────┐ ┌────────▼────────┐ ┌───────▼────────┐
+ │ wallet-webapi │ │ wallet-task │ │ wallet-hsm │
+ │ REST API │ │ Scheduled Jobs │ │ Key Management │
+ │ :10001 │ │ :10033 │ │ :10888 │
+ └───────┬─────────┘ └────────┬─────────┘ └───────┬─────────┘
+ │ │ │
+ └────────────┬───────────────┘ │
+ │ │
+ ┌───────▼────────┐ ┌───────▼────────┐
+ │ wallet-common │ │ wallet-entity │
+ │ Business Logic │◄─────────────────────────│ JPA / Data │
+ └──┬─────┬─────┬─┘ └───────┬─────────┘
+ │ │ │ │
+ ┌────▼┐ ┌──▼──┐ ┌▼──────┐ ┌───────▼────────┐
+ │ RPC │ │ MQ │ │xxl-job│ │ MySQL 8 │
+ │Nodes│ │ │ │ │ └────────────────┘
+ └─────┘ └─────┘ └───────┘
+```
+
+| Module | Description |
+|:-------|:------------|
+| **wallet-webapi** | REST API — address generation, deposits & withdrawals, admin dashboard, Swagger docs |
+| **wallet-task** | Scheduled jobs — block syncing, deposit detection, auto-sweeping, fee top-up |
+| **wallet-hsm** | Key management — HD wallet derivation, offline signing, key import/export |
+| **wallet-common** | Shared layer — business logic, RPC clients, caching, utilities |
+| **wallet-entity** | Data layer — JPA entities, repositories, QueryDSL |
+
+## Tech Stack
+
+| Category | Technology |
+|:---------|:-----------|
+| Language | Kotlin 1.9 + Java 17 |
+| Framework | Spring Boot 3.1.3 |
+| Build | Gradle 8.5 |
+| Database | MySQL 8.0 · Spring Data JPA · HikariCP |
+| Cache | Caffeine |
+| Message Queue | RabbitMQ (Spring AMQP) |
+| Task Scheduling | xxl-job 2.4.0 |
+| Blockchain | [tokencore 1.3.0](https://github.com/GalaxySciTech/tokencore) · web3j 4.10.3 · bitcoin-rpc-client 1.2.4 |
+| API Docs | SpringDoc OpenAPI 2.3 (Swagger UI) |
+| Container | Docker multi-stage · docker-compose |
+| CI/CD | GitHub Actions · GitLab CI |
+
+## Quick Start
+
+### Prerequisites
+
+- JDK 17+
+- MySQL 8.0+
+- RabbitMQ 3.x (required by wallet-task)
+
+### Docker Compose (Recommended)
+
+```bash
+git clone https://github.com/GalaxySciTech/java-wallet.git
+cd java-wallet
+
+cp .env.example .env # edit with your settings
+docker-compose up -d
+```
+
+Once running:
+- **API**: http://localhost:10001
+- **Swagger UI**: http://localhost:10001/swagger-ui.html
+- **RabbitMQ Console**: http://localhost:15672
+
+### Manual Setup
+
+```bash
+# 1. Set environment variables (see .env.example for full list)
+export DB_URL="jdbc:mysql://localhost:3306/wallet_db?useSSL=false&characterEncoding=UTF-8"
+export DB_USERNAME=root
+export DB_PASSWORD=your_password
+
+# 2. Build
+chmod +x gradlew
+./gradlew build -x test
+
+# 3. Run each service in a separate terminal
+./gradlew :wallet-webapi:bootRun
+./gradlew :wallet-task:bootRun
+./gradlew :wallet-hsm:bootRun
+```
+
+## Configuration
+
+All sensitive values are injected via environment variables — nothing is hardcoded. See [`.env.example`](.env.example) for the full list.
+
+| Variable | Service | Description |
+|:---------|:--------|:------------|
+| `DB_URL` | webapi, task | MySQL JDBC connection URL |
+| `DB_USERNAME` / `DB_PASSWORD` | webapi, task | Database credentials |
+| `RABBITMQ_HOST` / `RABBITMQ_PASSWORD` | task | RabbitMQ connection |
+| `KEYSTORE_DIR` / `KEYSTORE_PASSWORD` | hsm | Keystore path and password |
+| `XXL_JOB_ADMIN_ADDRESSES` | task | xxl-job scheduler address |
+| `WALLET_CRYPTO_PUSH_KEY` | webapi | AES key for deposit push notifications |
+
+## API Reference
+
+### Wallet API `/wallet/v1`
+
+| Method | Endpoint | Description |
+|:------:|:---------|:------------|
+| POST | `/get_address` | Generate new blockchain addresses in batch |
+| POST | `/send` | Withdraw (specify `from` or auto-select from hot wallet) |
+| POST | `/create_hot_address` | Create a hot wallet or gas wallet |
+| POST | `/export_wallet` | Export private key or mnemonic |
+| POST | `/import_wallet` | Import private key or mnemonic |
+| GET | `/get_hot_address` | Query hot wallet addresses |
+| GET | `/check_address` | Check if address private key exists |
+| GET | `/get_transaction` | Query deposit / withdrawal / sweep records |
+| GET | `/get_new_deposit` | Fetch new deposits (marked as read after fetch) |
+| GET | `/check_tx_status` | Check on-chain transaction status |
+
+### Blockchain API `/block_chain/v1`
+
+| Method | Endpoint | Description |
+|:------:|:---------|:------------|
+| GET | `/get_transaction` | Query on-chain transaction details |
+| GET | `/get_address_balance` | Query on-chain address balance |
+| GET | `/get_recommend_fee` | Get recommended fees (slow / medium / fast) |
+| GET | `/calculation_fee` | Calculate transaction fee |
+| GET | `/get_support_token` | List all supported tokens |
+
+### Admin API `/admin`
+
+| Method | Endpoint | Description |
+|:------:|:---------|:------------|
+| POST | `/login` | Admin login |
+| GET | `/get_dashboard` | Dashboard overview |
+| GET | `/get_addr_list` | Address list |
+| GET | `/get_token_list` | Token list |
+| POST | `/edit_token` | Edit token configuration |
+| POST | `/edit_config` | Edit system configuration |
+| POST | `/edit_white` | Edit IP whitelist |
+
+> Full interactive API docs are available at Swagger UI after starting the service.
-**Key Features:**
-- Dynamic retrieval of blockchain addresses.
-- Seamless deposit and withdrawal functions for multiple cryptocurrencies.
-- API-centric design for easy integration.
-
-**Technical Highlights:**
-- Developed using the SpringBoot framework.
-- Written in Java and Kotlin.
-- Utilizes RabbitMQ for messaging.
-- Employs MySQL for cloud database management.
-- Integrates xxl-job for distributed scheduled tasks.
+## Reliability
-## Architecture Overview
+Java-Wallet has been running in production and has safely processed hundreds of millions of dollars in transactions. It is built for high reliability, scalability, and real-world utility.
-
-
-
+## Contact
-## Reliability
+For technical support, business inquiries, or deployment consulting:
-Java-Wallet is a robust platform that has been rigorously tested, having managed transactions worth hundreds of millions of dollars in a production environment. It boasts high reliability, scalability, and utility, ensuring confidence in its deployment and use.
+**[@GalaxySciTech](https://t.me/GalaxySciTech)** on Telegram
-## Support
+## Disclaimer
-If you encounter any issues or require further clarification, feel free to [submit an issue](https://github.com/galaxyscitech/java-wallet/issues).
+Any commercial use of this source code is at your own risk. The authors assume no liability for any losses incurred by yourself or others.
-## Disclaimer
+## License
-Please note that any commercial activities pursued using this source code, which result in losses (either to oneself or to others), are the sole responsibility of the user. I hold no liability for such outcomes.
+This project is provided as-is. See the repository for license details.
diff --git a/README_CN.md b/README_CN.md
new file mode 100644
index 0000000..026ae0c
--- /dev/null
+++ b/README_CN.md
@@ -0,0 +1,209 @@
+Java-Wallet
+
+
+ 生产级多链加密货币钱包后台系统
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ English ·
+ Telegram ·
+ Issues ·
+ 快速开始
+
+
+---
+
+## 简介
+
+Java-Wallet 是一套经过生产环境验证的多链加密货币钱包后台系统,曾稳定管理过数亿美元级别的交易。系统提供区块链地址生成、充值检测、提现处理和自动归集等核心功能,支持主流公链和代币。
+
+核心签名组件 [tokencore](https://github.com/GalaxySciTech/tokencore) 支持全链离线签名,私钥全程本地运算,从不外泄。
+
+### 支持的公链
+
+| 公链 | 原生币 | 代币 |
+|:-----|:------:|:----:|
+| Bitcoin | BTC | OMNI (USDT) |
+| Ethereum | ETH | ERC-20 |
+| Tron | TRX | TRC-20 |
+| Bitcoin Cash | BCH | — |
+| Bitcoin SV | BSV | — |
+| Litecoin | LTC | — |
+| Dogecoin | DOGE | — |
+| Dash | DASH | — |
+
+## 系统架构
+
+```
+ ┌──────────────────────────────────────────────┐
+ │ 客户端 / 管理后台 UI │
+ └──────────────────┬───────────────────────────┘
+ │ HTTP
+ ┌───────────────────────────┼───────────────────────────┐
+ │ │ │
+ ┌───────▼────────┐ ┌────────▼────────┐ ┌───────▼────────┐
+ │ wallet-webapi │ │ wallet-task │ │ wallet-hsm │
+ │ REST 接口 │ │ 定时任务 │ │ 密钥管理 │
+ │ :10001 │ │ :10033 │ │ :10888 │
+ └───────┬─────────┘ └────────┬─────────┘ └───────┬─────────┘
+ │ │ │
+ └────────────┬───────────────┘ │
+ │ │
+ ┌───────▼────────┐ ┌───────▼────────┐
+ │ wallet-common │ │ wallet-entity │
+ │ 业务逻辑 │◄─────────────────────────│ 数据访问层 │
+ └──┬─────┬─────┬─┘ └───────┬─────────┘
+ │ │ │ │
+ ┌────▼┐ ┌──▼──┐ ┌▼──────┐ ┌───────▼────────┐
+ │ RPC │ │ MQ │ │xxl-job│ │ MySQL 8 │
+ │ 节点 │ │ │ │ │ └────────────────┘
+ └─────┘ └─────┘ └───────┘
+```
+
+| 模块 | 说明 |
+|:-----|:-----|
+| **wallet-webapi** | REST API — 地址生成、充提币、管理后台、Swagger 文档 |
+| **wallet-task** | 定时任务 — 区块同步、充值检测、自动归集、手续费补发 |
+| **wallet-hsm** | 密钥管理 — HD 钱包派生、离线签名、私钥导入导出 |
+| **wallet-common** | 公共层 — 业务逻辑、RPC 客户端、缓存、工具类 |
+| **wallet-entity** | 数据层 — JPA 实体、Repository、QueryDSL |
+
+## 技术栈
+
+| 类别 | 技术 |
+|:-----|:-----|
+| 语言 | Kotlin 1.9 + Java 17 |
+| 框架 | Spring Boot 3.1.3 |
+| 构建 | Gradle 8.5 |
+| 数据库 | MySQL 8.0 · Spring Data JPA · HikariCP |
+| 缓存 | Caffeine |
+| 消息队列 | RabbitMQ (Spring AMQP) |
+| 任务调度 | xxl-job 2.4.0 |
+| 区块链 | [tokencore 1.3.0](https://github.com/GalaxySciTech/tokencore) · web3j 4.10.3 · bitcoin-rpc-client 1.2.4 |
+| 接口文档 | SpringDoc OpenAPI 2.3 (Swagger UI) |
+| 容器化 | Docker 多阶段构建 · docker-compose |
+| CI/CD | GitHub Actions · GitLab CI |
+
+## 快速开始
+
+### 环境要求
+
+- JDK 17+
+- MySQL 8.0+
+- RabbitMQ 3.x(wallet-task 需要)
+
+### Docker Compose(推荐)
+
+```bash
+git clone https://github.com/GalaxySciTech/java-wallet.git
+cd java-wallet
+
+cp .env.example .env # 编辑配置
+docker-compose up -d
+```
+
+服务启动后:
+- **API 接口**: http://localhost:10001
+- **Swagger 文档**: http://localhost:10001/swagger-ui.html
+- **RabbitMQ 管理**: http://localhost:15672
+
+### 手动部署
+
+```bash
+# 1. 配置环境变量(完整列表见 .env.example)
+export DB_URL="jdbc:mysql://localhost:3306/wallet_db?useSSL=false&characterEncoding=UTF-8"
+export DB_USERNAME=root
+export DB_PASSWORD=your_password
+
+# 2. 构建项目
+chmod +x gradlew
+./gradlew build -x test
+
+# 3. 启动服务(分别在不同终端运行)
+./gradlew :wallet-webapi:bootRun
+./gradlew :wallet-task:bootRun
+./gradlew :wallet-hsm:bootRun
+```
+
+## 配置说明
+
+所有敏感配置均通过环境变量注入,绝不硬编码在代码中。完整列表见 [`.env.example`](.env.example)。
+
+| 变量 | 服务 | 说明 |
+|:-----|:-----|:-----|
+| `DB_URL` | webapi, task | MySQL JDBC 连接地址 |
+| `DB_USERNAME` / `DB_PASSWORD` | webapi, task | 数据库用户名和密码 |
+| `RABBITMQ_HOST` / `RABBITMQ_PASSWORD` | task | RabbitMQ 连接信息 |
+| `KEYSTORE_DIR` / `KEYSTORE_PASSWORD` | hsm | 密钥库存储路径与密码 |
+| `XXL_JOB_ADMIN_ADDRESSES` | task | xxl-job 调度中心地址 |
+| `WALLET_CRYPTO_PUSH_KEY` | webapi | 充值推送通知 AES 加密密钥 |
+
+## 接口文档
+
+### 钱包接口 `/wallet/v1`
+
+| 方法 | 路径 | 说明 |
+|:----:|:-----|:-----|
+| POST | `/get_address` | 批量生成区块链地址 |
+| POST | `/send` | 提现(可指定 from 地址,不指定则自动从热钱包转出) |
+| POST | `/create_hot_address` | 创建热钱包 / Gas 钱包地址 |
+| POST | `/export_wallet` | 导出私钥或助记词 |
+| POST | `/import_wallet` | 导入私钥或助记词 |
+| GET | `/get_hot_address` | 查询热钱包地址 |
+| GET | `/check_address` | 验证地址私钥是否存在 |
+| GET | `/get_transaction` | 查询充值/提现/归集记录 |
+| GET | `/get_new_deposit` | 获取新充值记录(拉取后自动标记已读) |
+| GET | `/check_tx_status` | 查询链上交易状态 |
+
+### 区块链接口 `/block_chain/v1`
+
+| 方法 | 路径 | 说明 |
+|:----:|:-----|:-----|
+| GET | `/get_transaction` | 链上查询交易详情 |
+| GET | `/get_address_balance` | 链上查询地址余额 |
+| GET | `/get_recommend_fee` | 获取推荐手续费(低速/中速/快速) |
+| GET | `/calculation_fee` | 计算交易手续费 |
+| GET | `/get_support_token` | 获取支持的币种列表 |
+
+### 管理后台接口 `/admin`
+
+| 方法 | 路径 | 说明 |
+|:----:|:-----|:-----|
+| POST | `/login` | 管理员登录 |
+| GET | `/get_dashboard` | 获取仪表盘概览数据 |
+| GET | `/get_addr_list` | 获取地址列表 |
+| GET | `/get_token_list` | 获取代币列表 |
+| POST | `/edit_token` | 编辑代币配置 |
+| POST | `/edit_config` | 编辑系统配置 |
+| POST | `/edit_white` | 编辑 IP 白名单 |
+
+> 完整的交互式接口文档请在启动服务后访问 Swagger UI。
+
+## 可靠性
+
+Java-Wallet 已在生产环境中长期稳定运行,安全管理过数亿美元的交易量。系统具备高可靠性、可扩展性和实用性,值得信赖。
+
+## 联系我们
+
+如需技术支持、商业合作或部署咨询,请通过 Telegram 联系:
+
+**[@GalaxySciTech](https://t.me/GalaxySciTech)**
+
+## 免责声明
+
+使用本源代码进行的任何商业活动,由此产生的损失(无论是对自己还是对他人)均由使用者自行承担,作者不对此承担任何责任。
+
+## 许可证
+
+本项目按原样提供,详见仓库中的许可证文件。
diff --git a/build.gradle b/build.gradle
index ae59870..5904868 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,9 +8,9 @@ allprojects {
}
repositories {
mavenLocal()
- maven {url 'https://maven.aliyun.com/repository/public/'}
+ maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://jitpack.io' }
- maven { url "https://kotlin.bintray.com/kotlinx" }
+ mavenCentral()
}
tasks.withType(JavaCompile) {
@@ -32,13 +32,13 @@ subprojects {
apply plugin: 'org.springframework.boot'
apply plugin: "io.spring.dependency-management"
- sourceCompatibility = 1.8
+ sourceCompatibility = 17
compileKotlin {
- kotlinOptions.jvmTarget = "1.8"
+ kotlinOptions.jvmTarget = "17"
}
compileTestKotlin {
- kotlinOptions.jvmTarget = "1.8"
+ kotlinOptions.jvmTarget = "17"
}
tasks.withType(JavaCompile) {
@@ -46,65 +46,34 @@ subprojects {
}
-// dependencyManagement {
-// imports {
-// mavenBom 'org.springframework.cloud:spring-cloud-dependencies:Dalston.RELEASE'
-// }
-// }
-
-
dependencies {
- compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
- compile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
- compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
- compile "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
- compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
- compile "org.springframework.boot:spring-boot-starter-cache:$springBootVersion"
- compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
- compile 'com.zaxxer:HikariCP:5.0.1'
- compile 'mysql:mysql-connector-java:5.1.40'
-// compile "org.springframework.boot:spring-boot-devtools:$springBootVersion"
- compile 'org.apache.commons:commons-lang3:3.8.1'
- compileOnly 'org.projectlombok:lombok:1.18.6'
- compile 'commons-beanutils:commons-beanutils:1.9.4'
-// compile "org.springframework.boot:spring-boot-starter-data-redis:$springBootVersion"
- compile 'org.web3j:core:4.2.0'
- compile 'wf.bitcoin:bitcoin-rpc-client:1.1.0'
-// compile 'com.github.EOSEssentials:eos-java-rpc-wrapper:master'
-
- // API Doc Generator: Swagger
- compile group: 'io.springfox', name: 'springfox-swagger2', version: '2.6.1'
- compile group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.6.1'
- compile "org.springframework.boot:spring-boot-starter-amqp:$springBootVersion"
- compile 'com.github.ben-manes.caffeine:caffeine:3.1.8'
- compile 'com.github.sealedtx:bitcoin-cash-converter:1.0'
- compile 'com.xuxueli:xxl-job-core:2.4.0'
- //ALI SDK
-// compile 'com.aliyun:aliyun-java-sdk-core:4.0.3'
-// //AWS SDK
-// compile("net.minidev:json-smart:2.2.1")
-// compile("com.amazonaws:aws-java-sdk:1.11.401") {
-// exclude module: "net.minidev"
-// compile group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1'
-// }
- compile 'com.github.TraderGalax:tokencore:1.2.7'
- testCompile "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
-
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+ implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3"
+ implementation "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
+ implementation "org.springframework.boot:spring-boot-starter-cache:$springBootVersion"
+ implementation "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
+ implementation 'com.zaxxer:HikariCP:5.0.1'
+ implementation 'com.mysql:mysql-connector-j:8.2.0'
+ implementation 'org.apache.commons:commons-lang3:3.14.0'
+ compileOnly 'org.projectlombok:lombok:1.18.30'
+ annotationProcessor 'org.projectlombok:lombok:1.18.30'
+ implementation 'commons-beanutils:commons-beanutils:1.9.4'
+ implementation 'org.web3j:core:4.10.3'
+ implementation 'wf.bitcoin:bitcoin-rpc-client:1.2.4'
+
+ implementation "org.springframework.boot:spring-boot-starter-amqp:$springBootVersion"
+ implementation 'com.github.ben-manes.caffeine:caffeine:3.1.8'
+ implementation 'com.github.sealedtx:bitcoin-cash-converter:1.0'
+ implementation 'com.xuxueli:xxl-job-core:2.4.0'
+ implementation 'com.github.GalaxySciTech:tokencore:1.3.0'
+
+ implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.3.0'
+
+ testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
}
-// configurations{
-// compileJava.exclude module: 'spring-boot-starter-tomcat'
-// }
-// task "create-dirs" << {
-// sourceSets*.java.srcDirs*.each{
-// it.mkdirs()
-// }
-// sourceSets*.kotlin.srcDirs*.each{
-// it.mkdirs()
-// }
-// sourceSets*.resources.srcDirs*.each{
-// it.mkdirs()
-// }
-// }
+
}
buildscript {
@@ -113,12 +82,12 @@ buildscript {
ext.springBootVersion = '3.1.3'
repositories {
- maven {url 'https://maven.aliyun.com/repository/public/'}
+ maven { url 'https://maven.aliyun.com/repository/public/' }
mavenLocal()
mavenCentral()
}
dependencies {
- classpath "io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE"
+ classpath "io.spring.gradle:dependency-management-plugin:1.1.4"
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
}
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..43b500c
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,81 @@
+version: '3.8'
+
+services:
+ mysql:
+ image: mysql:8.0
+ environment:
+ MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-devpassword}
+ MYSQL_DATABASE: wallet_db
+ ports:
+ - "3306:3306"
+ volumes:
+ - mysql_data:/var/lib/mysql
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ rabbitmq:
+ image: rabbitmq:3-management-alpine
+ environment:
+ RABBITMQ_DEFAULT_USER: ${RABBITMQ_USERNAME:-guest}
+ RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-guest}
+ ports:
+ - "5672:5672"
+ - "15672:15672"
+ healthcheck:
+ test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ wallet-webapi:
+ build:
+ context: .
+ dockerfile: wallet-webapi/Dockerfile
+ ports:
+ - "10001:10001"
+ environment:
+ DB_URL: jdbc:mysql://mysql:3306/wallet_db?allowMultiQueries=true&useSSL=false&characterEncoding=UTF-8&autoReconnect=true
+ DB_USERNAME: root
+ DB_PASSWORD: ${DB_PASSWORD:-devpassword}
+ depends_on:
+ mysql:
+ condition: service_healthy
+
+ wallet-task:
+ build:
+ context: .
+ dockerfile: wallet-task/Dockerfile
+ ports:
+ - "10033:10033"
+ environment:
+ DB_URL: jdbc:mysql://mysql:3306/wallet_db?allowMultiQueries=true&useSSL=false&characterEncoding=UTF-8&autoReconnect=true
+ DB_USERNAME: root
+ DB_PASSWORD: ${DB_PASSWORD:-devpassword}
+ RABBITMQ_HOST: rabbitmq
+ RABBITMQ_PORT: 5672
+ RABBITMQ_USERNAME: ${RABBITMQ_USERNAME:-guest}
+ RABBITMQ_PASSWORD: ${RABBITMQ_PASSWORD:-guest}
+ depends_on:
+ mysql:
+ condition: service_healthy
+ rabbitmq:
+ condition: service_healthy
+
+ wallet-hsm:
+ build:
+ context: .
+ dockerfile: wallet-hsm/Dockerfile
+ ports:
+ - "10888:10888"
+ environment:
+ KEYSTORE_DIR: /data/keystores
+ KEYSTORE_PASSWORD: ${KEYSTORE_PASSWORD:-}
+ volumes:
+ - keystore_data:/data/keystores
+
+volumes:
+ mysql_data:
+ keystore_data:
diff --git a/gradle.properties b/gradle.properties
index 694b686..2b83233 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,18 +1,14 @@
-# Gradle 编译配置
-#开启gradle并行编译,开启daemon,调整jvm内存大小
+# Gradle build configuration
org.gradle.daemon=true
org.gradle.configureondemand=true
org.gradle.parallel=true
-org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+org.gradle.jvmargs=-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
-#开启gradle缓存
+# Gradle caching
org.gradle.caching=true
-android.enableBuildCache=true
-#开启kotlin的增量和并行编译
+# Kotlin incremental and parallel compilation
kotlin.incremental=true
kotlin.incremental.java=true
-kotlin.incremental.js=true
kotlin.caching.enabled=true
-#开启kotlin并行编译
kotlin.parallel.tasks.in.project=true
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index ecd525e..0cea8ae 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
-#Thu Apr 11 15:34:58 CST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
diff --git a/wallet-common/build.gradle b/wallet-common/build.gradle
index 97084fc..a16cce5 100644
--- a/wallet-common/build.gradle
+++ b/wallet-common/build.gradle
@@ -1,7 +1,6 @@
-bootRepackage.enabled=false
-
+bootJar.enabled = false
+jar.enabled = true
dependencies {
- compile project(":wallet-entity")
+ implementation project(":wallet-entity")
}
-
diff --git a/wallet-common/src/main/kotlin/com/wallet/biz/cache/impl/CacheServiceImpl.kt b/wallet-common/src/main/kotlin/com/wallet/biz/cache/impl/CacheServiceImpl.kt
index d6a2ae7..ae3a493 100644
--- a/wallet-common/src/main/kotlin/com/wallet/biz/cache/impl/CacheServiceImpl.kt
+++ b/wallet-common/src/main/kotlin/com/wallet/biz/cache/impl/CacheServiceImpl.kt
@@ -15,7 +15,7 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cache.annotation.Cacheable
import org.springframework.stereotype.Service
import org.web3j.protocol.core.DefaultBlockParameterName
-import javax.annotation.PostConstruct
+import jakarta.annotation.PostConstruct
import kotlin.collections.HashMap
/**
diff --git a/wallet-common/src/main/kotlin/com/wallet/biz/config/AsyncConfig.kt b/wallet-common/src/main/kotlin/com/wallet/biz/config/AsyncConfig.kt
index 782c2eb..5ae9c1c 100644
--- a/wallet-common/src/main/kotlin/com/wallet/biz/config/AsyncConfig.kt
+++ b/wallet-common/src/main/kotlin/com/wallet/biz/config/AsyncConfig.kt
@@ -1,11 +1,8 @@
package com.wallet.biz.config
+import org.springframework.context.annotation.Configuration
import org.springframework.scheduling.annotation.EnableAsync
-/**
- * Created by pie on 2020/2/7 16: 40.
- */
+@Configuration
@EnableAsync
-class AsyncConfig {
-
-}
\ No newline at end of file
+open class AsyncConfig
diff --git a/wallet-common/src/main/kotlin/com/wallet/biz/config/CacheConfig.kt b/wallet-common/src/main/kotlin/com/wallet/biz/config/CacheConfig.kt
index 4b7af55..88a5c88 100644
--- a/wallet-common/src/main/kotlin/com/wallet/biz/config/CacheConfig.kt
+++ b/wallet-common/src/main/kotlin/com/wallet/biz/config/CacheConfig.kt
@@ -1,19 +1,13 @@
package com.wallet.biz.config
-import com.wallet.biz.cache.CacheService
import com.github.benmanes.caffeine.cache.Caffeine
-import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cache.CacheManager
import org.springframework.cache.annotation.EnableCaching
import org.springframework.cache.caffeine.CaffeineCacheManager
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import java.util.concurrent.TimeUnit
-import javax.annotation.PostConstruct
-/**
- * Created by pie on 2020/7/24 02: 59.
- */
@Configuration
@EnableCaching
open class CacheConfig {
@@ -22,11 +16,11 @@ open class CacheConfig {
open fun cacheManager(): CacheManager {
val caffeine = Caffeine.newBuilder()
.initialCapacity(100)
- .maximumSize(1000)
- .expireAfterWrite(3, TimeUnit.SECONDS)
+ .maximumSize(5000)
+ .expireAfterWrite(30, TimeUnit.SECONDS)
+ .recordStats()
val cacheManager = CaffeineCacheManager()
cacheManager.setCaffeine(caffeine)
return cacheManager
}
-
}
diff --git a/wallet-common/src/main/kotlin/com/wallet/biz/config/DbOp.kt b/wallet-common/src/main/kotlin/com/wallet/biz/config/DbOp.kt
index ee6ff62..73a5214 100644
--- a/wallet-common/src/main/kotlin/com/wallet/biz/config/DbOp.kt
+++ b/wallet-common/src/main/kotlin/com/wallet/biz/config/DbOp.kt
@@ -4,19 +4,17 @@ import org.springframework.beans.factory.annotation.Autowired
import org.springframework.jdbc.core.JdbcTemplate
import org.springframework.stereotype.Component
-
-/**
- * Created by pie on 2020/11/1 16: 13.
- */
@Component
class DbOp {
- fun select(sql: String): List