4. Wallets · Addresses · Asset Wallet
Stage 9 정식 매핑 — 3 asset 패턴 · whitelisted address · chain-specific quirk3 Asset Pattern (★ Stage 9 정식 명세)
account-and-wallet-structure.md, p.1-2 에서 정식 enumerate.
| Asset 패턴 | 예시 | Permanent Address | Deposit Address 개수 | 분기자 |
|---|---|---|---|---|
| UTXO-based | BTC, BCH, LTC, DOGE | 1 | N | address 그 자체 |
| Account-based (no tag) | ETH, EVM 전반 | — | 1 (단일 강제) | — |
| Account-based (tag/memo) | XRP, XLM | — | 1 (on-chain 동일) | N tags / memos |
EVM 의 "1 vault account = 1 address" 제약
End-client 별 unique address 가 필요한 경우 individual vault account 필요 → intermediate vault 패턴 사용 (omnibus + intermediate per client).
DB Schema
CREATE TABLE asset_wallets (
id BINARY(16) PRIMARY KEY,
vault_account_id BINARY(16) NOT NULL,
chain VARCHAR(32) NOT NULL, -- 'BTC', 'ETH', 'SOL', ...
asset_id VARCHAR(64) NOT NULL, -- 'BTC', 'ETH', 'USDC_ETH', ...
asset_pattern ENUM('utxo', 'account-no-tag', 'account-tag') NOT NULL,
permanent_address VARCHAR(128), -- UTXO 만 set
created_at DATETIME(6) NOT NULL,
UNIQUE KEY (vault_account_id, asset_id),
KEY (chain)
);
CREATE TABLE addresses (
id BINARY(16) PRIMARY KEY,
asset_wallet_id BINARY(16) NOT NULL,
address_string VARCHAR(128) NOT NULL,
tag_or_memo VARCHAR(64), -- XRP/XLM 의 분기자
address_type ENUM('deposit', 'change', 'permanent') NOT NULL,
derivation_index INT, -- UTXO 의 deposit address index
deactivated_at DATETIME(6),
created_at DATETIME(6) NOT NULL,
KEY (asset_wallet_id, address_type),
UNIQUE KEY (address_string, tag_or_memo)
);
Whitelisted Address ≠ Vault Address
whitelisting-new-addresses.md, p.1: Whitelisted address = Vault 외부 deposit address.
| Type | 의미 | workspace 잔액 표시 | billable |
|---|---|---|---|
| Internal | 같은 workspace 의 다른 user/team 의 외부 wallet | 표시 | YES |
| External | 외부 organization 의 wallet | 표시 안 됨 | — |
| Contract / Program | smart contract address | — | — |
CREATE TABLE whitelisted_addresses (
id BINARY(16) PRIMARY KEY,
workspace_id BINARY(16) NOT NULL,
type ENUM('internal', 'external', 'contract') NOT NULL,
asset_id VARCHAR(64) NOT NULL,
address_string VARCHAR(128) NOT NULL,
tag_or_memo VARCHAR(64),
label VARCHAR(128),
approved_by_quorum_id BINARY(16) NOT NULL, -- Admin Quorum approval 의무
approved_at DATETIME(6) NOT NULL,
KEY (workspace_id, type)
);
CREATE TABLE one_time_addresses (
-- OTA = whitelist 우회 path. Address-level quorum 없음, Policy 가 유일한 방어선
id BINARY(16) PRIMARY KEY,
workspace_id BINARY(16) NOT NULL,
used_in_tx_id BINARY(16) NOT NULL,
address_string VARCHAR(128) NOT NULL,
used_at DATETIME(6) NOT NULL
);
Chain-별 운영 제약 (Stage 7)
| 제약 | 예시 | DB 의 함의 |
|---|---|---|
| Minimum balance (Base Reserve) | ALGO / KSM / NEAR / DOT / XRP / SOL / XLM / TON 등 | asset_wallets.min_balance_reserved 컬럼 |
| Minimum transaction amount | BTC 0.00000582 / ALGO 1e-6 / ADA 1 / DOGE 0.01 / TON 1e-6 | Submit 시 validation; 미만 시 Amount Too Small status |
| Account 활성화 | Stellar (1 XLM 필수), Polkadot (0.01 DOT 이상), Near (token contract pre-funding) | asset_wallets.activated_at 컬럼 |
| Trust line (XRP) | Reserve 미만 시 on-chain 자동 삭제 | 주기적 reconciliation + 상태 동기화 |
| Token wallet 제약 (TL) | ALGO / XRP / SOL / XLM token wallet | Role 별 생성 권한 차이 — role_permissions 테이블에 'TL' label |
| Chain type 분류 | EVM account-based / non-EVM account-based / UTXO / Cosmos SDK | chains lookup 테이블의 type 컬럼 |
| Internal transactions (EVM) | smart contract 내부 native transfer — Ethereum / Optimism / Arbitrum / Avalanche / Base / Celo 등 | 관찰 메커니즘은 본 자료 미명시 → 17. Deposit |
Withdrawal Vault Round-Robin (Stage 9)
- EVM: nonce 가 순차 — 단일 vault stuck 시 전체 queue 정체. 여러 withdrawal vault round-robin 권장
- Bitcoin: unconfirmed input 25 subsequent tx chain limit (Bitcoin Core default) — 여러 withdrawal vault
- Solana: vault account 당 동시 5 tx queue (6번째 이상 Submitted max 2h 대기 후 terminated)