# ADR-008 UI Implementation Guide

This document provides guidance for front-end developers implementing UI for the ADR-008 security features.

## 1. Commit-Reveal Investment System

### Overview
Investments now use a two-phase commit-reveal pattern to prevent front-running attacks. Users must first commit a hash of their investment, wait for a delay period, then reveal the actual amount.

### Flow
```
1. User decides to invest amount X in opportunity Y
2. Frontend generates random nonce (32 bytes)
3. Frontend computes commitment = SHA256(amount || nonce || investorAddress)
4. User calls commitInvestment(opportunityID, commitment, vitaID)
5. Wait 10+ blocks (configurable: CommitRevealDelay)
6. User calls revealInvestment(commitmentID, amount, nonce)
7. If valid, investment is executed
```

### Contract Methods

#### `commitInvestment(opportunityID: uint64, commitment: bytes32, vitaID: uint64) -> uint64`
- Returns: commitmentID
- Event: `CommitmentCreated(commitmentID, opportunityID, vitaID, revealDeadline)`

#### `revealInvestment(commitmentID: uint64, amount: uint64, nonce: bytes) -> bool`
- Must be called after CommitRevealDelay blocks (default: 10)
- Must be called before CommitRevealWindow expires (default: 1000 blocks)
- Event: `CommitmentRevealed(commitmentID, amount, investmentID)`

#### `cancelCommitment(commitmentID: uint64) -> bool`
- Can cancel pending commitments
- Event: `CommitmentCanceled(commitmentID)`

#### `getCommitment(commitmentID: uint64) -> CommitmentInfo | null`
- Returns commitment details including status

### Frontend Implementation Notes

```typescript
// Generate commitment
function createCommitment(amount: bigint, investorAddress: string): { commitment: string, nonce: string } {
  const nonce = crypto.randomBytes(32);
  const preimage = Buffer.concat([
    Buffer.alloc(8), // amount as uint64 big-endian
    nonce,
    Buffer.from(investorAddress, 'hex')
  ]);
  // Write amount as big-endian uint64
  preimage.writeBigUInt64BE(amount, 0);

  const commitment = sha256(preimage);
  return {
    commitment: commitment.toString('hex'),
    nonce: nonce.toString('hex')
  };
}

// IMPORTANT: Store nonce securely until reveal!
// If user loses nonce, they cannot reveal and funds are locked until expiry
```

### UI Considerations
- **Nonce Storage**: Store nonce in localStorage/sessionStorage with commitmentID as key
- **Progress Indicator**: Show blocks remaining until reveal is allowed
- **Deadline Warning**: Alert user if reveal deadline is approaching
- **Retry Logic**: If reveal fails, nonce is still valid for retry

---

## 2. Whale Concentration Limits

### Overview
No single investor can hold more than 5% (configurable) of any investment opportunity's total pool.

### How It Works
- When `invest()` is called, the contract checks:
  ```
  (existingInvestment + newAmount) / (totalPool + newAmount) <= WealthConcentration
  ```
- Default limit: 500 basis points (5%)
- Enforced at investment time, not at commitment time

### UI Considerations
- **Pre-check**: Before committing, query user's existing investment in opportunity
- **Warning**: Show warning if user is approaching concentration limit
- **Error Handling**: Handle "investment would exceed whale concentration limit" error gracefully

### Querying Current Investment
```typescript
// Get all investments by an investor
const investments = await contract.getInvestmentsByInvestor(vitaID);
const investmentInOpp = investments.find(inv => inv.opportunityID === targetOppID);
const currentAmount = investmentInOpp?.amount || 0n;

// Get opportunity details
const opp = await contract.getOpportunity(oppID);
const totalPool = opp.totalPool;

// Calculate max additional investment
const maxConcentration = config.wealthConcentration; // e.g., 500 = 5%
const maxAllowed = (totalPool * BigInt(maxConcentration)) / 10000n;
const maxAdditional = maxAllowed - currentAmount;
```

---

## 3. Sybil Resistance Vesting

### Overview
New Vita tokens have a 30-day vesting period before gaining full rights. This prevents mass creation of fake identities for manipulation.

### Default Vesting Period
- 2,592,000 blocks (~30 days at 1 second per block)
- Committee can adjust vesting for individual tokens

### Contract Methods

#### `isFullyVested(tokenID: uint64) -> bool`
- Returns true if current block >= vestedUntil

#### `getVestingInfo(tokenID: uint64) -> [vestedUntil, isFullyVested, remainingBlocks] | null`
- `vestedUntil`: Block height when vesting completes
- `isFullyVested`: Current vesting status
- `remainingBlocks`: Blocks until fully vested (0 if already vested)

#### `setVesting(tokenID: uint64, vestedUntil: uint32) -> bool` (Committee only)
- Can accelerate vesting for verified identities
- Can extend vesting for suspicious accounts

### UI Considerations

#### Registration Flow
```typescript
// After Vita registration, show vesting status
const vestingInfo = await vita.getVestingInfo(tokenID);
if (!vestingInfo[1]) { // not fully vested
  const remainingBlocks = vestingInfo[2];
  const estimatedTime = remainingBlocks * 1; // 1 second per block
  showVestingBanner(`Your identity will be fully verified in ~${formatDuration(estimatedTime)}`);
}
```

#### Feature Gating
Some features may require fully vested Vita:
- **Voting**: May require full vesting to prevent vote manipulation
- **Large Investments**: Higher limits may require vesting
- **Attestation**: May need vesting to attest others

```typescript
// Check before allowing sensitive actions
async function canPerformAction(vitaID: uint64, action: string): Promise<boolean> {
  const isVested = await vita.isFullyVested(vitaID);

  switch(action) {
    case 'vote':
    case 'large_investment':
    case 'attest_others':
      return isVested;
    default:
      return true; // Basic actions allowed during vesting
  }
}
```

#### Vesting Progress Display
```typescript
// Calculate and display vesting progress
const vestingInfo = await vita.getVestingInfo(tokenID);
const vestedUntil = vestingInfo[0];
const token = await vita.getTokenByID(tokenID);
const createdAt = token.createdAt;

const totalVestingBlocks = vestedUntil - createdAt;
const elapsedBlocks = currentBlock - createdAt;
const progressPercent = Math.min(100, (elapsedBlocks / totalVestingBlocks) * 100);
```

---

## Configuration Values

These can be queried from the contracts:

### Collocatio Config
```typescript
const config = await collocatio.getConfig();
// config.commitRevealDelay = 10 (blocks)
// config.commitRevealWindow = 1000 (blocks)
// config.wealthConcentration = 500 (basis points = 5%)
```

### Vita Vesting
```typescript
// Default vesting period: 2,592,000 blocks (~30 days)
// Query individual token vesting via getVestingInfo()
```

---

## Events to Subscribe

### Collocatio Events
- `CommitmentCreated(commitmentID, opportunityID, vitaID, revealDeadline)`
- `CommitmentRevealed(commitmentID, amount, investmentID)`
- `CommitmentCanceled(commitmentID)`

### Vita Events
- `VestingUpdated(tokenID, vestedUntil, updatedBy)`

---

## Error Messages

| Error | Meaning | UI Action |
|-------|---------|-----------|
| `commitment already exists` | Duplicate commitment | Show existing commitment |
| `commitment not found` | Invalid commitmentID | Check ID is correct |
| `reveal too early` | Before delay period | Show countdown |
| `reveal window expired` | Past deadline | Commitment forfeited |
| `commitment verification failed` | Wrong amount/nonce | Check stored values |
| `investment would exceed whale concentration limit` | Too much in one opp | Show max allowed |
| `vita is not fully vested` | Vesting incomplete | Show remaining time |
