# wallet_db 钱包账本库

## 数据库定位

wallet_db 保存玩家余额、余额分片、资金流水和幂等记录，是资金安全的核心库。余额更新必须经过 wallet-shard-service，任何服务都不能直接 update 玩家余额。

## 核心表

### wallet_accounts 钱包账户表

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| account_id | bigint | 钱包账户 ID |
| merchant_id | bigint | 商户 ID |
| player_id | bigint | 玩家 ID |
| currency | varchar(16) | 币种 |
| balance | numeric(28, 8) | 可用余额 |
| frozen_balance | numeric(28, 8) | 冻结余额 |
| shard_id | int | 分片 ID |
| version | bigint | 乐观锁版本 |
| updated_at | timestamptz | 更新时间 |

### wallet_ledger 资金流水表

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| ledger_id | bigint | 流水 ID |
| idempotency_key | varchar(128) | 幂等键，唯一 |
| account_id | bigint | 钱包账户 ID |
| order_id | varchar(128) | 关联订单 |
| change_amount | numeric(28, 8) | 变动金额 |
| balance_after | numeric(28, 8) | 变动后余额 |
| biz_type | varchar(32) | BET、PAYOUT、REVERSAL |
| created_at | timestamptz | 创建时间 |

## 关键约束

- `wallet_ledger.idempotency_key` 必须唯一。
- 余额和流水必须在同一事务内完成。
- 账本流水不可物理删除，不允许覆盖历史金额。

## 示例 SQL

```sql
create unique index uk_wallet_ledger_idem on wallet_ledger(idempotency_key);
create index idx_wallet_accounts_shard on wallet_accounts(shard_id, account_id);
```

## merchant-gateway 第一阶段落地表

第一阶段商户 API 为了持久化测试数据，会通过 `平台服务/merchant-gateway/migrations/0001_merchant_gateway_core.sql` 在 `jiekouapi` PostgreSQL 库中创建以下简化钱包表。正式资金链路上线后，需要迁移到 wallet-service、wallet-shard-service 和 ledger-service。

### merchant_wallets

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| merchant_id | text | 商户编码 |
| player_id | text | 玩家 ID |
| currency | varchar(16) | 币种 |
| balance | bigint | 余额，最小货币单位 |
| updated_at | timestamptz | 更新时间 |

主键：`(merchant_id, player_id)`。

### merchant_transfers

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| merchant_id | text | 商户编码 |
| txn_id | text | 商户交易号 |
| player_id | text | 玩家 ID |
| type | varchar(32) | DEPOSIT 或 WITHDRAW |
| amount | bigint | 金额，最小货币单位 |
| balance_after | bigint | 交易后余额 |
| currency | varchar(16) | 币种 |
| status | varchar(32) | 状态 |
| remark | text | 备注 |
| created_at | timestamptz | 创建时间 |

主键：`(merchant_id, txn_id)`，用于商户交易幂等。
