@pioneer-platform/integration-view-only
v1.1.50
Published
Proof-of-concept demonstrating Pioneer SDK's view-only mode - fetch balances and view portfolio without requiring a connected KeepKey device.
Readme
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:
- ✅ Pubkeys can be generated from a connected device and cached
- ✅ SDK can initialize in view-only mode using cached pubkeys
- ✅ Balances can be fetched without device connection
- ✅ 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
# 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 devTest 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)
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:
{
"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
Filter Wildcard NetworkIds
const networkIds = [...new Set( PUBKEY_BLOB.flatMap((pk: any) => pk.networks || []) )].filter((id: string) => !id.includes('*')); // Removes invalid "eip155:*" patternsSkip 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
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 fileDependencies
{
"@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
Pubkeys are NOT sensitive
- Public keys are safe to store
- No private keys or seeds cached
- Cannot sign transactions with pubkeys alone
View-Only Limitations
isViewOnlyMode() === truecanSignTransactions() === false- All signing operations disabled
- Perfect for portfolio monitoring
Cache Invalidation
- Manual: Delete
pubkeys.json - Version check: Clears on version mismatch
- Device switch: Generates new pubkeys
- Manual: Delete
Next Steps
This proof-of-concept demonstrates the pattern works. To implement in production:
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
Mobile QR Code Flow
- Generate pubkeys on desktop
- Export as QR code
- Scan on mobile
- View portfolio without device
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/96Debug 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:60Troubleshooting
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.jsonand retry
"API call failed: Bad Request"
- Verify using
api.keepkey.info(notpioneers.dev) - Check
nodes: []andbalances: []in config - Ensure wildcard networkIds are filtered
"View-only mode should be active but is not"
- Check
viewOnlyMode: truein config - Verify
skipDevicePairing: true - Ensure
pubkeysarray 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
