# Node.js ↔ Spring Boot (Java) ↔ DDL v1.5 Cross-Check Report

> **작성일**: 2026-03-16
> **기준 DDL**: `v2-docs/CRYPTOMENTS_V2_DDL.sql` (v1.5, 40 tables, 2072 lines)
> **Node.js**: `node-service/packages/common/src/types/` + `db/repositories/`
> **Java**: `common/src/main/java/com/cryptoments/common/` (entity, enums, repository)

---

## 1. Enum/Status 매칭 테이블

### 1-1. ApproveStatus (wallet_approvals.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| PENDING | ✅ | ✅ | ✅ | |
| GAS_SUPPORTING | ✅ | ✅ | ✅ | |
| GAS_READY | ✅ | ✅ | ✅ | |
| APPROVING | ✅ | ✅ | ✅ | |
| APPROVED | ✅ | ✅ | ✅ | |
| FAILED | ✅ | ✅ | ✅ | |
| DEFERRED | ✅ | ✅ | ✅ | |
| REVOKED | ❌ | ❌ | ✅ | **Java only** — 관리자 수동 철회용. DDL 미정의 |

**판정**: ⚠️ LOW — `REVOKED`는 Java 비즈니스 확장 값. Node.js는 사용하지 않으므로 무방.

### 1-2. CollectionStatus (collection_queue.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| QUEUED | ✅ | ✅ | ✅ | |
| COLLECTING | ✅ | ✅ | ✅ | |
| BROADCASTING | ✅ | ✅ | ✅ | |
| CONFIRMED | ✅ | ✅ | ✅ | |
| FAILED | ✅ | ✅ | ✅ | |
| DEFERRED | ✅ | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

### 1-3. WithdrawalStatus (withdrawals.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| REQUESTED | ✅ | ✅ | ✅ | |
| PENDING_APPROVAL | ✅ | ✅ | ✅ | |
| APPROVED | ✅ | ✅ | ✅ | |
| REJECTED | ✅ | ✅ | ✅ | |
| BALANCE_PENDING | ❌ | ❌ | ✅ | **Java only** — DDL 미정의 |
| PROCESSING | ✅ | ✅ | ✅ | |
| BROADCASTING | ✅ | ✅ | ✅ | |
| CONFIRMED | ✅ | ✅ | ✅ | |
| FAILED | ✅ | ✅ | ✅ | |
| CANCELLED | ✅ | ❌ | ✅ | **Node.js `CANCELED` (1 L)** |
| CANCELED | ❌ | ✅ | ❌ | 스펠링 불일치 |

**판정**: 🔴 **HIGH**
1. **`CANCELED` vs `CANCELLED`** — Node.js가 single-L 사용. DDL/Java는 double-L. DB에 직접 INSERT/UPDATE하므로 불일치 시 WHERE 조건 미매칭 위험.
2. **`BALANCE_PENDING`** — Java에만 존재. DDL에 없으므로 Java에서 제거하거나 DDL에 추가 필요.

### 1-4. WithdrawalType (withdrawals.withdrawal_type)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| USER_PAYOUT | ✅ | ✅ | ✅ | |
| REFUND | ✅ | ✅ | ✅ | |
| PARTNER_WITHDRAW | ✅ | ✅ | ✅ | |
| SETTLEMENT_WITHDRAW | ✅ | ❌ | ✅ | Node.js 미정의 |
| INTERNAL | ✅ | ❌ | ✅ | Node.js 미정의 |

**판정**: ⚠️ LOW — Node.js는 출금 타입과 무관하게 동일 TX 실행. 타입 읽기만 하므로 기능상 문제 없음. 단, TypeScript 타입 완전성을 위해 추가 권장.

### 1-5. RegistrationStatus (relayer_wallets.registration_status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| PENDING | ✅ | ✅ | ✅ | |
| REGISTERING | ✅ | ✅ | ❌ | **Java 누락** |
| REGISTERED | ✅ | ✅ | ✅ | |
| DEREGISTERING | ✅ | ✅ | ❌ | **Java 누락** |
| REVOKED | ✅ | ✅ | ✅ | |

**판정**: 🔴 **HIGH** — Java `RegistrationStatus` enum에 `REGISTERING`, `DEREGISTERING` 누락. Node.js가 이 값을 DB에 쓰면 Java에서 역직렬화 실패.

### 1-6. WalletType (wallet_addresses.wallet_type)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| HOT | ✅ | ✅ | ✅ | |
| MASTER | ✅ | ✅ | ✅ | |
| GAS | ✅ | ✅ | ✅ | |
| ADMIN | ✅ | ✅ | ❌ | **Java 누락** |
| SETTLEMENT | ✅ | ✅ | ✅ | |
| POOL | ✅ | ✅ | ✅ | |

**판정**: 🔴 **HIGH** — Java `WalletType` enum에 `ADMIN` 누락. Node.js `blockchain-api`가 ADMIN 지갑을 생성하고 `wallet_type = 'ADMIN'`으로 INSERT하면 Java에서 역직렬화 실패.

### 1-7. WalletAddressStatus (wallet_addresses.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| ACTIVE | ✅ | ✅ | ✅ | |
| INACTIVE | ✅ | ✅ | ✅ | |
| RESERVED | ❌ | ❌ | ✅ | **Java only** — DDL 미정의 |

**판정**: ⚠️ LOW — `RESERVED`는 향후 풀 주소 예약용으로 추가된 것으로 보임. DDL에 없으므로 실제 사용 시 DDL 동기화 필요.

### 1-8. RelayerWalletStatus (relayer_wallets.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| ACTIVE | ✅ | ✅ | ✅ | |
| PAUSED | ✅ | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

### 1-9. RelayerContractStatus (relayer_contracts.status)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| ACTIVE | ✅ | ✅ | ✅ (String) | |
| PAUSED | ✅ | ✅ | ✅ (String) | |
| DEPRECATED | ✅ | ✅ | ✅ (String) | |

**판정**: ✅ 일치 — Java는 enum 없이 String 타입 사용.

### 1-10. GasCostTxType (gas_cost_records.tx_type)

| Value | DDL | Node.js | Java | 비고 |
|-------|-----|---------|------|------|
| COLLECTION | ✅ | ✅ | ✅ | |
| WITHDRAWAL | ✅ | ✅ | ✅ | |
| APPROVE | ✅ | ✅ | ✅ | |
| GAS_SUPPORT | ✅ | ✅ | ✅ | |
| ENERGY_RENTAL | ✅ | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

---

## 2. Entity/Interface 컬럼 매칭

### 2-1. collection_queue

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| collection_code | ✅ | ✅ | |
| wallet_address_id | ✅ | ✅ | |
| partner_id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| currency_id | ✅ | ✅ | |
| amount | ✅ | ✅ | |
| collection_mode | ✅ | ✅ | |
| scheduled_at | ✅ | ✅ | |
| status | ✅ | ✅ | |
| error_message | ✅ | ✅ | v1.3 |
| retry_count | ✅ | ✅ | v1.3 |
| tx_hash | ✅ | ✅ | v1.3 renamed |
| relayer_wallet_id | ✅ | ✅ | v1.3 |
| created_at | ✅ | ✅ | |
| updated_at | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

### 2-2. wallet_approvals

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| wallet_address_id | ✅ | ✅ | |
| currency_id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| spender_address | ✅ | ✅ | |
| approved_amount | ✅ | ✅ | |
| approve_tx_hash | ✅ | ✅ | |
| gas_tx_hash | ✅ | ✅ | v1.3 |
| status | ✅ | ✅ | v1.3 renamed |
| error_message | ✅ | ✅ | v1.3 |
| retry_count | ✅ | ✅ | v1.3 |
| approved_at | ✅ | ✅ | |
| created_at | ✅ | ✅ | |
| updated_at | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

### 2-3. relayer_wallets

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| wallet_address_id | ✅ | ✅ | |
| relayer_role | ✅ | ✅ | v1.3 |
| contract_address | ✅ | ✅ | |
| registration_tx_hash | ✅ | ✅ | |
| registration_status | ✅ | ✅ | |
| status | ✅ | ✅ | |
| priority | ✅ | ✅ | v1.3 |
| current_pending_tx_count | ✅ | ✅ | v1.3 |
| max_pending_tx_count | ✅ | ✅ | v1.3 |
| created_at | ❌ | ✅ | Node.js type 미정의 (SELECT * 사용) |
| updated_at | ❌ | ✅ | Node.js type 미정의 (SELECT * 사용) |

**판정**: ✅ 기능상 일치 (Node.js는 timestamp 미사용)

### 2-4. withdrawals

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| withdrawal_code | ✅ | ✅ | |
| partner_id | ✅ | ✅ | |
| partner_user_id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| currency_id | ✅ | ✅ | |
| withdrawal_type | ✅ | ✅ | |
| request_source | ✅ | ✅ | |
| requested_by | ✅ | ✅ | |
| to_address | ✅ | ✅ | |
| amount | ✅ | ✅ | |
| partner_reference | ✅ | ✅ | |
| partner_metadata | ❌ | ✅ | Node.js 미정의 |
| ref_code | ✅ | ✅ | |
| tx_hash | ✅ | ✅ | |
| relayer_wallet_id | ✅ | ✅ | v1.3 |
| block_number | ✅ | ✅ | |
| status | ✅ | ✅ | |
| error_message | ✅ | ✅ | v1.3 |
| price_krw | ❌ | ✅ | Node.js 미정의 |
| price_usd | ❌ | ✅ | Node.js 미정의 |
| confirmed_at | ✅ | ✅ | |
| created_at | ✅ | ✅ | |
| updated_at | ✅ | ✅ | |

**판정**: ✅ 기능상 문제 없음 — Node.js는 가격/메타데이터 컬럼 불필요 (Spring Boot 관리)

### 2-5. wallet_index_manager

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| hd_wallet_id | ✅ | ❌ | **Java 누락** |
| wallet_type | ✅ | ✅ | |
| partner_id | ✅ | ✅ | |
| current_index | ✅ | ✅ | |
| created_at | ✅ | ✅ | |
| updated_at | ✅ | ✅ | |

**판정**: 🔴 **HIGH** — Java `WalletIndexManager` entity에 `hdWalletId` 필드 누락. DDL에 `hd_wallet_id BIGINT NOT NULL`로 정의되어 있으며, UNIQUE KEY에도 포함됨.

### 2-6. blockchain_networks

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| chain_symbol | ✅ | ✅ | v1.3 renamed from `code` |
| name | ✅ | ✅ | |
| chain_id | ✅ | ✅ | |
| network_type | ✅ | ✅ | v1.3 |
| rpc_url | ✅ | ✅ | v1.3 |
| rpc_url_fallback | ✅ | ✅ | v1.3 |
| explorer_url | ✅ | ✅ | |
| native_currency | ✅ | ✅ | |
| block_confirmation_count | ✅ | ✅ | v1.3 renamed |
| is_active | ✅ | ✅ | |

**판정**: ✅ 주요 컬럼 일치 (Node.js는 필요 컬럼만 정의)

### 2-7. gas_cost_records

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| partner_id | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| tx_type | ✅ | ✅ | |
| tx_hash | ✅ | ✅ | |
| reference_type | ✅ | ✅ | |
| reference_id | ✅ | ✅ | |
| fee_native | ✅ | ✅ | |
| native_price_usd | ✅ | ✅ | v1.4 |
| fee_usd | ✅ | ✅ | |
| bandwidth_fee_trx | ✅ | ✅ | v1.4 |
| energy_fee_trx | ✅ | ✅ | v1.4 |
| billing_status | ✅ | ✅ | |
| invoice_id | ✅ | ✅ | |
| created_at | ✅ | ✅ | |
| updated_at | ✅ | ✅ | |

**판정**: ✅ 완벽 일치

### 2-8. currencies

| DDL Column | Node.js | Java | 비고 |
|------------|---------|------|------|
| id | ✅ | ✅ | |
| symbol | ✅ | ✅ | |
| network_id | ✅ | ✅ | |
| name | ✅ | ✅ | |
| contract_address | ✅ | ✅ | v1.4 |
| currency_type | ✅ | ✅ | |
| decimals | ✅ | ✅ | |
| is_stablecoin | ✅ | ✅ | |
| is_active | ✅ | ✅ | |

**판정**: ✅ 일치

---

## 3. SQL 쿼리 컬럼명 검증

Node.js Repository SQL에서 사용하는 컬럼명이 DDL v1.5와 일치하는지 확인.

| Repo | SQL 컬럼 참조 | DDL 매칭 | 비고 |
|------|--------------|---------|------|
| DepositRepo | `bn.chain_symbol AS network` | ✅ | v1.3 renamed |
| DepositRepo | `c.symbol AS currency` | ✅ | |
| WithdrawalRepo | `c.symbol AS currency` | ✅ | |
| WalletBalanceRepo | `bn.name AS network_name` | ✅ | |
| WalletBalanceRepo | `c.symbol AS currency_symbol` | ✅ | |
| CollectionQueueRepo | `tx_hash` | ✅ | v1.3 renamed |
| WalletApprovalRepo | `status` | ✅ | v1.3 renamed |
| NonceTrackerRepo | `nonce_tracker` (table) | ✅ | |
| RelayerWalletRepo | `registration_status` | ✅ | |
| WalletKeyRepo | `encryption_key_version` | ✅ | v1.2 renamed |
| WalletIndexManagerRepo | `current_index` | ✅ | v1.2 renamed |

**판정**: ✅ 모든 SQL 컬럼명 DDL v1.5와 일치

---

## 4. DB Polling Contract 검증

### 4-1. wallet_approvals (wallet-activator)

| 단계 | Spring Boot | Node.js | 일치 |
|------|-------------|---------|------|
| INSERT | `status = PENDING` | — | ✅ |
| 폴링 | — | `WHERE status = 'PENDING'` | ✅ |
| 가스 전송 시작 | — | `SET status = 'GAS_SUPPORTING'` | ✅ |
| 가스 전송 완료 | — | `SET status = 'GAS_READY'` | ✅ |
| 재폴링 | — | `WHERE status = 'GAS_READY'` | ✅ |
| approve 시작 | — | `SET status = 'APPROVING'` | ✅ |
| approve 완료 | — | `SET status = 'APPROVED'` | ✅ |
| 실패 | — | `SET status = 'FAILED'` | ✅ |
| 읽기 | `findByStatus(APPROVED)` | — | ✅ |

**판정**: ✅ 폴링 계약 일치

### 4-2. collection_queue (relayer-api)

| 단계 | Spring Boot | Node.js | 일치 |
|------|-------------|---------|------|
| INSERT | `status = QUEUED` | — | ✅ |
| 폴링 | — | `WHERE status = 'QUEUED'` | ✅ |
| TX 시작 | — | `SET status = 'COLLECTING'` | ✅ |
| TX broadcast | — | `SET status = 'BROADCASTING'` | ✅ |
| TX 확인 | — | `SET status = 'CONFIRMED'` | ✅ |
| 실패 | — | `SET status = 'FAILED'` | ✅ |
| 읽기 | `findByStatus(CONFIRMED)` | — | ✅ |

**판정**: ✅ 폴링 계약 일치

### 4-3. withdrawals (relayer-api)

| 단계 | Spring Boot | Node.js | 일치 |
|------|-------------|---------|------|
| INSERT | `status = APPROVED` (승인 후) | — | ✅ |
| 폴링 | — | `WHERE status = 'APPROVED'` | ✅ |
| TX 시작 | — | `SET status = 'PROCESSING'` | ✅ |
| TX broadcast | — | `SET status = 'BROADCASTING'` | ✅ |
| TX 확인 | — | `SET status = 'CONFIRMED'` | ✅ |
| 실패 | — | `SET status = 'FAILED'` | ✅ |
| 읽기 | `findByStatus(CONFIRMED)` | — | ✅ |

**판정**: ✅ 폴링 계약 일치

---

## 5. 수정 필요 사항 요약

### 🔴 HIGH (런타임 오류 가능)

| # | 항목 | 위치 | 수정 내용 |
|---|------|------|----------|
| H1 | `RegistrationStatus` enum 누락 | Java `common/enums/RegistrationStatus.java` | `REGISTERING`, `DEREGISTERING` 추가 |
| H2 | `WalletType` enum 누락 | Java `common/enums/WalletType.java` | `ADMIN` 추가 |
| H3 | `WalletIndexManager.hdWalletId` 누락 | Java `common/entity/WalletIndexManager.java` | `private Long hdWalletId;` 추가 |
| H4 | `CANCELED` vs `CANCELLED` 스펠링 | Node.js `types/tx.ts` | `CANCELED` → `CANCELLED` |

### ⚠️ MEDIUM (기능 정확성)

| # | 항목 | 위치 | 수정 내용 |
|---|------|------|----------|
| M1 | `WithdrawalStatus.BALANCE_PENDING` DDL 미정의 | Java `common/enums/WithdrawalStatus.java` | DDL에 추가하거나 Java에서 제거 |
| M2 | `WithdrawalType` 불완전 | Node.js `types/tx.ts` | `SETTLEMENT_WITHDRAW`, `INTERNAL` 추가 |

### ℹ️ LOW (권장)

| # | 항목 | 위치 | 수정 내용 |
|---|------|------|----------|
| L1 | `WalletAddressStatus.RESERVED` DDL 미정의 | Java `common/enums/WalletAddressStatus.java` | 사용 시 DDL 동기화 |
| L2 | `ApproveStatus.REVOKED` DDL 미정의 | Java `common/enums/ApproveStatus.java` | 사용 시 DDL에 추가 |

---

## 6. 수정 체크리스트

### Java (Spring Boot) 수정

- [ ] **H1**: `RegistrationStatus.java`에 `REGISTERING`, `DEREGISTERING` 추가
- [ ] **H2**: `WalletType.java`에 `ADMIN` 추가
- [ ] **H3**: `WalletIndexManager.java`에 `private Long hdWalletId;` 필드 추가
- [ ] **M1**: `WithdrawalStatus.BALANCE_PENDING` — 비즈니스에서 사용하면 DDL에 추가, 아니면 제거

### Node.js 수정

- [ ] **H4**: `types/tx.ts` — `WithdrawalStatus`의 `CANCELED` → `CANCELLED` 변경
- [ ] **M2**: `types/tx.ts` — `WithdrawalType`에 `SETTLEMENT_WITHDRAW`, `INTERNAL` 추가

---

## 7. Telegram 테이블명 검증

| DDL Table | Node.js Repo | Java Entity | 비고 |
|-----------|-------------|-------------|------|
| partner_telegram_configs | `TelegramConfigRepo` → `partner_telegram_configs` | `PartnerTelegramConfig` → `@XEntity("partner_telegram_configs")` | ✅ |
| partner_telegram_subscriptions | `TelegramSubscriptionRepo` → `partner_telegram_subscriptions` | `PartnerTelegramSubscription` → `@XEntity("partner_telegram_subscriptions")` | ✅ |

**판정**: ✅ 테이블명 일치

---

## 8. 결론

- **전체 40개 테이블 중 Node.js 관여 17개** — 대부분 DDL v1.5 정합
- **HIGH 4건**: Java enum 누락 3건 + Node.js 스펠링 1건 → 즉시 수정 필요
- **MEDIUM 2건**: DDL↔Java 상태값 정합 + Node.js 타입 완전성
- **DB Polling Contract**: 3개 폴링 흐름 모두 정확히 일치
- **SQL 컬럼명**: Node.js/Java 모두 v1.5 DDL과 일치 (v1.3 rename 반영 완료)
