# BC-Game Up/Down API 문서

## 기본 정보

**Base URL**: `https://gr.ezywallets.com/api`
**WebSocket URL**: `wss://gr.ezywallets.com/ws`

모든 API는 JSON 형식으로 응답합니다.

---

## 1. 사용자 API

### 사용자 정보 조회

**Endpoint**: `GET /api/user.php`

**Parameters**:
- `session_id` (required): 사용자 세션 ID

**Request**:
```javascript
fetch('/api/user.php?session_id=test123')
  .then(r => r.json())
  .then(console.log);
```

**Response**:
```json
{
  "success": true,
  "user": {
    "session_id": "test123",
    "balance": 1000.00,
    "total_won": 0,
    "total_lost": 0,
    "total_bets": 0,
    "is_guest": true
  },
  "statistics": {
    "total_bets": 0,
    "total_wagered": 0,
    "total_won": 0,
    "total_lost": 0,
    "win_count": 0,
    "lose_count": 0,
    "win_rate": 0,
    "net_profit": 0
  }
}
```

---

## 2. 게임 상태 API

### 현재 게임 상태 조회

**Endpoint**: `GET /api/game.php`

**Request**:
```javascript
fetch('/api/game.php')
  .then(r => r.json())
  .then(console.log);
```

**Response**:
```json
{
  "success": true,
  "round_id": 1,
  "round_number": 1,
  "status": "BETTING",
  "countdown": 25,
  "start_timestamp": 1736883600000,
  "start_price": 98765.4300,
  "end_price": null,
  "result": "PENDING",
  "total_up_amount": 100.00,
  "total_down_amount": 50.00,
  "total_up_players": 5,
  "total_down_players": 3,
  "total_bets": 8,
  "timestamp": 1736883625000,
  "config": {
    "duration": 60,
    "bettingTime": 45,
    "calculatingTime": 30,
    "distributingTime": 5,
    "publishingTime": 3
  }
}
```

**Status 종류**:
- `BETTING`: 베팅 가능 (0-30초)
- `CALCULATING`: 베팅 마감 (30-55초)
- `DISTRIBUTING`: 결과 계산 중 (55-57초)
- `PUBLISHING`: 결과 공개 (57-60초)
- `WAITING`: 대기 중

---

## 3. 베팅 API

### 베팅하기

**Endpoint**: `POST /api/bet.php`

**Headers**:
```
Content-Type: application/json
```

**Body**:
```json
{
  "direction": "UP",
  "amount": 10,
  "session_id": "test123"
}
```

**Parameters**:
- `direction` (required): "UP" 또는 "DOWN"
- `amount` (required): 베팅 금액 (1-10000)
- `session_id` (required): 사용자 세션 ID
- `user_id` (optional): 등록 사용자 ID

**Request**:
```javascript
fetch('/api/bet.php', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    direction: 'UP',
    amount: 10,
    session_id: 'test123'
  })
}).then(r => r.json()).then(console.log);
```

**Success Response** (201):
```json
{
  "success": true,
  "bet_id": 123,
  "round_id": 1,
  "direction": "UP",
  "amount": 10,
  "timestamp": 1736883625,
  "balance": 990.00
}
```

**Error Response** (400/403):
```json
{
  "success": false,
  "error": "Insufficient balance"
}
```

**가능한 에러**:
- `"Insufficient balance"`: 잔액 부족
- `"Round is not accepting bets"`: 베팅 시간 종료
- `"Invalid bet direction"`: 잘못된 direction
- `"Bet amount is below minimum (1)"`: 최소 금액 미달
- `"Bet amount exceeds maximum (10000)"`: 최대 금액 초과

---

## 4. 라운드 정보 API

### 특정 라운드 조회

**Endpoint**: `GET /api/round.php`

**Parameters**:
- `round_id`: 특정 라운드 ID
- `current=1`: 현재 라운드

**Request**:
```javascript
// 현재 라운드
fetch('/api/round.php?current=1')
  .then(r => r.json())
  .then(console.log);

// 특정 라운드
fetch('/api/round.php?round_id=123')
  .then(r => r.json())
  .then(console.log);
```

**Response**:
```json
{
  "success": true,
  "round": {
    "id": 1,
    "round_number": 1,
    "status": "BETTING",
    "start_timestamp": 1736883600000,
    "end_timestamp": null,
    "start_price": 98765.4300,
    "end_price": null,
    "result": "PENDING",
    "total_up_amount": 100.00,
    "total_down_amount": 50.00,
    "total_up_players": 5,
    "total_down_players": 3,
    "created_at": "2026-01-15 01:00:00"
  },
  "statistics": {
    "total_bets": 8,
    "up_bets": 5,
    "down_bets": 3,
    "up_amount": 100.00,
    "down_amount": 50.00
  },
  "bets": [
    {
      "id": 1,
      "direction": "UP",
      "amount": 10.00,
      "payout": null,
      "result": "PENDING",
      "placed_at": "2026-01-15 01:00:05"
    }
  ]
}
```

---

## 5. 히스토리 API

### 라운드 히스토리 조회

**Endpoint**: `GET /api/history.php`

**Parameters**:
- `limit`: 조회할 라운드 수 (기본: 20)
- `session_id`: 사용자별 베팅 히스토리

**Request**:
```javascript
// 최근 라운드 20개
fetch('/api/history.php?limit=20')
  .then(r => r.json())
  .then(console.log);

// 사용자 베팅 히스토리
fetch('/api/history.php?session_id=test123&limit=10')
  .then(r => r.json())
  .then(console.log);
```

**Response (라운드 히스토리)**:
```json
{
  "success": true,
  "type": "rounds",
  "statistics_24h": {
    "unique_players": 93,
    "total_bets": 450,
    "total_wagered": 4500.00,
    "total_payout": 4410.00,
    "win_rate": 44.35
  },
  "rounds": [
    {
      "id": 10,
      "round_number": 10,
      "start_timestamp": 1736883000000,
      "end_timestamp": 1736883060000,
      "start_price": 98700.00,
      "end_price": 98750.00,
      "result": "UP",
      "status": "COMPLETED",
      "total_up_amount": 200.00,
      "total_down_amount": 100.00,
      "total_up_players": 10,
      "total_down_players": 5,
      "total_amount": 300.00,
      "total_players": 15
    }
  ]
}
```

**Response (사용자 히스토리)**:
```json
{
  "success": true,
  "type": "session",
  "session_id": "test123",
  "statistics": {
    "total_bets": 10,
    "total_wagered": 100.00,
    "total_won": 50.00,
    "total_lost": 50.00,
    "win_count": 5,
    "lose_count": 5,
    "win_rate": 50.00,
    "net_profit": 0.00
  },
  "bets": [
    {
      "id": 1,
      "round_id": 10,
      "round_number": 10,
      "direction": "UP",
      "amount": 10.00,
      "payout": 19.60,
      "result": "WIN",
      "start_price": 98700.00,
      "end_price": 98750.00,
      "round_result": "UP",
      "placed_at": "2026-01-15 01:00:05"
    }
  ]
}
```

---

## 6. WebSocket API

### 연결

**URL**: `wss://gr.ezywallets.com/ws`

**연결 예시**:
```javascript
const ws = new WebSocket('wss://gr.ezywallets.com/ws');

ws.onopen = () => {
  console.log('Connected');

  // 구독
  ws.send(JSON.stringify({
    type: 'subscribe',
    session_id: 'test123'
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  console.log('Message:', data);
};
```

### 메시지 타입

#### 1. 게임 상태 (매초 브로드캐스트)

```json
{
  "type": "game.state",
  "round_id": 1,
  "round_number": 1,
  "status": "BETTING",
  "countdown": 25,
  "start_timestamp": 1736883600000,
  "start_price": 98765.43,
  "total_up_amount": 100.00,
  "total_down_amount": 50.00,
  "total_up_players": 5,
  "total_down_players": 3,
  "timestamp": 1736883625000
}
```

#### 2. 베팅 알림

```json
{
  "type": "bet.placed",
  "bet": {
    "round_id": 1,
    "direction": "UP",
    "amount": 10.00
  },
  "timestamp": 1736883625000
}
```

#### 3. 라운드 결과

```json
{
  "type": "round.result",
  "result": {
    "round_id": 1,
    "round_number": 1,
    "start_price": 98765.43,
    "end_price": 98800.50,
    "result": "UP"
  },
  "timestamp": 1736883660000
}
```

#### 4. 클라이언트 → 서버 메시지

**구독**:
```json
{
  "type": "subscribe",
  "session_id": "test123"
}
```

**Ping**:
```json
{
  "type": "ping"
}
```

**상태 조회**:
```json
{
  "type": "get_state"
}
```

---

## 사용 예시

### React/TypeScript

```typescript
import { BackendAPI, BackendWebSocket } from './services';

// 1. API 초기화 (자동)
// BackendAPI.init();

// 2. 사용자 정보 가져오기
async function loadUserInfo() {
  const sessionId = BackendAPI.getSessionId();
  const response = await fetch(`/api/user.php?session_id=${sessionId}`);
  const data = await response.json();

  console.log('Balance:', data.user.balance);
  return data;
}

// 3. 게임 상태 가져오기
async function loadGameState() {
  const data = await BackendAPI.getGameState();
  console.log('Round:', data.round_number, 'Status:', data.status);
  return data;
}

// 4. 베팅하기
async function placeBet(direction: 'UP' | 'DOWN', amount: number) {
  try {
    const result = await BackendAPI.placeBet(direction, amount);
    console.log('Bet placed! New balance:', result.balance);
    return result;
  } catch (error) {
    console.error('Bet failed:', error);
    throw error;
  }
}

// 5. WebSocket 연결
const ws = new BackendWebSocket(BackendAPI.getSessionId());

ws.on('game_state', (data) => {
  console.log('Game state updated:', data.status, data.countdown);
});

ws.on('bet_placed', (bet) => {
  console.log('New bet:', bet.direction, bet.amount);
});

ws.on('round_result', (result) => {
  console.log('Round ended:', result.result);
});

await ws.connect();
```

### Vanilla JavaScript

```javascript
// 1. 세션 ID 생성
const sessionId = 'session_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9);
localStorage.setItem('bc_game_session_id', sessionId);

// 2. 잔액 조회
async function getBalance() {
  const res = await fetch(`/api/user.php?session_id=${sessionId}`);
  const data = await res.json();
  return data.user.balance;
}

// 3. 베팅
async function bet(direction, amount) {
  const res = await fetch('/api/bet.php', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ direction, amount, session_id: sessionId })
  });
  return await res.json();
}

// 4. WebSocket
const ws = new WebSocket('wss://gr.ezywallets.com/ws');
ws.onopen = () => {
  ws.send(JSON.stringify({ type: 'subscribe', session_id: sessionId }));
};
ws.onmessage = (e) => {
  const data = JSON.parse(e.data);
  if (data.type === 'game.state') {
    console.log('Status:', data.status, 'Countdown:', data.countdown);
  }
};
```

---

## 에러 코드

| HTTP Code | 의미 |
|-----------|------|
| 200 | 성공 |
| 201 | 생성 성공 (베팅) |
| 400 | 잘못된 요청 |
| 401 | 인증 실패 |
| 403 | 권한 없음 (베팅 마감) |
| 404 | 찾을 수 없음 |
| 500 | 서버 오류 |

---

## 베팅 규칙

- **최소 베팅**: 1 USDT
- **최대 베팅**: 10,000 USDT
- **시작 잔액**: 1,000 USDT (게스트)
- **RTP**: 98% (하우스 수수료 2%)
- **배당 계산**: `(총 베팅액 × 0.98) ÷ 승자 총 베팅액`

## 게임 타이밍

- **라운드 시간**: 60초
- **베팅 가능**: 0-30초 (30초간)
- **베팅 마감**: 30초 시점
- **결과 확인**: 55-60초
