kalp_dlt_wallet 1.0.2 copy "kalp_dlt_wallet: ^1.0.2" to clipboard
kalp_dlt_wallet: ^1.0.2 copied to clipboard

A Flutter package for interacting with distributed ledger technology (DLT) through the Kalp wallet system.

example/lib/main.dart

import 'dart:developer';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:kalp_dlt_wallet/kalp_dlt_wallet.dart';

// Import method options
enum ImportMethod { seedWords, privateKey }

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Kalp DLT Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Kalp DLT Example'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final TextEditingController _apiKeyController = TextEditingController();
  late KalpDLTWallet kalpDlt;

  KalpWallet wallet = KalpWallet.empty();
  String? _seedWords;
  final TextEditingController _customSeedController = TextEditingController();
  final TextEditingController _privateKeyController = TextEditingController();
  bool _useCustomSeeds = false;
  ImportMethod _importMethod = ImportMethod.seedWords;

  // Added state variables to store operation results
  String? _readResult;
  String? _writeResult;
  String? _gasFeesResult;

  // Loading state variables
  bool _isGeneratingSeeds = false;
  bool _isCreatingWallet = false;
  bool _isImportingWallet = false;
  bool _isReading = false;
  bool _isWriting = false;
  bool _isLoadingGasFees = false;

  bool get _isApiKeyPresent => _apiKeyController.text.trim().isNotEmpty;

  final _nglChannleName = 'YourNGLChannelName';
  final _gatewayChannelName = 'YourGatewayChannelName';
  static final _nglBaseUrl = 'YourNGLBaseUrl';
  static final _gatewayBaseUrl = 'YourGatewayBaseUrl';

  @override
  void initState() {
    super.initState();
    // Initialize with empty API key initially
    kalpDlt = KalpDLTWallet.initialize(
      apiKey: '',
      nglBaseUrl: _nglBaseUrl,
      gatewayBaseUrl: _gatewayBaseUrl,
    );

    // Listen to changes in API key
    _apiKeyController.addListener(_updateKalpDLT);
  }

  void _updateKalpDLT() {
    kalpDlt = KalpDLTWallet.initialize(
      apiKey: _apiKeyController.text,
      nglBaseUrl: _nglBaseUrl,
      gatewayBaseUrl: _gatewayBaseUrl,
    );
  }

  @override
  void dispose() {
    _apiKeyController.removeListener(_updateKalpDLT);
    _apiKeyController.dispose();
    _customSeedController.dispose();
    _privateKeyController.dispose();
    super.dispose();
  }

  Future<void> _generateSeedWords() async {
    if (_isGeneratingSeeds || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isGeneratingSeeds = true;
    });

    try {
      await kalpDlt.createSeedWords();
      if (mounted) {
        setState(() {
          _seedWords = KalpDLTWallet.lastGeneratedSeeds;
        });
      }
    } catch (e) {
      if (mounted) {
        SnackBar snackBar = SnackBar(content: Text(e.toString()));
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
    } finally {
      if (mounted) {
        setState(() {
          _isGeneratingSeeds = false;
        });
      }
    }
  }

  Future<void> _createWallet() async {
    if (_isCreatingWallet || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isCreatingWallet = true;
    });

    try {
      await kalpDlt.createWalletWithSeedWords(
        channelName: _nglChannleName,
        seedWords: KalpDLTWallet.lastGeneratedSeeds?.split(' ') ?? [],
        errorCallback: (dynamic e) {
          setState(() {
            _isCreatingWallet = false;
          });
          String errorMessage = "";
          if (e is DioException && e.response != null) {
            errorMessage = e.response?.data['message'] ?? e.toString();
          } else {
            errorMessage = e.toString();
          }

          SnackBar snackBar = SnackBar(content: Text(errorMessage));
          ScaffoldMessenger.of(context).showSnackBar(snackBar);
        },
        callback: (data) async {
          setState(() {
            wallet = data;
            _isCreatingWallet = false;
          });

          log(data.toString());
        },
      );
    } catch (e) {
      setState(() {
        _isCreatingWallet = false;
      });
    }
  }

  Future<void> _importWallet() async {
    if (_isImportingWallet || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isImportingWallet = true;
    });

    try {
      if (_importMethod == ImportMethod.privateKey) {
        // Import using private key
        final privateKey = _privateKeyController.text.trim();
        if (privateKey.isEmpty) {
          if (mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Please enter a private key')),
            );
          }
          setState(() {
            _isImportingWallet = false;
          });
          return;
        }

        if (!KalpDLTWallet.isValidPrivateKey(privateKey)) {
          if (mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Invalid private key format')),
            );
          }
          setState(() {
            _isImportingWallet = false;
          });
          return;
        }

        await kalpDlt.importWalletWithPrivateKey(
          channelName: _nglChannleName,
          privateKey: privateKey,
          errorCallback: (dynamic e) {
            setState(() {
              _isImportingWallet = false;
            });
            String errorMessage = "";
            if (e is DioException && e.response != null) {
              errorMessage = e.response?.data['message'] ?? e.toString();
            } else {
              errorMessage = e.toString();
            }

            SnackBar snackBar = SnackBar(content: Text(errorMessage));
            ScaffoldMessenger.of(context).showSnackBar(snackBar);
          },
          callback: (data) async {
            setState(() {
              wallet = data;
              _isImportingWallet = false;
            });
            log(data.toString());
            if (mounted) {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(
                    content:
                        Text('Wallet imported successfully with private key!')),
              );
            }
          },
        );
      } else {
        // Import using seed words (existing functionality)
        final List<String> seedWords;
        if (_useCustomSeeds && _customSeedController.text.isNotEmpty) {
          seedWords = _customSeedController.text.trim().split(' ');
        } else {
          seedWords = KalpDLTWallet.lastGeneratedSeeds?.split(' ') ?? [];
        }

        if (seedWords.isEmpty) {
          if (mounted) {
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(
                  content: Text(
                      'No seed words available. Please generate or enter seeds.')),
            );
          }
          setState(() {
            _isImportingWallet = false;
          });
          return;
        }

        await kalpDlt.createWalletWithSeedWords(
          importWallet: true,
          channelName: _nglChannleName,
          seedWords: seedWords,
          errorCallback: (dynamic e) {
            setState(() {
              _isImportingWallet = false;
            });
            String errorMessage = "";
            if (e is DioException && e.response != null) {
              errorMessage = e.response?.data['isregistered'] ?? false
                  ? 'Wallet already registered'
                  : 'Wallet not registered';
            } else {
              errorMessage = e.toString();
            }

            SnackBar snackBar = SnackBar(content: Text(errorMessage));
            ScaffoldMessenger.of(context).showSnackBar(snackBar);
          },
          callback: (data) async {
            setState(() {
              wallet = data;
              _isImportingWallet = false;
            });
            log(data.toString());
            if (mounted) {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Wallet imported successfully!')),
              );
            }
          },
        );
      }
    } catch (e) {
      setState(() {
        _isImportingWallet = false;
      });
    }
  }

  Future<void> read() async {
    if (_isReading || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isReading = true;
    });

    try {
      final data = await kalpDlt.read(
          proposal: Proposal.empty().copyWith(
        walletAddress: wallet.enrollmentId,
        publicCertificate: wallet.publicCertificate,
        network: _gatewayChannelName,
        contractAddress: 'koot',
        functionName: 'GetBalance',
        functionParams: ['walletid355'],
      ));

      setState(() {
        _readResult = data.toString();
      });
    } catch (e) {
      if (mounted) {
        String errorMessage = "";
        if (e is DioException && e.response != null) {
          errorMessage = e.response?.data['message'].toString() ?? e.toString();
        } else {
          errorMessage = e.toString();
        }
        SnackBar snackBar = SnackBar(content: Text(errorMessage));
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
    } finally {
      if (mounted) {
        setState(() {
          _isReading = false;
        });
      }
    }
  }

  Future<void> write() async {
    if (_isWriting || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isWriting = true;
    });

    try {
      final data = await kalpDlt.write(
          proposal: Proposal.empty().copyWith(
        walletAddress: wallet.enrollmentId,
        publicCertificate: wallet.publicCertificate,
        network: _gatewayChannelName,
        contractAddress: 'koot',
        functionName: 'GetBalance',
        functionParams: ['walletid355'],
      ));
      setState(() {
        _writeResult = data.toString();
      });
    } catch (e) {
      if (mounted) {
        String errorMessage = "";
        if (e is DioException && e.response != null) {
          errorMessage = e.response?.data['message'].toString() ?? e.toString();
        } else {
          errorMessage = e.toString();
        }
        SnackBar snackBar = SnackBar(content: Text(errorMessage));
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
    } finally {
      if (mounted) {
        setState(() {
          _isWriting = false;
        });
      }
    }
  }

  Future<void> getGasFees() async {
    if (_isLoadingGasFees || !_isApiKeyPresent) {
      if (!_isApiKeyPresent) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Please enter an API key first')),
        );
      }
      return;
    }

    setState(() {
      _isLoadingGasFees = true;
    });

    try {
      final data = await kalpDlt.gasFees(
          proposal: Proposal.empty().copyWith(
        walletAddress: wallet.enrollmentId,
        publicCertificate: wallet.publicCertificate,
        network: _gatewayChannelName,
        contractAddress: 'klp-fbeadf7d20-cc',
        functionName: 'GetGasFees',
        functionParams: [],
      ));
      setState(() {
        _gasFeesResult = data.toString();
      });
    } catch (e) {
      if (mounted) {
        String errorMessage = "";
        if (e is DioException && e.response != null) {
          errorMessage = e.response?.data['message'].toString() ?? e.toString();
        } else {
          errorMessage = e.toString();
        }
        SnackBar snackBar = SnackBar(content: Text(errorMessage));
        ScaffoldMessenger.of(context).showSnackBar(snackBar);
      }
    } finally {
      if (mounted) {
        setState(() {
          _isLoadingGasFees = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: <Widget>[
              // API Key input field
              TextField(
                controller: _apiKeyController,
                decoration: const InputDecoration(
                  labelText: 'API Key',
                  border: OutlineInputBorder(),
                ),
                onChanged: (value) {
                  setState(() {
                    _updateKalpDLT();
                  });
                },
              ),
              const SizedBox(height: 20),
              // Generate seed words section
              ElevatedButton(
                onPressed: _isGeneratingSeeds ? null : _generateSeedWords,
                child: _isGeneratingSeeds
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Generating...'),
                        ],
                      )
                    : const Text('Generate Seed Words'),
              ),

              if (_seedWords != null) ...[
                const SizedBox(height: 10),
                const Text('Generated Seed Words:'),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    _seedWords!,
                    textAlign: TextAlign.center,
                    style: const TextStyle(fontWeight: FontWeight.bold),
                  ),
                ),
              ],

              // Display wallet information when available
              if (wallet != KalpWallet.empty()) ...[
                const SizedBox(height: 20),
                const Divider(),
                const SizedBox(height: 10),
                const Text('Wallet Information',
                    style:
                        TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                const SizedBox(height: 10),
                Card(
                  elevation: 2,
                  child: Padding(
                    padding: const EdgeInsets.all(12.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        _buildWalletInfoRow(
                            'Enrollment ID', wallet.enrollmentId),
                        const Divider(),
                        const Text('Public Certificate:'),
                        Container(
                          height: 100,
                          margin: const EdgeInsets.only(top: 5),
                          padding: const EdgeInsets.all(8),
                          decoration: BoxDecoration(
                            color: Colors.grey[200],
                            borderRadius: BorderRadius.circular(4),
                          ),
                          child: SingleChildScrollView(
                            child: Text(
                              wallet.publicCertificate.length > 100
                                  ? '${wallet.publicCertificate.substring(0, 100)}...'
                                  : wallet.publicCertificate,
                              style: const TextStyle(fontSize: 12),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],

              const SizedBox(height: 20),
              const Divider(),

              // Import wallet section with seed options
              const SizedBox(height: 10),
              const Text('Import Wallet',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),

              // Radio buttons for import method
              Column(
                children: [
                  RadioListTile<ImportMethod>(
                    title: const Text('Import with seed words'),
                    value: ImportMethod.seedWords,
                    groupValue: _importMethod,
                    onChanged: (ImportMethod? value) {
                      setState(() {
                        _importMethod = value!;
                      });
                    },
                  ),
                  RadioListTile<ImportMethod>(
                    title: const Text('Import with private key'),
                    value: ImportMethod.privateKey,
                    groupValue: _importMethod,
                    onChanged: (ImportMethod? value) {
                      setState(() {
                        _importMethod = value!;
                        if (value == ImportMethod.privateKey) {
                          _useCustomSeeds =
                              false; // Disable custom seeds when using private key
                        }
                      });
                    },
                  ),
                ],
              ),

              if (_importMethod == ImportMethod.seedWords) ...[
                // Toggle for seed source
                Row(
                  children: [
                    Switch(
                      value: _useCustomSeeds,
                      onChanged: (value) {
                        setState(() {
                          _useCustomSeeds = value;
                        });
                      },
                    ),
                    Text(_useCustomSeeds
                        ? 'Using custom seeds'
                        : 'Using generated seeds'),
                  ],
                ),

                // Custom seed input field (visible only when toggle is on)
                if (_useCustomSeeds) ...[
                  const SizedBox(height: 10),
                  TextField(
                    controller: _customSeedController,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                      labelText: 'Enter seed words',
                      hintText: 'Separate words with spaces',
                    ),
                    maxLines: 3,
                  ),
                ],
              ],

              // Private key input field (visible only when private key toggle is on)
              if (_importMethod == ImportMethod.privateKey) ...[
                const SizedBox(height: 10),
                TextField(
                  controller: _privateKeyController,
                  decoration: const InputDecoration(
                    border: OutlineInputBorder(),
                    labelText: 'Enter private key',
                    hintText: 'Enter your private key (hex or PEM format)',
                  ),
                  maxLines: 3,
                ),
              ],

              const SizedBox(height: 10),
              ElevatedButton(
                onPressed: _isImportingWallet ? null : _importWallet,
                child: _isImportingWallet
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Importing...'),
                        ],
                      )
                    : const Text('Import Wallet'),
              ),

              const SizedBox(height: 20),
              const Divider(),

              // Other wallet operations
              const SizedBox(height: 10),
              const Text('Wallet Operations',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
              const SizedBox(height: 10),

              ElevatedButton(
                onPressed: _isCreatingWallet ? null : _createWallet,
                child: _isCreatingWallet
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Creating...'),
                        ],
                      )
                    : const Text('Create New Wallet'),
              ),

              ElevatedButton(
                onPressed: _isReading ? null : read,
                child: _isReading
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Reading...'),
                        ],
                      )
                    : const Text('Read'),
              ),

              ElevatedButton(
                onPressed: _isWriting ? null : write,
                child: _isWriting
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Writing...'),
                        ],
                      )
                    : const Text('Write'),
              ),

              ElevatedButton(
                onPressed: _isLoadingGasFees ? null : getGasFees,
                child: _isLoadingGasFees
                    ? const Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                            ),
                          ),
                          SizedBox(width: 10),
                          Text('Loading Gas Fees...'),
                        ],
                      )
                    : const Text('Gas Fees'),
              ),

              // Display results
              if (_readResult != null) ...[
                const SizedBox(height: 20),
                const Text('Read Result:',
                    style:
                        TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                Text(_readResult!),
              ],
              if (_writeResult != null) ...[
                const SizedBox(height: 20),
                const Text('Write Result:',
                    style:
                        TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                Text(_writeResult!),
              ],
              if (_gasFeesResult != null) ...[
                const SizedBox(height: 20),
                const Text('Gas Fees Result:',
                    style:
                        TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                Text(_gasFeesResult!),
              ],
            ],
          ),
        ),
      ),
    );
  }

  // Helper method to build wallet information rows
  Widget _buildWalletInfoRow(String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4.0),
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          SizedBox(
            width: 120,
            child: Text(
              label,
              style: const TextStyle(fontWeight: FontWeight.bold),
            ),
          ),
          Expanded(
            child: GestureDetector(
              onTap: () async {
                await Clipboard.setData(
                  ClipboardData(text: value),
                );
              },
              child: Text(
                value,
                style: const TextStyle(
                  fontFamily: 'monospace',
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}
2
likes
120
points
54
downloads

Publisher

verified publisherkalp.studio

Weekly Downloads

A Flutter package for interacting with distributed ledger technology (DLT) through the Kalp wallet system.

Topics

#blockchain #wallet #kalpdlt

Documentation

API reference

License

MIT (license)

Dependencies

basic_utils, bip39_mnemonic, dio, flutter, freezed_annotation, json_annotation, meta, path_provider, pointycastle, webview_flutter

More

Packages that depend on kalp_dlt_wallet