# Phase 1B: 가스비 USD 환산 + TRON 비용 상세 기록 — 수정 보고서

**작업일**: 2026-03-16
**기준 문서**: `NODEJS_PHASE1B_GAS_COST_ENHANCEMENT_GUIDE.md`
**DDL 버전**: v1.5
**빌드 결과**: `pnpm run build` — 5개 패키지 모두 SUCCESS

---

## 수정 결과 요약

| 항목 | 상태 | 변경 파일 |
|------|------|----------|
| B-0. check-wallets.ts 잔존 버그 | ✅ | 1 |
| B-1. 타입 정의 (GasCostRecord/Insert) | ✅ | 1 |
| B-2. GasCostRecordRepo (insert/updateFee/updateTronFee) | ✅ | 1 |
| B-3. NativePriceService 생성 + export | ✅ | 3 (신규 2 + 수정 1) |
| B-4. CollectionPoller USD 환산 | ✅ | 1 |
| B-5. WithdrawalPoller USD 환산 | ✅ | 1 |
| B-6. ApprovalProcessor USD 환산 | ✅ | 1 |

---

## B-0. 잔존 버그 수정 ✅

**파일**: `blockchain-api/scripts/check-wallets.ts:23`

`key_version` → `encryption_key_version` (Phase 1 A-5 누락분)

---

## B-1. 타입 정의 수정 ✅

**파일**: `common/src/types/tx.ts`

`GasCostRecord`에 3개 필드 추가:
- `native_price_usd: string | null` — 환산 시점 USD 시세
- `bandwidth_fee_trx: string | null` — TRON bandwidth 비용
- `energy_fee_trx: string | null` — TRON 에너지 렌탈 비용

`GasCostRecordInsert`에 동일 3개 optional 필드 추가.

---

## B-2. GasCostRecordRepo 수정 ✅

**파일**: `common/src/db/repositories/GasCostRecordRepo.ts`

| 메서드 | 변경 내용 |
|--------|----------|
| `insert()` | 11개 컬럼 (기존 8 + native_price_usd, bandwidth_fee_trx, energy_fee_trx) |
| `updateFee()` | 파라미터 `nativePriceUsd` 추가, COALESCE로 기존 값 보존 |
| `updateTronFee()` | **신규** — TRON bandwidth 비용 + fee_native 합산 + USD 환산 |

---

## B-3. NativePriceService 생성 ✅

**신규 파일 2개**:

| 파일 | 내용 |
|------|------|
| `common/src/price/NativePriceService.ts` | `getNativePriceUsd(networkId)`, `calcFeeUsd(feeNative, priceUsd)` |
| `common/src/price/index.ts` | re-export |

**수정**: `common/src/index.ts` — `getNativePriceUsd`, `calcFeeUsd` export 추가

### 환산 로직

```
currencies (currency_type='NATIVE') + currency_prices JOIN
→ price_usd 반환 (null이면 시세 미등록)
→ calcFeeUsd = parseFloat(feeNative) * parseFloat(priceUsd) → toFixed(8)
```

---

## B-4. CollectionPoller USD 환산 ✅

**파일**: `relayer-api/src/services/CollectionPoller.ts`

| 비용 기록 | 변경 |
|----------|------|
| COLLECTION | `native_price_usd` 스냅샷 저장 (fee_native는 webhook에서 업데이트) |
| ENERGY_RENTAL | `fee_native` + `native_price_usd` + `fee_usd` 계산 + `energy_fee_trx` 기록 |

---

## B-5. WithdrawalPoller USD 환산 ✅

**파일**: `relayer-api/src/services/WithdrawalPoller.ts`

CollectionPoller와 동일 패턴:
- WITHDRAWAL: `native_price_usd` 스냅샷
- ENERGY_RENTAL: `fee_native` + USD 환산 + `energy_fee_trx`

---

## B-6. ApprovalProcessor USD 환산 ✅

**파일**: `wallet-activator/src/services/ApprovalProcessor.ts`

| 비용 기록 | 변경 |
|----------|------|
| `recordActualFee()` | receipt에서 feeNative 계산 후 `getNativePriceUsd()` → `calcFeeUsd()` → `updateFee()` |
| GAS_SUPPORT (EVM) | INSERT 시점에 `native_price_usd` + `fee_usd` 계산 |
| ENERGY_RENTAL (TRON) | `energy_fee_trx` + USD 환산 |
| GAS_SUPPORT (TRON 활성화) | `native_price_usd` + `fee_usd` 계산 |
| APPROVE | INSERT 시점에 `native_price_usd` 스냅샷 (fee_native는 `recordActualFee()`에서) |

---

## 변경 파일 목록 (9개)

| 패키지 | 파일 | 유형 |
|--------|------|------|
| blockchain-api | `scripts/check-wallets.ts` | B-0 버그 수정 |
| common | `src/types/tx.ts` | B-1 타입 |
| common | `src/db/repositories/GasCostRecordRepo.ts` | B-2 Repo |
| common | `src/price/NativePriceService.ts` | B-3 **신규** |
| common | `src/price/index.ts` | B-3 **신규** |
| common | `src/index.ts` | B-3 export |
| relayer-api | `src/services/CollectionPoller.ts` | B-4 |
| relayer-api | `src/services/WithdrawalPoller.ts` | B-5 |
| wallet-activator | `src/services/ApprovalProcessor.ts` | B-6 |

---

## 선행 작업 (DB Migration)

```sql
-- 1. currencies: 네이티브 토큰 추가
INSERT INTO currencies (symbol, network_id, name, contract_address, currency_type, decimals, is_stablecoin) VALUES
('BNB', 2, 'BNB (BSC)',     NULL, 'NATIVE', 18, FALSE),
('POL', 3, 'POL (Polygon)', NULL, 'NATIVE', 18, FALSE),
('TRX', 4, 'TRX (TRON)',   NULL, 'NATIVE', 6,  FALSE);

-- 2. gas_cost_records: 컬럼 추가
ALTER TABLE gas_cost_records
  ADD COLUMN native_price_usd DECIMAL(20,8) AFTER fee_native,
  ADD COLUMN bandwidth_fee_trx DECIMAL(36,18) AFTER fee_usd,
  ADD COLUMN energy_fee_trx DECIMAL(36,18) AFTER bandwidth_fee_trx;
```

## 주의사항

1. `currency_prices`에 네이티브 토큰 시세가 없으면 `getNativePriceUsd()` → null → `fee_usd`/`native_price_usd` NULL 저장
2. `calcFeeUsd`는 `parseFloat` 기반 — 가스비 소액 범위에서는 정밀도 충분
3. TRON `fee_native = bandwidth_fee_trx + energy_fee_trx` 합산 구조
