diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 2140bca42b3675b554a4fac5071c08606b0d5312..b0b9696f9e75f7b81c1c654cd613bdda917d2aaf 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -10,7 +10,6 @@
     <uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
 
     <application
-        android:preserveLegacyExternalStorage="true"
         android:requestLegacyExternalStorage="true"
         android:icon="@mipmap/ic_launcher"
         android:label="Ginkgo">
diff --git a/assets/translations/en.json b/assets/translations/en.json
index c32f7cfad8db8fe9dc4208536c41f41175b8ca41..2c8e6d2adbf8edf15d3cbc12965f54f4f8462ea8 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -124,5 +124,6 @@
   "error_installing_desktop": "Error installing Äž1nkgo in your Desktop: (error: {error})",
   "install_desktop": "Install Äž1nkgo in Desktop",
   "import_failed": "Wallet import failed",
-  "select_file_to_import": "Select the wallet backup"
+  "select_file_to_import": "Select the wallet backup",
+  "You can't send money to yourself.": "You can't send money to yourself."
 }
diff --git a/assets/translations/es.json b/assets/translations/es.json
index 46a179451d4bd2ba658e801060e3305ad7611a35..dff193b89bd031e9babc20067b566453b26ca3db 100644
--- a/assets/translations/es.json
+++ b/assets/translations/es.json
@@ -31,11 +31,11 @@
   "no_internet": "Sin conexión a internet",
   "skip": "Omitir",
   "start": "Comenzar",
-  "offline": "¡Está desconectad@!",
+  "offline": "¡Estás desconectad@!",
   "online_terminal": "En línea",
   "offline_terminal": "Fuera de línea",
-  "show_qr_to_client": "Muestre su clave pública a su clientæ",
-  "show_qr_to_client_amount": "Muestre este QR con esa cantidad a otro monedero Äž1nkgo",
+  "show_qr_to_client": "Muestra su clave pública a su clientæ",
+  "show_qr_to_client_amount": "Muestra este QR con esa cantidad a otro monedero Äž1nkgo",
   "keys_tooltip": "Las claves públicas y privadas en Ğ1 y Duniter son como un sistema de cerradura y llave, donde la clave pública actúa como la cerradura que puede ser abierta por cualquiera que tenga la clave privada correspondiente, proporcionando una forma segura de autenticar y verificar transacciones",
   "card_validity": "Validez",
   "card_validity_tooltip": "Tenga en cuenta que este monedero solo es accesible mientras utiliza este navegador y este dispositivo específico. Si borra o restablece el navegador, perderá el acceso a este monedero y los fondos almacenados en el.",
@@ -124,5 +124,6 @@
   "error_installing_desktop": "Error al instalar Äž1nkgo en Desktop (error: {error})",
   "install_desktop": "Instalar Äž1nkgo en tu Desktop",
   "import_failed": "Error al importar monedero",
-  "select_file_to_import": "Selecciona el monedero guadado"
+  "select_file_to_import": "Selecciona el monedero guadado",
+  "You can't send money to yourself.": "No puedes enviarte dinero a ti mismo/a."
 }
diff --git a/lib/g1/api.dart b/lib/g1/api.dart
index 9b113e6892c1bfb26d3b497c6c8d1e44a5d62c8a..e57ee5b5ff98e83417ce636742140e367aa2d57b 100644
--- a/lib/g1/api.dart
+++ b/lib/g1/api.dart
@@ -544,8 +544,9 @@ Future<T?> gvaFunctionWrapper<T>(
         final T? result = await specificFunction(gva);
         return result;
       }
-    } catch (e, stacktrace) {
-      await Sentry.captureException(e, stackTrace: stacktrace);
+    } catch (e) {
+      await Sentry.captureMessage(
+          'Error trying to use gva node ${node.url} $e');
       logger('Error trying ${node.url} $e');
       logger('Increasing node errors of ${node.url} (${node.errors})');
       NodeManager()
diff --git a/lib/g1/transaction_parser.dart b/lib/g1/transaction_parser.dart
index 660397144c236c704af6a561d34bb54260448678..656f208b8a5da88025b1cc1446004749d8a12587 100644
--- a/lib/g1/transaction_parser.dart
+++ b/lib/g1/transaction_parser.dart
@@ -33,7 +33,7 @@ TransactionsAndBalanceState transactionParser(String txData) {
       balance = balance -= amount;
     }
     final DateTime txDate =
-        DateTime.fromMillisecondsSinceEpoch(timestamp * 1000);
+        DateTime.fromMillisecondsSinceEpoch(timestamp * 1000, isUtc: true);
     /* if (!kReleaseMode) {
       logger('Timestamp: $timestamp');
       logger('Fecha: $txDate');
diff --git a/lib/ui/contacts_cache.dart b/lib/ui/contacts_cache.dart
index 8683fc145c0e907a88d7661471f94c61249d3b12..8837f5a87a6bdff90a1c94450297fea5852b9ae1 100644
--- a/lib/ui/contacts_cache.dart
+++ b/lib/ui/contacts_cache.dart
@@ -1,4 +1,5 @@
 import 'dart:async';
+import 'dart:collection';
 import 'dart:convert';
 import 'dart:io';
 
@@ -22,13 +23,18 @@ class ContactsCache {
   Box<dynamic>? _box;
 
   Future<void> init() async {
-    if (kIsWeb) {
-      _box = await Hive.openBox(_boxName);
-    } else {
-      final Directory appDocDir = await getApplicationDocumentsDirectory();
-      final String appDocPath = appDocDir.path;
-      _box = await Hive.openBox(_boxName, path: appDocPath);
+    try {
+      if (kIsWeb) {
+        _box = await Hive.openBox(_boxName);
+      } else {
+        final Directory appDocDir = await getApplicationDocumentsDirectory();
+        final String appDocPath = appDocDir.path;
+        _box = await Hive.openBox(_boxName, path: appDocPath);
+      }
+    } catch (e) {
+      logger('Error opening Hive: $e');
     }
+    _box ??= _MemoryFallbackBox<Contact>();
   }
 
   Future<void> dispose() async {
@@ -37,9 +43,9 @@ class ContactsCache {
 
   static ContactsCache? _instance;
   final Map<String, List<Completer<Contact>>> _pendingRequests =
-      <String, List<Completer<Contact>>>{};
+  <String, List<Completer<Contact>>>{};
   static Duration duration =
-      kReleaseMode ? const Duration(days: 3) : const Duration(hours: 5);
+  kReleaseMode ? const Duration(days: 3) : const Duration(hours: 5);
 
   final String _boxName = 'contacts_cache';
 
@@ -135,9 +141,9 @@ class ContactsCache {
 
     if (record != null) {
       final Map<String, dynamic> typedRecord =
-          Map<String, dynamic>.from(record as Map<dynamic, dynamic>);
+      Map<String, dynamic>.from(record as Map<dynamic, dynamic>);
       final DateTime timestamp =
-          DateTime.parse(typedRecord['timestamp'] as String);
+      DateTime.parse(typedRecord['timestamp'] as String);
       final bool before = DateTime.now().isBefore(timestamp.add(duration));
       if (before) {
         final Contact contact = Contact.fromJson(
@@ -148,3 +154,147 @@ class ContactsCache {
     return null;
   }
 }
+
+class _MemoryFallbackBox<E> extends Box<E> {
+  final Map<String, dynamic> _storage = HashMap<String, dynamic>();
+
+  @override
+  String get name => '_memory_fallback_box';
+
+  @override
+  bool get isOpen => true;
+
+  @override
+  String? get path => null;
+
+  @override
+  bool get lazy => false;
+
+  @override
+  Iterable<dynamic> get keys => _storage.keys;
+
+  @override
+  int get length => _storage.length;
+
+  @override
+  bool get isEmpty => _storage.isEmpty;
+
+  @override
+  bool get isNotEmpty => _storage.isNotEmpty;
+
+  @override
+  dynamic keyAt(int index) {
+    return _storage.keys.elementAt(index);
+  }
+
+  @override
+  Stream<BoxEvent> watch({dynamic key}) {
+    throw UnimplementedError('watch() is not supported in _MemoryFallbackBox');
+  }
+
+  @override
+  bool containsKey(dynamic key) {
+    return _storage.containsKey(key);
+  }
+
+  @override
+  Future<void> put(dynamic key, E value) async {
+    _storage[key as String] = value;
+  }
+
+  @override
+  Future<void> putAt(int index, E value) async {
+    _storage[_storage.keys.elementAt(index)] = value;
+  }
+
+  @override
+  Future<void> putAll(Map<dynamic, E> entries) async {
+    _storage.addAll(entries as Map<String, dynamic>);
+  }
+
+  @override
+  Future<int> add(E value) async {
+    throw UnimplementedError('add() is not supported in _MemoryFallbackBox');
+  }
+
+  @override
+  Future<Iterable<int>> addAll(Iterable<E> values) async {
+    throw UnimplementedError('addAll() is not supported in _MemoryFallbackBox');
+  }
+
+  @override
+  Future<void> delete(dynamic key) async {
+    _storage.remove(key);
+  }
+
+  @override
+  Future<void> deleteAt(int index) async {
+    _storage.remove(_storage.keys.elementAt(index));
+  }
+
+  @override
+  Future<void> deleteAll(Iterable<dynamic> keys) async {
+    // ignore: prefer_foreach
+    for (final dynamic key in keys) {
+      _storage.remove(key);
+    }
+  }
+
+  @override
+  Future<void> compact() async {}
+
+  @override
+  Future<int> clear() async {
+    final int count = _storage.length;
+    _storage.clear();
+    return count;
+  }
+
+  @override
+  Future<void> close() async {}
+
+  @override
+  Future<void> deleteFromDisk() async {}
+
+  @override
+  Future<void> flush() async {}
+
+  @override
+  E? get(dynamic key, {E? defaultValue}) {
+    return _storage.containsKey(key) ? _storage[key] as E : defaultValue;
+  }
+
+  @override
+  E? getAt(int index) {
+    return _storage.values.elementAt(index) as E?;
+  }
+
+  @override
+  Map<dynamic, E> toMap() {
+    return Map<dynamic, E>.from(_storage);
+  }
+
+  @override
+  Iterable<E> get values => _storage.values.cast<E>();
+
+  @override
+  Iterable<E> valuesBetween({dynamic startKey, dynamic endKey}) {
+    if (startKey == null && endKey == null) {
+      return values;
+    }
+
+    final int startIndex = startKey != null ? _storage.keys.toList().indexOf(
+        startKey as String) : 0;
+    final int endIndex = endKey != null ? _storage.keys.toList().indexOf(
+        endKey as String) : _storage.length - 1;
+
+    if (startIndex < 0 || endIndex < 0) {
+      throw ArgumentError('Start key or end key not found in the box.');
+    }
+
+    return _storage.values.skip(startIndex)
+        .take(endIndex - startIndex + 1)
+        .cast<E>();
+  }
+
+}
diff --git a/lib/ui/screens/pay_form.dart b/lib/ui/screens/pay_form.dart
index af8e41ca7422e6e5ad7cf0a91a81da7c73545fda..8d4ea40a87452f6d37bb1cd6cb4c252045296c2b 100644
--- a/lib/ui/screens/pay_form.dart
+++ b/lib/ui/screens/pay_form.dart
@@ -1,3 +1,4 @@
+import 'package:connectivity_wrapper/connectivity_wrapper.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/material.dart';
@@ -35,6 +36,20 @@ class _PayFormState extends State<PayForm> {
       if (state.comment != null && _commentController.text != state.comment) {
         _commentController.text = state.comment;
       }
+      final ButtonStyle payBtnStyle = ElevatedButton.styleFrom(
+        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
+        shape: RoundedRectangleBorder(
+          borderRadius: BorderRadius.circular(30.0),
+        ),
+        foregroundColor: Colors.white,
+        backgroundColor: Theme.of(context).colorScheme.primary,
+        textStyle: const TextStyle(
+          fontWeight: FontWeight.bold,
+          fontSize: 16,
+        ),
+      );
+      final Widget payBtnText = Text(tr('g1_form_pay_send') +
+          (!kReleaseMode ? ' ${state.amount} ${state.comment}' : ''));
       return Form(
         key: _formKey,
         child: Column(
@@ -70,51 +85,47 @@ class _PayFormState extends State<PayForm> {
               },
             ),
             const SizedBox(height: 10.0),
-            ElevatedButton(
-              onPressed: (!state.canBeSent() ||
-                      state.amount == null ||
-                      !_commentValidate() ||
-                      !_weHaveBalance(context, state.amount!))
-                  ? null
-                  : () async {
-                      try {
-                        await payWithRetry(context, state, false);
-                      } on RetryException {
-                        // Here the transactions can be lost, so we must implement some manual retry use
-                        await payWithRetry(context, state, true);
-                      }
-                    },
-              style: ElevatedButton.styleFrom(
-                padding:
-                    const EdgeInsets.symmetric(horizontal: 20, vertical: 25),
-                shape: RoundedRectangleBorder(
-                  borderRadius: BorderRadius.circular(30.0),
+            ConnectivityWidgetWrapper(
+                stacked: false,
+                offlineWidget: ElevatedButton(
+                  onPressed: null,
+                  style: payBtnStyle,
+                  child: _buildBtn(Text(tr('offline'))),
                 ),
-                foregroundColor: Colors.white,
-                backgroundColor: Theme.of(context).colorScheme.primary,
-                textStyle: const TextStyle(
-                  fontWeight: FontWeight.bold,
-                  fontSize: 16,
-                ),
-              ),
-              child: Row(
-                mainAxisAlignment: MainAxisAlignment.center,
-                children: <Widget>[
-                  const Icon(Icons.send),
-                  const SizedBox(width: 10),
-                  Text(tr('g1_form_pay_send') +
-                      (!kReleaseMode
-                          ? ' ${state.amount} ${state.comment}'
-                          : '')),
-                ],
-              ),
-            )
+                child: ElevatedButton(
+                  onPressed: (!state.canBeSent() ||
+                          state.amount == null ||
+                          !_commentValidate() ||
+                          !_weHaveBalance(context, state.amount!))
+                      ? null
+                      : () async {
+                          try {
+                            await payWithRetry(context, state, false);
+                          } on RetryException {
+                            // Here the transactions can be lost, so we must implement some manual retry use
+                            await payWithRetry(context, state, true);
+                          }
+                        },
+                  style: payBtnStyle,
+                  child: _buildBtn(payBtnText),
+                ))
           ],
         ),
       );
     });
   }
 
+  Row _buildBtn(Widget payBtnText) {
+    return Row(
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: <Widget>[
+        const Icon(Icons.send),
+        const SizedBox(width: 10),
+        payBtnText,
+      ],
+    );
+  }
+
   bool _commentValidate() {
     final bool? val = _formKey.currentState?.validate();
     logger('Validating comment: $val');
diff --git a/lib/ui/ui_helpers.dart b/lib/ui/ui_helpers.dart
index 7dbc04845bc0da22fddb62781272bbe2b75864f0..930c10af193518a775ce73c1fd29b33b084d3842 100644
--- a/lib/ui/ui_helpers.dart
+++ b/lib/ui/ui_helpers.dart
@@ -197,7 +197,7 @@ ListTile contactToListItem(Contact contact, int index, BuildContext context,
       trailing: trailing);
 }
 
-bool showShare() => onlyInDevelopment;
+bool showShare() => onlyInDevelopment || !kIsWeb;
 
 bool get onlyInDevelopment => !inProduction;
 
@@ -207,7 +207,10 @@ bool get onlyInProduction => kReleaseMode;
 
 bool get inProduction => onlyInProduction;
 
-String assets(String str) => (kIsWeb && kReleaseMode) ? 'assets/$str' : str;
+String assets(String str) =>
+    (kIsWeb && kReleaseMode) || (!kIsWeb && Platform.isAndroid)
+        ? 'assets/$str'
+        : str;
 
 Future<Directory?> getAppSpecificExternalFilesDirectory(
     [bool ext = false]) async {
diff --git a/lib/ui/widgets/first_screen/pay_contact_search_page.dart b/lib/ui/widgets/first_screen/pay_contact_search_page.dart
index a225daab25212576a2cab968bab696793680614b..a6e7ed0179ddf8045bd16d1eb60e545a201287b3 100644
--- a/lib/ui/widgets/first_screen/pay_contact_search_page.dart
+++ b/lib/ui/widgets/first_screen/pay_contact_search_page.dart
@@ -148,10 +148,11 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> {
                   if (_results.length == 1 && pay != null) {
                     final Contact contact = _results[0];
                     paymentCubit.selectUser(contact, pay.amount);
-                  } else if (pay!.amount != null) {
-                    paymentCubit.selectKeyAmount(pay.contact!, pay.amount!);
-                  } else {
-                    paymentCubit.selectKey(pay.contact);
+                    if (pay.amount != null) {
+                      paymentCubit.selectKeyAmount(contact, pay.amount!);
+                    } else {
+                      paymentCubit.selectKey(contact);
+                    }
                   }
                   if (!mounted) {
                     return;