npm package: @pioneer-platform/integration-view-only
Description: Proof-of-concept demonstrating Pioneer SDK's view-only mode - fetch balances and view portfolio without requiring a connected KeepKey device.
Latest version: 1.1.50

# View-Only Mode E2E Test

Proof-of-concept demonstrating Pioneer SDK's view-only mode - fetch balances and view portfolio without requiring a connected KeepKey device.

## Purpose

This test proves that:
1. ✅ Pubkeys can be generated from a connected device and cached
2. ✅ SDK can initialize in view-only mode using cached pubkeys
3. ✅ Balances can be fetched without device connection
4. ✅ Complete portfolio display works in view-only mode

**Performance Benefit:** 10-15x faster startup (< 1 second vs 5-15 seconds)

## Test Architecture

### Three-Phase Pattern

```
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 1: Generate Pubkeys (First Run Only)                     │
├─────────────────────────────────────────────────────────────────┤
│ • Connect to KeepKey device                                     │
│ • Initialize Pioneer SDK with full device access                │
│ • Generate pubkeys for 17 chains:                               │
│   - EVM: ETH, MATIC, BASE, BSC                                  │
│   - UTXO: BTC, LTC, DOGE, BCH, DASH                            │
│   - Cosmos: GAIA, OSMO, MAYA, THOR                             │
│   - Ripple: XRP                                                 │
│   - Solana: SOL                                                 │
│   - TRON: TRX                                                   │
│   - TON: Toncoin                                                │
│ • Store pubkeys to pubkeys.json (21 pubkey objects)            │
│ • Save device info and metadata                                 │
└─────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 2: Initialize View-Only Mode (Subsequent Runs)           │
├─────────────────────────────────────────────────────────────────┤
│ • Check for cached pubkeys.json                                 │
│ • Load pubkeys from cache                                       │
│ • Initialize SDK with:                                          │
│   - viewOnlyMode: true                                          │
│   - skipDevicePairing: true                                     │
│   - skipKeeperEndpoint: true                                    │
│   - pubkeys: CACHED_PUBKEYS                                     │
│ • NO device connection required                                 │
│ • Verify: isViewOnlyMode() === true                            │
│ • Verify: canSignTransactions() === false                      │
└─────────────────────────────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 3: Fetch Balances, Validate Data, and Display Portfolio  │
├─────────────────────────────────────────────────────────────────┤
│ • Show addresses being queried (first 5)                        │
│ • Call SDK.getBalances() using cached pubkeys                   │
│ • Fetch from api.keepkey.info (617ms)                          │
│ • Receive 96 balances across 11 chains                         │
│ • **NEW: COMPREHENSIVE DATA VALIDATION**                        │
│   - Verify balance data structure                               │
│   - Check for all-zero balances (API failure indicator)        │
│   - Validate price data completeness (>50% must have prices)   │
│   - Ensure chain identifiers present                            │
│   - Compare chains requested vs chains with data                │
│ • Display validation report with errors/warnings                │
│ • **TEST FAILS if critical validation errors detected**        │
│ • Display formatted tables:                                     │
│   - 🪙 NATIVE ASSETS (18 assets)                               │
│   - 💵 STABLECOINS (3 assets)                                  │
│   - 🎯 TOKENS (75 tokens)                                      │
│   - 📊 CHAIN BREAKDOWN with percentages                        │
│ • Total portfolio value: $415.55                                │
└─────────────────────────────────────────────────────────────────┘
```

## Running the Test

```bash
# First run (generate pubkeys - requires connected KeepKey)
bun run dev

# Subsequent runs (view-only mode - no device needed)
bun run dev

# Clean cache and regenerate
rm pubkeys.json && bun run dev
```

## Test Results

### Successful Output Example

```
*************************************************************
*        PIONEER SDK - VIEW-ONLY MODE E2E TEST             *
*************************************************************

📂 Found existing pubkeys.json - Loading cached pubkeys
✅ Loaded 18 pubkeys from cache
   Device: keepkey:TestKeepKeyMain.json
   Skipping Phase 1 (device already paired)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PHASE 2: Testing View-Only Mode (No Device Required)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✅ SDK instance created
   Pubkeys loaded: 18
   View-only mode: true
   Can sign transactions: false

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
PHASE 3: Verifying Balance Data
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

🪙  NATIVE ASSETS

┌────────┬──────────────────────────────┬─────────────┬────────────┬───────────┐
│ Symbol │ Chain                        │ Balance     │ Price      │ Value USD │
├────────┼──────────────────────────────┼─────────────┼────────────┼───────────┤
│ BTC    │ bip122:000000000019d6689c... │ 0.00061789  │ $105421.00 │ $65.14    │
│ ETH    │ eip155:1                     │ 0.00556245  │ $3537.63   │ $19.68    │
│ ...    │ ...                          │ ...         │ ...        │ ...       │
└────────┴──────────────────────────────┴─────────────┴────────────┴───────────┘
  📊 Total Native: $152.84

💵  STABLECOINS
[Table with USDC, USDT]
  📊 Total Stablecoins: $12.68

🎯  TOKENS
[Table with top 15 tokens]
  📊 Total Tokens: $250.03

📊  CHAIN BREAKDOWN
[Table with per-chain totals and percentages]

═══════════════════════════════════════════════════════════════
  💰 TOTAL PORTFOLIO VALUE: $415.55
═══════════════════════════════════════════════════════════════
  Native: $152.84 (36.8%)
  Stablecoins: $12.68 (3.1%)
  Tokens: $250.03 (60.2%)
  Assets: 18 native + 3 stablecoins + 75 tokens = 96 total
═══════════════════════════════════════════════════════════════

🎉 VIEW-ONLY MODE E2E TEST PASSED!
```

## Key Technical Details

### API Configuration

**CRITICAL:** Must use `api.keepkey.info` API (NOT `pioneers.dev`)

```typescript
const apiUrl = process.env.API_URL || 'https://api.keepkey.info';
const spec = `${apiUrl}/spec/swagger.json`;

const config = {
  spec,
  keepkeyApiKey: process.env.KEEPKEY_API_KEY || 'e4ea6479-5ea4-4c7d-b824-e075101bf9fd',
  wss: process.env.VITE_PIONEER_URL_WSS || 'wss://api.keepkey.info',
  viewOnlyMode: true,
  skipDevicePairing: true,
  skipKeeperEndpoint: true,
  pubkeys: CACHED_PUBKEYS,
  blockchains: NETWORK_IDS,
  nodes: [],      // Required empty array
  balances: [],   // Required empty array
};
```

### Pubkey Cache Format

`pubkeys.json`:
```json
{
  "pubkeys": [
    {
      "symbol": "ETH",
      "address": "0x141D9959cAe3853b035000490C03991eB70Fc4aC",
      "pubkey": "0x141D9959cAe3853b035000490C03991eB70Fc4aC",
      "networks": ["eip155:1", "eip155:137", "eip155:56", ...],
      "pathMaster": "m/44'/60'/0'/0/0",
      "note": "ETH"
    },
    {
      "symbol": "BTC",
      "pubkey": "xpub6BxKtd6aAuz23XqtWXeSqxShJZn8yqiUmaTdvsPWS3riKkNRcXEPmn1CXmKM1M43mrWfN5QwjdLRghZLrgwMLCeRZqZNuYhVNXr6Pp7aDsH",
      "networks": ["bip122:000000000019d6689c085ae165831e93"],
      "pathMaster": "m/44'/0'/0'",
      "scriptType": "p2pkh",
      "note": "Bitcoin (Legacy)"
    },
    // ... 16 more pubkeys
  ],
  "deviceInfo": {
    "label": "keepkey:TestKeepKeyMain.json",
    "model": "KeepKey",
    "deviceId": "...",
    "features": {...}
  },
  "timestamp": 1234567890,
  "version": "1.0.0"
}
```

### Critical Implementation Details

1. **Filter Wildcard NetworkIds**
   ```typescript
   const networkIds = [...new Set(
     PUBKEY_BLOB.flatMap((pk: any) => pk.networks || [])
   )].filter((id: string) => !id.includes('*'));
   // Removes invalid "eip155:*" patterns
   ```

2. **Skip GetCharts Gracefully**
   - SDK was modified to handle missing GetCharts API
   - Continues without charts data if API unavailable
   - Located in: `pioneer-sdk/src/index.ts:2140-2153`

3. **Table Rendering**
   - Simple ASCII table rendering (no external deps)
   - Box drawing characters: ┌─┬─┐├─┼─┤└─┴─┘
   - Auto-sizing columns with max width 30 chars
   - Function: `renderTable()` at line 32

## File Structure

```
intergration-view-only/
├── src/
│   ├── index.ts              # Main test file (3 phases)
│   └── portfolio-table.ts    # Reference from intergration-coins
├── pubkeys.json              # Cached pubkeys (gitignored)
├── package.json              # Dependencies
├── tsconfig.json             # TypeScript config
└── README.md                 # This file
```

## Dependencies

```json
{
  "@pioneer-platform/pioneer-sdk": "workspace:*",
  "@pioneer-platform/pioneer-coins": "workspace:*",
  "@pioneer-platform/pioneer-caip": "workspace:*",
  "@pioneer-platform/loggerdog": "workspace:*",
  "typescript": "5.2.2"
}
```

## Performance Metrics

### Phase 1 (First Run - With Device)
- Device connection: ~2-5 seconds
- Pubkey generation: ~3-10 seconds
- **Total: ~5-15 seconds**

### Phase 2 + 3 (Subsequent Runs - View-Only)
- Load from cache: <10ms
- SDK initialization: ~100ms
- Balance fetch: ~617ms
- **Total: <1 second**

**Performance Improvement: 10-15x faster startup**

## Security Notes

1. **Pubkeys are NOT sensitive**
   - Public keys are safe to store
   - No private keys or seeds cached
   - Cannot sign transactions with pubkeys alone

2. **View-Only Limitations**
   - `isViewOnlyMode() === true`
   - `canSignTransactions() === false`
   - All signing operations disabled
   - Perfect for portfolio monitoring

3. **Cache Invalidation**
   - Manual: Delete `pubkeys.json`
   - Version check: Clears on version mismatch
   - Device switch: Generates new pubkeys

## Next Steps

This proof-of-concept demonstrates the pattern works. To implement in production:

1. **KeepKey Vault Implementation**
   - Store pubkeys in localStorage (not JSON file)
   - Add UI modal for mode selection
   - Implement mode switching (view-only ↔ full)
   - See: `/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault/docs/view-only-mode-implementation.md`

2. **Mobile QR Code Flow**
   - Generate pubkeys on desktop
   - Export as QR code
   - Scan on mobile
   - View portfolio without device

3. **Cloud Sync (Optional)**
   - Encrypted pubkey backup
   - Multi-device sync
   - User-controlled encryption

## Validation System

### Critical Errors (Test Fails with Exit Code 1)

❌ **All balances are zero**
- Indicates balance API is not returning data
- Check API connectivity and authentication

❌ **>50% of balances missing price data**
- Indicates pricing service failure
- Verify pricing API endpoints are responding

❌ **Balances exist but no chain identifiers**
- Data structure corruption
- Check Pioneer SDK balance transformation logic

### Warnings (Non-Critical)

⚠️ **Missing network identifiers on individual balances**
- Some balances may not display correctly
- Review balance data structure

⚠️ **Missing addresses on balances**
- Balance attribution may be unclear
- Check pubkey → balance mapping

⚠️ **Total portfolio value is $0**
- May indicate empty wallet (normal)
- Or pricing data unavailable (warning)

### Validation Output Example

```
🔍 Running Data Validation...

📊 Validation Results:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Total balances: 96
  Zero balances: 12
  Missing prices: 3
  Missing networks: 0
  Invalid formats: 0
  Chains requested: 14
  Chains with balances: 11
  Total value USD: $415.55

✅ Data structure validation PASSED

📊 Test Statistics:
   Pubkeys: 18
   Networks: 14
   Balances: 96
   Chains with data: 11
   Total value: $415.55
   Zero balances: 12/96
   Missing prices: 3/96
```

### Debug Output (On Validation Failure)

When validation fails, the test automatically dumps:

```
🔍 Debugging Info:
   First 3 balance entries:

   Balance 1:
     symbol: BTC
     networkId: bip122:000000000019d6689c085ae165831e93
     balance: 0.00061789
     priceUsd: 105421.00
     valueUsd: 65.14
     address: bc1qh7629dslkfjdslkfj...
     caip: bip122:000000000019d6689c085ae165831e93/slip44:0

   Balance 2:
     symbol: ETH
     networkId: eip155:1
     balance: 0.00556245
     priceUsd: 3537.63
     valueUsd: 19.68
     address: 0x141D9959cAe3853b03...
     caip: eip155:1/slip44:60
```

## Troubleshooting

### Validation Failures

**"❌ CRITICAL: ALL balances are zero"**
- Pioneer API not returning balance data
- Check: `curl https://api.keepkey.info/api/v1/health`
- Verify: KEEPKEY_API_KEY is valid
- Review: Pioneer server logs for errors

**"❌ CRITICAL: X/Y balances missing price data"**
- Pricing service is down or degraded
- Check coincap/coingecko API status
- May require fallback to another pricing provider

**"No balances found but pubkeys exist"**
- May be normal (empty wallet)
- Or balance fetching logic broken
- Check network connectivity to blockchain nodes

### "Failed to generate pubkeys"
- Ensure KeepKey device is connected
- Check USB connection
- Verify device is unlocked
- Delete `pubkeys.json` and retry

### "API call failed: Bad Request"
- Verify using `api.keepkey.info` (not `pioneers.dev`)
- Check `nodes: []` and `balances: []` in config
- Ensure wildcard networkIds are filtered

### "View-only mode should be active but is not"
- Check `viewOnlyMode: true` in config
- Verify `skipDevicePairing: true`
- Ensure `pubkeys` array is provided

## References

- **Vault Implementation Plan:** `/Users/highlander/WebstormProjects/keepkey-stack/projects/keepkey-vault/docs/view-only-mode-implementation.md`
- **Working Test Reference:** `/Users/highlander/WebstormProjects/keepkey-stack/projects/pioneer/e2e/wallets/intergration-coins`
- **Pioneer SDK:** `@pioneer-platform/pioneer-sdk`
- **API Spec:** `https://api.keepkey.info/spec/swagger.json`

---

**Status:** ✅ PRODUCTION READY - Pattern proven and documented