Tools/crypto-wallet-core — 다중 체인 지갑 코어 서비스
account_balance_walletBlockchain2026-04-25· 4분 읽기

crypto-wallet-core — 다중 체인 지갑 코어 서비스

BTC·ETH·SOL·BSC를 통합 인터페이스로 다루는 NestJS 모노레포 — 노드 풀 자동 페일오버·통일된 v1 API·TDD 기반 설계

list목차(7)
💼

crypto-wallet-core

Bitcoin · Ethereum · Solana · BNB Chain을 한 인터페이스에서 다루는 통합 지갑 코어. 각 체인은 독립 패키지로 운용되고, 동적 노드 풀이 헬스 체크 결과에 따라 엔드포인트를 자동 전환합니다.

왜 만들었나

지갑 시스템이 여러 체인을 다룰수록 라이브러리·노드·서명 흐름이 제각각이라 운영 부담이 폭증합니다. 각 체인을 독립 패키지로 두되 공통 인터페이스(getBalance, broadcastTransaction 등)를 강제해 호출자 코드를 단일화한 것이 출발점입니다.

핵심 설계

  • 모노레포 + 패키지 분리: packages/{core,bitcoin,ethereum,solana,bnb} + apps/api. 각 패키지는 독립 빌드·테스트.
  • 공통 인터페이스: BlockchainNetwork 타입으로 잔액·트랜잭션 조회·브로드캐스트 추상화.
  • 동적 노드 관리: NodeManager가 노드 풀을 들고 주기적 헬스 체크 + 응답 지연 측정 + 장애 노드 자동 제외. 런타임에 노드 추가/제거 가능.
  • TDD: Red → Green → Refactor 사이클. 단위/통합/E2E 테스트 디렉터리 분리, 커버리지 80%+ 목표.

지원 네트워크와 라이브러리

네트워크라이브러리비고
Bitcoinbitcoinjs-lib · bitcoin-coreCore RPC 클라이언트
Ethereumethers.jsEVM 표준
Solana@solana/web3.js · spl-tokenSPL 토큰 포함
BNB Chainethers.jsEVM 호환

API 규약 (4개 체인 통일)

작업메서드경로
지갑 생성GET/v1/<chain>/wallet/create
주소 검증GET/v1/<chain>/address/validate?address=...
잔액 조회GET/v1/<chain>/balance/:address
비서명 TX 생성POST/v1/<chain>/transaction/create-unsigned
TX 서명POST/v1/<chain>/transaction/sign
TX 브로드캐스트POST/v1/<chain>/transaction/broadcast
개인키 즉시 전송POST/v1/<chain>/send/private-key
최신 블록GET/v1/<chain>/block/latest

경로·필드를 4개 체인에서 동일하게 맞춰, 신규 체인 추가 시 클라이언트 수정 없이 어댑터만 구현하면 됩니다. 민감 엔드포인트(send/private-key, transaction/sign)는 별도로 5 req/60s 추가 throttle.

운영 디테일

  • 기본 RPC: PublicNode 무료 엔드포인트(bitcoin-rpc.publicnode.com, ethereum-rpc.publicnode.com 등)를 디폴트로. 환경변수 <CHAIN>_NODES로 자체 노드·Infura·Alchemy·Helius 등 추가.
  • API 키: API_KEY_REQUIRED=true면 모든 엔드포인트가 x-api-key 헤더 필수. Swagger UI(/api)에서 Authorize로 설정.
  • Throttler: 글로벌 30 req/60s, 민감 엔드포인트는 별도 5 req/60s.

사용 예 (TypeScript)

import { EthereumService } from '@crypto-wallet-core/ethereum';

const service = new EthereumService();
service.nodeManager.addNode('https://mainnet.infura.io/v3/YOUR_KEY');

// 헬스 체크
const health = await service.nodeManager.checkAllNodes();
// [{ endpoint, healthy: true, latency: 95 }, ...]

// 잔액
const balance = await service.getBalance('0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb');

// 브로드캐스트
const txHash = await service.broadcastTransaction('0x...');

회고

네트워크별 특수성(Bitcoin UTXO vs EVM account 모델 vs Solana slot 등)을 공통 인터페이스 뒤에 숨기면 코드 단순성은 좋지만, 정작 중요한 디테일(가스 추정·재서명 로직·재시도 정책)이 어댑터 안에 갇혀 디버깅이 어려워지는 트레이드오프가 있습니다. 두 번째로 짠다면 어댑터별 옵저버블·로그 컨벤션을 인터페이스 일부로 강제했을 것 같습니다.

More in Blockchain