POWR/docs/olas-ndk-mobile-resources.md

17 KiB

NDK Mobile Implementation References

File Structure Overview

NDK Mobile Implementation References

Core Types and Exports

Main Entry Point (src/index.ts)

import '@bacons/text-decoder/install';
import 'react-native-get-random-values';

export * from './hooks';
export * from './cache-adapter/sqlite';
export * from './components';
export * from './components/relays';
export * from '@nostr-dev-kit/ndk';

import NDK from '@nostr-dev-kit/ndk';
export default NDK;

Core Types (src/types.ts)

export type SettingsStore = {
    getSync: (key: string) => string | null;
    get: (key: string) => Promise<string | null>;
    set: (key: string, value: string) => Promise<void>;
    delete: (key: string) => Promise<void>;
}

File Structure Overview

NDK Mobile Structure (@nostr-dev-kit/ndk-mobile)

src/
  ├── cache-adapter/
  │   ├── migrations.ts      [REVIEWED] - Database versioning system
  │   └── sqlite.ts         [REVIEWED] - SQLite implementation
  ├── hooks/
  │   ├── ndk.ts            [REVIEWED] - Core NDK hook
  │   ├── session.ts        [REVIEWED] - Session management
  │   ├── subscribe.ts      [REVIEWED] - Event subscription
  │   ├── user-profile.ts   [REVIEWED] - Profile handling
  │   └── wallet.ts         [REVIEWED] - Wallet integration
  ├── providers/
  │   ├── ndk/
  │   │   ├── signers/      [REVIEWED]
  │   │   │   ├── nip07.ts  - Browser extension auth
  │   │   │   ├── nip46.ts  - Remote signing
  │   │   │   └── pk.ts     - Private key handling
  │   │   ├── wallet.tsx    [REVIEWED] - Wallet provider impl
  │   │   └── context.tsx   
  │   └── session/
  │       └── NEED ACCESS
  ├── stores/
  │   ├── ndk.ts            [REVIEWED] - NDK state management
  │   ├── session/          [REVIEWED] - Session management
  │   │   ├── index.ts      - Store definition
  │   │   ├── types.ts      - Type definitions
  │   │   └── actions/      - Store actions
  │   └── wallet.ts
  └── types.ts

Recent Component Analysis

Authentication & Signing (providers/ndk/signers/)

NIP-07 Browser Extension (nip07.ts)

export async function loginWithNip07() {
    const signer = new NDKNip07Signer();
    return signer.user().then(async (user: NDKUser) => {
        if (user.npub) {
            return { user, npub: user.npub, signer };
        }
    });
}

NIP-46 Remote Signing (nip46.ts)

export async function withNip46(
    ndk: NDK, 
    token: string, 
    sk?: string
): Promise<NDKSigner | null> {
    let localSigner = sk ? 
        new NDKPrivateKeySigner(sk) : 
        NDKPrivateKeySigner.generate();
    
    const signer = new NDKNip46Signer(ndk, token, localSigner);
    return signer.blockUntilReady();
}

Wallet Provider (providers/ndk/wallet.tsx)

  • Key Features:

    • Wallet state management
    • Balance tracking
    • Transaction monitoring
    • Multi-wallet support (NWC, Cashu)
  • Notable Implementation:

function persistWalletConfiguration(
    wallet: NDKWallet, 
    settingsStore: SettingsStore
) {
    const payload = walletPayload(wallet);
    const type = wallet.type;
    settingsStore.set('wallet', JSON.stringify({ type, payload }));
}

POWR Implementation Patterns

1. Authentication Strategy

// Support multiple auth methods
export type WorkoutAuthMethod = 
    | { type: 'nip07' }
    | { type: 'nip46'; token: string }
    | { type: 'privateKey'; key: string };

// Auth provider wrapper
export const WorkoutAuthProvider = ({ 
    children,
    onAuth
}: PropsWithChildren<{
    onAuth: (user: NDKUser) => void
}>) => {
    // Implementation
};

2. Session Management

export interface WorkoutSession {
    currentUser: NDKUser;
    activeWorkout?: NDKEvent;
    templates: Map<string, NDKEvent>;
    history: NDKEvent[];
}

export const WorkoutSessionProvider = ({
    children,
    session
}: PropsWithChildren<{
    session: WorkoutSession
}>) => {
    // Implementation
};

Files Still Needed:

  1. Session Provider Implementation:

    src/providers/session/
    ├── context.tsx
    └── index.tsx
    
  2. Wallet Store Implementation:

    src/stores/wallet.ts
    ```# POWR Implementation Resources
    
    

File Structures

NDK Mobile Structure (@nostr-dev-kit/ndk-mobile)

src/
  ├── cache-adapter/
  │   ├── migrations.ts      [REVIEWED] - Database versioning system
  │   └── sqlite.ts         [REVIEWED] - SQLite implementation
  ├── hooks/
  │   ├── ndk.ts            [REVIEWED] - Core NDK hook
  │   ├── session.ts        [REVIEWED] - Session management
  │   ├── subscribe.ts      [REVIEWED] - Event subscription
  │   ├── user-profile.ts   [REVIEWED] - Profile handling
  │   └── wallet.ts         [REVIEWED] - Wallet integration
  ├── providers/
  │   ├── ndk/
  │   │   ├── signers/
  │   │   │   ├── nip07.ts  [REVIEWED] - Browser extension auth
  │   │   │   ├── nip46.ts  [REVIEWED] - Remote signing
  │   │   │   └── pk.ts     [REVIEWED] - Private key handling
  │   │   └── context.tsx
  │   └── session/
  ├── stores/
  │   ├── ndk.ts            [REVIEWED] - NDK state management
  │   ├── session/
  │   │   ├── index.ts      [REVIEWED] - Session store
  │   │   ├── types.ts      [REVIEWED] - Session types
  │   │   ├── utils.ts      [REVIEWED] - Helper functions
  │   │   └── actions/      [REVIEWED]
  │   │       ├── addEvent.ts    - Event handling
  │   │       ├── init.ts        - Session initialization
  │   │       ├── mutePubkey.ts  - User muting
  │   │       ├── setEvents.ts   - Event management
  │   │       ├── setMuteList.ts - Mute list management
  │   │       └── wot.ts         - Web of trust
  │   └── wallet.ts
  └── types.ts

Files To Review Next

NDK Mobile

  1. Provider Implementation:

    src/providers/ndk/
    ├── context.tsx    - NDK context setup
    └── index.tsx      - Provider exports
    
  2. Session Provider:

    src/providers/session/
    ├── context.tsx    - Session context
    └── index.tsx      - Session exports
    

NDK Core Internals

Looking at specific NDK files would be helpful:

packages/ndk/
├── events/
│   ├── Event.ts     - Event implementation
│   └── kinds.ts     - Event kind definitions
└── relay/
    ├── Relay.ts     - Relay implementation
    └── Pool.ts      - Relay pool management

## Detailed Component Analysis

### 0. Authentication & Signing (NDK)

#### Signer Implementation (`src/providers/ndk/signers/`)
- **Available Signers**:
  - NIP-07 (Browser Extension)
  - NIP-46 (Remote Signing)
  - Private Key
- **Key Implementations**:

```typescript
// NIP-07 Browser Extension
export async function loginWithNip07() {
    const signer = new NDKNip07Signer();
    return signer.user().then(async (user: NDKUser) => {
        if (user.npub) {
            return { user, npub: user.npub, signer };
        }
    });
}

// NIP-46 Remote Signing
export async function withNip46(ndk: NDK, token: string, sk?: string): Promise<NDKSigner | null> {
    let localSigner = sk ? 
        new NDKPrivateKeySigner(sk) : 
        NDKPrivateKeySigner.generate();
    
    const signer = new NDKNip46Signer(ndk, token, localSigner);
    return signer.blockUntilReady();
}
  • Payload Handling:
export async function withPayload(
    ndk: NDK,
    payload: string,
    settingsStore: SettingsStore
): Promise<NDKSigner | null> {
    if (payload.startsWith('nsec1')) return withPrivateKey(payload);
    // NIP-46 handling with local key persistence
}
  • POWR Applications:
    • User authentication
    • Workout signing
    • Template authorization
    • Private workout encryption

Wallet Integration (hooks/wallet.ts)

  • Core Functionality:
const useNDKWallet = () => {
    const { ndk } = useNDK();
    const activeWallet = useWalletStore(s => s.activeWallet);
    const setActiveWallet = (wallet: NDKWallet) => {
        storeSetActiveWallet(wallet);
        ndk.wallet = wallet;
        // Handle persistence
    }
    return { activeWallet, setActiveWallet, balances };
}
  • Features:
    • Wallet state management
    • Balance tracking
    • Settings persistence
  • POWR Applications:
    • Premium template purchases
    • Trainer payments
    • Achievement rewards

1. Session Store Implementation (NDK)

Store Architecture (stores/index.ts, stores/types.ts)

  • Core State Structure:
export interface SessionState {
    follows: string[] | undefined;
    muteListEvent: NDKList | undefined;
    muteList: Set<Hexpubkey>;
    events: Map<NDKKind, NDKEvent[]>;
    wot: Map<Hexpubkey, number>;
    ndk: NDK | undefined;
}
  • Initialization Options:
export interface SessionInitOpts {
    follows?: boolean;
    muteList?: boolean;
    wot?: number | false;
    kinds?: Map<NDKKind, { wrapper?: NDKEventWithFrom<any> }>;
    filters?: (user: NDKUser) => NDKFilter[];
}

Event Management (stores/actions/)

Event Addition (addEvent.ts)
export const addEvent = (event: NDKEvent, onAdded, set) => {
    set((state: SessionState) => {
        const kind = event.kind!;
        const newEvents = new Map(state.events);
        let existing = newEvents.get(kind) || [];

        // Handle replaceable events
        if (event.isParamReplaceable()) {
            // Deduplication logic
        }

        newEvents.set(kind, [...existing, event]);
        return { events: newEvents, ...changes };
    });
};
  • Key Features:
    • Event deduplication
    • Replaceable event handling
    • State immutability
Session Initialization (init.ts)
export const initSession = (
    ndk: NDK,
    user: NDKUser,
    settingsStore: SettingsStore,
    opts: SessionInitOpts,
    on: SessionInitCallbacks,
    set,
    get
) => {
    const filters = generateFilters(user, opts);
    const sub = ndk.subscribe(filters, {
        groupable: false,
        closeOnEose: false
    });
    // Event handling setup
};
  • Features:
    • Filter generation
    • Event subscription
    • State initialization

Web of Trust Implementation (wot.ts)

export function addWotEntries(
    ndk: NDK,
    follows: Hexpubkey[],
    settingsStore: SettingsStore,
    set: (state: Partial<SessionState>) => void,
    cb: () => void
) {
    // WoT computation implementation
}
  • Key Features:
    • Trust score computation
    • Cache management
    • Persistence strategy

POWR Adaptation Strategy

1. Workout Session Store

export interface WorkoutSessionState {
    activeWorkout?: NDKEvent;
    templates: Map<NDKKind, NDKEvent[]>;
    workoutHistory: NDKEvent[];
    follows: Set<Hexpubkey>; // Following trainers/users
    trust: Map<Hexpubkey, number>; // Trainer trust scores
}

export interface WorkoutInitOpts {
    loadTemplates?: boolean;
    loadHistory?: boolean;
    watchFollows?: boolean;
    trustScoring?: boolean;
}

2. Event Management

export const addWorkoutEvent = (event: NDKEvent, set) => {
    set((state: WorkoutSessionState) => {
        switch(event.kind) {
            case 33401: // Exercise Template
                return handleTemplateEvent(state, event);
            case 33402: // Workout Template
                return handleWorkoutTemplate(state, event);
            case 33403: // Workout Record
                return handleWorkoutRecord(state, event);
        }
    });
};

3. Trust System

export const computeTrainerTrust = (
    trainerId: Hexpubkey,
    state: WorkoutSessionState
) => {
    // Factors to consider:
    // - Number of users following
    // - Template usage count
    // - Verified credentials
    // - User ratings
};

2. NDK Core Components

Cache System (src/cache-adapter/)

SQLite Adapter (sqlite.ts)
  • Key Implementation:
export class NDKCacheAdapterSqlite implements NDKCacheAdapter {
    // Core caching functionality
    async setEvent(event: NDKEvent, filters: NDKFilter[], relay?: NDKRelay)
    async query(subscription: NDKSubscription)
    async fetchProfile(pubkey: Hexpubkey)
}
  • Notable Features:
    • LRU caching for profiles
    • Transaction support
    • Batch operation handling
    • Event deduplication
  • POWR Applications:
    • Workout template caching
    • Performance optimization
    • Offline data access
Migrations (migrations.ts)
  • Key Tables:
export const migrations = [{
    version: 0,
    up: async (db: SQLite.SQLiteDatabase) => {
        // Events table
        // Profiles table
        // Event tags table
        // Relay status table
    }
}];
  • POWR Adaptation Needed:
    • Add workout-specific tables
    • Template versioning
    • Exercise history tracking

2. Event Handling System

Subscription Hook (src/hooks/subscribe.ts)

  • Core Interface:
interface UseSubscribeParams {
    filters: NDKFilter[] | null;
    opts?: {
        wrap?: boolean;
        bufferMs?: number;
        includeMuted?: boolean;
    };
}
  • Key Features:
    • Event buffering system
    • Automatic deduplication
    • Muted user filtering
  • POWR Applications:
    • Real-time workout updates
    • Social feed implementation
    • Template sharing

Session Management (src/hooks/session.ts)

  • Key Functionality:
    • User authentication
    • Event caching
    • Profile management
  • Notable Methods:
useNDKSession() {
    // Session initialization
    // Wallet management
    // Event handling
}

3. Olas Implementation Patterns

State Management (stores/session/)

  • Core Store Structure:
export const useNDKSessionStore = create<SessionState>()((set, get) => ({
    follows: undefined,
    events: new Map(),
    muteList: new Set(),
    
    // Actions
    init: (ndk, user, settingsStore, opts, cb),
    addEvent: (event, onAdded),
    setEvents: (kind, events)
}));
  • Key Features:
    • Immutable state updates
    • Action composition
    • Event buffering
  • POWR Applications:
    • Workout state management
    • Progress tracking
    • Social interactions

Event Actions (stores/session/actions/)

  • Key Implementations:
    • addEvent.ts: Event processing and deduplication
    • init.ts: Session initialization and relay setup
    • setEvents.ts: Batch event updates
  • Notable Patterns:
export const addEvent = (event: NDKEvent, onAdded, set) => {
    set((state: SessionState) => {
        // Event processing
        // State updates
        // Callback handling
    });
};

UI Components (components/relays/)

  • Connectivity Indicator:
const CONNECTIVITY_STATUS_COLORS: Record<NDKRelayStatus, string> = {
    [NDKRelayStatus.CONNECTED]: '#66cc66',
    [NDKRelayStatus.DISCONNECTED]: '#aa4240',
    // ...
};
  • Usage in POWR:
    • Connection status visualization
    • Workout sync indicators
    • Real-time feedback

Files To Review Next

Priority 1

  1. NDK Provider Context:

    • src/providers/ndk/context.tsx
    • Implementation of NDK context
    • Provider patterns
  2. Database Utilities:

    • apps/mobile/utils/db.ts
    • Database operations
    • Sync logic

Priority 2

  1. Form Management:
    • apps/mobile/components/NewPost/store.ts
    • State management patterns
    • Form validation

Implementation Strategy for POWR

Phase 1: Core Data Layer

  1. Adapt NDK's SQLite adapter:
export class WorkoutCacheAdapter extends NDKCacheAdapterSqlite {
    // Add workout-specific methods
    async setWorkoutRecord(workout: NDKEvent): Promise<void>;
    async getWorkoutHistory(): Promise<NDKEvent[]>;
    async getTemplates(): Promise<NDKEvent[]>;
}

Phase 2: State Management

  1. Create workout store using Olas patterns:
export const useWorkoutStore = create<WorkoutState>((set, get) => ({
    activeWorkout: undefined,
    templates: new Map(),
    history: [],
    
    // Actions
    startWorkout: (template: NDKEvent) => {},
    recordSet: (exercise: NDKEvent, weight: number, reps: number) => {},
    completeWorkout: () => {}
}));

Phase 3: Event Handling

  1. Implement workout-specific subscriptions:
export const useWorkoutSubscribe = ({filters, opts}) => {
    return useSubscribe({
        filters,
        opts: {
            buffer: true,
            includeMuted: false
        }
    });
};

Would you like me to:

  1. Add analysis for any specific component?
  2. Create example implementations for POWR?
  3. Review additional files?