diff --git a/packages/komodo_defi_framework/app_build/build_config.json b/packages/komodo_defi_framework/app_build/build_config.json index b3b5511..a7839b1 100644 --- a/packages/komodo_defi_framework/app_build/build_config.json +++ b/packages/komodo_defi_framework/app_build/build_config.json @@ -28,7 +28,7 @@ "coins": { "fetch_at_build_enabled": true, "update_commit_on_build": true, - "bundled_coins_repo_commit": "5e12a42ea95f8f50667291c7adae881eef513bf0", + "bundled_coins_repo_commit": "d7906da4ab0283ea7dcd22d8b5157a8a46eac0f2", "coins_repo_api_url": "https://api.github.com/repos/KomodoPlatform/coins", "coins_repo_content_url": "https://komodoplatform.github.io/coins", "coins_repo_branch": "master", diff --git a/packages/komodo_defi_sdk/example/lib/main.dart b/packages/komodo_defi_sdk/example/lib/main.dart index 9423129..0a74c63 100644 --- a/packages/komodo_defi_sdk/example/lib/main.dart +++ b/packages/komodo_defi_sdk/example/lib/main.dart @@ -159,10 +159,20 @@ class _KomodoAppState extends State { }); } on AuthException catch (e) { setState(() { + _scaffoldKey.currentState?.showSnackBar( + SnackBar( + content: Text('Auth Error: (${e.type}) ${e.message}'), + ), + ); _statusMessage = 'Auth Error: (${e.type}) ${e.message}'; }); } catch (e) { setState(() { + _scaffoldKey.currentState?.showSnackBar( + SnackBar( + content: Text('An unexpected error occurred: $e'), + ), + ); _statusMessage = 'An unexpected error occurred: $e'; }); } @@ -254,11 +264,11 @@ class _KomodoAppState extends State { TextFormField( controller: _walletNameController, decoration: const InputDecoration(labelText: 'Wallet Name'), - validator: notEmptyValidator, + validator: passwordValidator, ), TextFormField( controller: _passwordController, - validator: notEmptyValidator, + validator: passwordValidator, decoration: InputDecoration( labelText: 'Password', suffixIcon: IconButton( @@ -723,10 +733,15 @@ class _KomodoAppState extends State { ); } - String? notEmptyValidator(String? input, {String? fieldName}) { + String? passwordValidator(String? input, {String? fieldName}) { if (input == null || input.isEmpty) { return 'Please enter a ${fieldName ?? 'value'}.'; } + + if (input.contains(RegExp('[<>&]'))) { + return "Invalid password: contains '<', '>', or '&'"; + } + return null; } diff --git a/packages/komodo_defi_sdk/example/web/kdf/res/kdf_wrapper.dart b/packages/komodo_defi_sdk/example/web/kdf/res/kdf_wrapper.dart index 1acf13e..b6793c4 100644 --- a/packages/komodo_defi_sdk/example/web/kdf/res/kdf_wrapper.dart +++ b/packages/komodo_defi_sdk/example/web/kdf/res/kdf_wrapper.dart @@ -3,11 +3,12 @@ import 'dart:async'; // This is a web-specific file, so it's safe to ignore this warning // ignore: avoid_web_libraries_in_flutter -import 'dart:js' as js; +import 'dart:js_interop'; +import 'dart:js_interop_unsafe'; import 'package:flutter/services.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart'; -import 'package:js/js_util.dart'; +import 'package:web/web.dart'; class KdfPlugin { static void registerWith(Registrar registrar) { @@ -57,38 +58,57 @@ class KdfPlugin { final completer = Completer(); - final script = - js.context['document'].callMethod('createElement', ['script']); - script['src'] = 'kdf/kdflib.js'; - script['onload'] = js.allowInterop(() { - _libraryLoaded = true; - completer.complete(); - }); - script['onerror'] = js.allowInterop((event) { - completer.completeError('Failed to load kdflib.js'); - }); + final script = (document.createElement('script') as HTMLScriptElement) + ..src = 'kdf/kdflib.js' + ..onload = () { + _libraryLoaded = true; + completer.complete(); + }.toJS + ..onerror = (event) { + completer.completeError('Failed to load kdflib.js'); + }.toJS; - js.context['document']['head'].callMethod('appendChild', [script]); + document.head!.appendChild(script); return completer.future; } Future _mm2Main(String conf, Function logCallback) async { await _ensureLoaded(); - return dartify( - js.context.callMethod('mm2_main', [conf, js.allowInterop(logCallback)]), - )! as int; + + try { + final jsCallback = logCallback.toJS; + final jsResponse = globalContext.callMethod( + 'mm2_main'.toJS, + [conf.toJS, jsCallback].toJS, + ); + if (jsResponse == null) { + throw Exception('mm2_main call returned null'); + } + + final dynamic dartResponse = (jsResponse as JSAny?).dartify(); + if (dartResponse == null) { + throw Exception('Failed to convert mm2_main response to Dart'); + } + + return dartResponse as int; + } catch (e) { + throw Exception('Error in mm2_main: $e\nConfig: $conf'); + } } int _mm2MainStatus() { if (!_libraryLoaded) { throw StateError('KDF library not loaded. Call ensureLoaded() first.'); } - return js.context.callMethod('mm2_main_status') as int; + + final jsResult = globalContext.callMethod('mm2_main_status'.toJS); + return jsResult.dartify()! as int; } Future _mm2Stop() async { await _ensureLoaded(); - return js.context.callMethod('mm2_stop') as int; + final jsResult = globalContext.callMethod('mm2_stop'.toJS); + return jsResult.dartify()! as int; } } diff --git a/packages/komodo_defi_types/lib/src/cryptography/mnemonic.dart b/packages/komodo_defi_types/lib/src/cryptography/mnemonic.dart index dbeb550..24e0352 100644 --- a/packages/komodo_defi_types/lib/src/cryptography/mnemonic.dart +++ b/packages/komodo_defi_types/lib/src/cryptography/mnemonic.dart @@ -84,18 +84,14 @@ class EncryptedMnemonicData { // Factory method to create EncryptedMnemonicData from JSON factory EncryptedMnemonicData.fromJson(Map json) { - final encryptedData = - json.valueOrNull('encrypted_mnemonic_data') ?? - (throw ArgumentError('Invalid encrypted mnemonic data')); - return EncryptedMnemonicData( - encryptionAlgorithm: encryptedData.value('encryption_algorithm'), + encryptionAlgorithm: json.value('encryption_algorithm'), keyDerivationDetails: Argon2Details.fromJson( - encryptedData.value('key_derivation_details'), + json.value('key_derivation_details'), ), - iv: encryptedData.value('iv'), - ciphertext: encryptedData.value('ciphertext'), - tag: encryptedData.value('tag'), + iv: json.value('iv'), + ciphertext: json.value('ciphertext'), + tag: json.value('tag'), ); } @@ -160,15 +156,21 @@ class Argon2Details { // Factory method to create Argon2Details from JSON factory Argon2Details.fromJson(Map json) { - // final argon2Params = json.value('Argon2', 'params'); + var argon2Params = json; + var argon2Salt = json; + if (json['Argon2'] != null) { + argon2Params = json.value('Argon2', 'params'); + argon2Salt = json.value('Argon2'); + } + return Argon2Details( - algorithm: json.value('algorithm'), - version: int.parse(json['version'].toString()), - mCost: json.value('m_cost'), - tCost: json.value('t_cost'), - pCost: json.value('p_cost'), - saltAes: json.value('salt_aes'), - saltHmac: json.value('salt_hmac'), + algorithm: argon2Params.value('algorithm'), + version: int.parse(argon2Params['version'].toString()), + mCost: argon2Params.value('m_cost'), + tCost: argon2Params.value('t_cost'), + pCost: argon2Params.value('p_cost'), + saltAes: argon2Salt.value('salt_aes'), + saltHmac: argon2Salt.value('salt_hmac'), ); }