komodo_defi_sdk 0.3.0+0 copy "komodo_defi_sdk: ^0.3.0+0" to clipboard
komodo_defi_sdk: ^0.3.0+0 copied to clipboard

A high-level opinionated library that provides a simple way to build cross-platform Komodo Defi Framework applications (primarily focused on wallets). This package seves as the entry point for the pac [...]

example/lib/main.dart

// lib/main.dart
import 'dart:async';

import 'package:dragon_logs/dragon_logs.dart' as dragon;
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kdf_sdk_example/blocs/auth/auth_bloc.dart';
import 'package:kdf_sdk_example/screens/asset_page.dart';
import 'package:kdf_sdk_example/widgets/instance_manager/instance_view.dart';
import 'package:kdf_sdk_example/widgets/instance_manager/kdf_instance_drawer.dart';
import 'package:kdf_sdk_example/widgets/instance_manager/kdf_instance_state.dart';
import 'package:komodo_cex_market_data/komodo_cex_market_data.dart'
    show sparklineRepository;
import 'package:komodo_defi_sdk/komodo_defi_sdk.dart';
import 'package:komodo_defi_types/komodo_defi_types.dart';

final GlobalKey<ScaffoldMessengerState> _scaffoldKey =
    GlobalKey<ScaffoldMessengerState>();
final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dragon.DragonLogs.init();

  // Create instance manager
  final instanceManager = KdfInstanceManager();

  // Create default SDK instance with config
  final defaultSdk = KomodoDefiSdk(config: _config);
  await defaultSdk.initialize();
  dragon.log('Default SDK instance initialized');

  unawaited(
    sparklineRepository.init().catchError((
      Object? error,
      StackTrace? stackTrace,
    ) {
      dragon.log('Error during sparklineRepository initialization: $error');
      debugPrintStack(stackTrace: stackTrace);
    }),
  );

  // Register default instance
  await instanceManager.registerInstance('Local Instance', _config, defaultSdk);
  dragon.log('Registered default instance');

  runApp(
    MultiRepositoryProvider(
      providers: [RepositoryProvider<KomodoDefiSdk>.value(value: defaultSdk)],
      child: KdfInstanceManagerProvider(
        notifier: instanceManager,
        child: MaterialApp(
          scaffoldMessengerKey: _scaffoldKey,
          navigatorKey: _navigatorKey,
          theme: ThemeData(colorSchemeSeed: Colors.blue, useMaterial3: true),
          darkTheme: ThemeData(
            colorSchemeSeed: Colors.blue,
            useMaterial3: true,
            brightness: Brightness.dark,
          ),
          home: const KomodoApp(),
        ),
      ),
    ),
  );
}

// Default SDK configuration
const KomodoDefiSdkConfig _config = KomodoDefiSdkConfig();

class KomodoApp extends StatefulWidget {
  const KomodoApp({super.key});

  @override
  State<KomodoApp> createState() => _KomodoAppState();
}

class _KomodoAppState extends State<KomodoApp> {
  // Instance-specific state management
  final Map<String, InstanceState> _instanceStates = {};
  final Map<String, KdfUser?> _currentUsers = {};
  final Map<String, String> _statusMessages = {};
  int _selectedInstanceIndex = 0;

  // Form controllers and state
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final TextEditingController _searchController = TextEditingController();
  List<Asset> _filteredAssets = [];
  Map<AssetId, Asset>? _allAssets;
  bool _initialized = false;

  @override
  void initState() {
    super.initState();
    _searchController.addListener(_filterAssets);
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    if (!_initialized) {
      _initializeInstances();
      _initialized = true;
    }
  }

  Future<void> _initializeInstances() async {
    final manager = KdfInstanceManagerProvider.of(context);

    // Initialize state for each instance
    for (final instance in manager.instances.values) {
      await _initializeInstance(instance);
    }
  }

  Future<void> _initializeInstance(KdfInstanceState instance) async {
    _getOrCreateInstanceState(instance.name);

    // Initialize assets
    _allAssets = instance.sdk.assets.available;
    _filterAssets();

    // Initialize auth state
    final user = await instance.sdk.auth.currentUser;
    _updateInstanceUser(instance.name, user);

    // Setup auth state listener
    instance.sdk.auth.authStateChanges.listen((user) {
      _updateInstanceUser(instance.name, user);
    });

    // Load known users
    await _fetchKnownUsers(instance);
    dragon.log('Initialized instance ${instance.name}');
  }

  void _updateInstanceUser(String instanceName, KdfUser? user) {
    setState(() {
      _currentUsers[instanceName] = user;
      _statusMessages[instanceName] =
          user != null
              ? 'Current wallet: ${user.walletId.name}'
              : 'Not signed in';
    });
    dragon.DragonLogs.setSessionMetadata({
      'instance': instanceName,
      if (user != null) 'user': user.walletId.compoundId,
    });
    dragon.log(
      user != null
          ? 'User ${user.walletId.compoundId} authenticated in $instanceName'
          : 'User signed out of $instanceName',
    );
  }

  Future<void> _fetchKnownUsers(KdfInstanceState instance) async {
    try {
      await instance.sdk.ensureInitialized();
      final users = await instance.sdk.auth.getUsers();
      final state = _getOrCreateInstanceState(instance.name);
      state.knownUsers = users;
      setState(() {});
    } catch (e, s) {
      dragon.log('Error fetching known users: $e', 'ERROR');
      debugPrintStack(stackTrace: s);
    }
  }

  void _filterAssets() {
    final query = _searchController.text.toLowerCase();
    final assets = _allAssets;
    if (assets == null) return;

    setState(() {
      _filteredAssets =
          assets.values.where((v) {
            final asset = v.id.name;
            final id = v.id.id;
            return asset.toLowerCase().contains(query) ||
                id.toLowerCase().contains(query);
          }).toList();
    });
  }

  InstanceState _getOrCreateInstanceState(String instanceName) {
    return _instanceStates.putIfAbsent(instanceName, InstanceState.new);
  }

  @override
  Widget build(BuildContext context) {
    final manager = KdfInstanceManagerProvider.of(context);
    final instances = manager.instances.values.toList();

    return Scaffold(
      drawer: const KdfInstanceDrawer(),
      appBar: AppBar(
        title: Text(
          instances.isEmpty
              ? 'KDF Demo'
              : 'KDF Demo - ${instances[_selectedInstanceIndex].name}',
        ),
        actions: [
          if (instances.isNotEmpty) ...[
            Badge(
              backgroundColor:
                  instances[_selectedInstanceIndex].isConnected
                      ? Colors.green
                      : Colors.red,
              child: const Icon(Icons.cloud),
            ),
            IconButton(
              icon: const Icon(Icons.download),
              tooltip: 'Export Logs',
              onPressed: () async {
                await dragon.DragonLogs.exportLogsToDownload();
                _scaffoldKey.currentState?.showSnackBar(
                  const SnackBar(content: Text('Logs exported')),
                );
              },
            ),
            const SizedBox(width: 16),
          ],
        ],
      ),
      body:
          instances.isEmpty
              ? const Center(child: Text('No KDF instances configured'))
              : IndexedStack(
                index: _selectedInstanceIndex,
                children: [
                  for (final instance in instances)
                    Padding(
                      padding: const EdgeInsets.all(16),
                      child: BlocProvider(
                        create: (context) => AuthBloc(sdk: instance.sdk),
                        child: BlocListener<AuthBloc, AuthState>(
                          listener: (context, state) {
                            final user =
                                state.isAuthenticated ? state.user : null;
                            _updateInstanceUser(instance.name, user);
                          },
                          child: Form(
                            key: _formKey,
                            autovalidateMode:
                                AutovalidateMode.onUserInteraction,
                            child: InstanceView(
                              instance: instance,
                              state: 'active',
                              statusMessage:
                                  _statusMessages[instance.name] ??
                                  'Not initialized',
                              searchController: _searchController,
                              filteredAssets: _filteredAssets,
                              onNavigateToAsset:
                                  (asset) =>
                                      _onNavigateToAsset(instance, asset),
                            ),
                          ),
                        ),
                      ),
                    ),
                ],
              ),
      bottomNavigationBar: _buildInstanceNavigator(instances),
    );
  }

  Widget _buildInstanceNavigator(List<KdfInstanceState> instances) {
    if (instances.length <= 1) return const SizedBox.shrink();

    return NavigationBar(
      selectedIndex: _selectedInstanceIndex,
      onDestinationSelected: (index) {
        setState(() => _selectedInstanceIndex = index);
      },
      destinations: [
        for (final instance in instances)
          NavigationDestination(
            icon: Badge(
              backgroundColor: instance.isConnected ? Colors.green : Colors.red,
              child: const Icon(Icons.cloud),
            ),
            label: instance.name,
          ),
      ],
    );
  }

  void _onNavigateToAsset(KdfInstanceState instance, Asset asset) {
    _navigatorKey.currentState?.push(
      MaterialPageRoute<void>(builder: (context) => AssetPage(asset)),
    );
  }

  @override
  void dispose() {
    _searchController.dispose();
    for (final state in _instanceStates.values) {
      state.dispose();
    }
    _instanceStates.clear();
    super.dispose();
  }
}

abstract class InstanceData {
  // Base interface for instance-specific data
}

class InstanceState extends InstanceData {
  final walletNameController = TextEditingController();
  final passwordController = TextEditingController();
  List<KdfUser> knownUsers = [];
  bool isHdMode = true;
  bool obscurePassword = true;

  void dispose() {
    walletNameController.dispose();
    passwordController.dispose();
  }
}
8
likes
0
points
0
downloads

Publisher

verified publisherkomodoplatform.com

Weekly Downloads

A high-level opinionated library that provides a simple way to build cross-platform Komodo Defi Framework applications (primarily focused on wallets). This package seves as the entry point for the packages in this repository.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

collection, decimal, flutter, flutter_secure_storage, get_it, http, komodo_cex_market_data, komodo_coins, komodo_defi_framework, komodo_defi_local_auth, komodo_defi_rpc_methods, komodo_defi_types, komodo_ui, logging, mutex, provider, shared_preferences

More

Packages that depend on komodo_defi_sdk