diff --git a/.gitignore b/.gitignore
index 603d6ca8b1ef10bd23284f39239d10f8d8a93466..5615bc8b917cd3c8bff30920bfce6860c09f7769 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,5 @@ app.*.map.json
 /android/app/debug
 /android/app/profile
 /android/app/release
-web
 build.sh
-linux/
\ No newline at end of file
+linux/
diff --git a/assets/translations/ca.json b/assets/translations/ca.json
index f5184ee4a1d152ea3ac8864c4b258037ae761cb5..a475ce92482962c5c9efbd86a8a46978852943a4 100644
--- a/assets/translations/ca.json
+++ b/assets/translations/ca.json
@@ -56,7 +56,6 @@
   "data_load_error": "Error en carregar les dades",
   "add_contact": "Afegeix el contacte",
   "contact_added": "Contacte afegit",
-  "no_transactions": "Encara no tens cap transacció",
   "qr-scanner-title": "Escaneja el QR d'algú",
   "copy_contact_key": "Copia",
   "nothing_found": "No s'ha trobat res",
diff --git a/assets/translations/en.json b/assets/translations/en.json
index 98e2c41502e49c09b3743d62b1bcd14414126bc7..c44742e661f7235b2d4963a4b7bcf1a7f0f92df7 100644
--- a/assets/translations/en.json
+++ b/assets/translations/en.json
@@ -56,7 +56,7 @@
   "data_load_error": "Error loading data",
   "add_contact": "Add contact",
   "contact_added": "Contact added",
-  "no_transactions": "You don't have any transaction yet",
+  "no_transactions": "This wallet has no balance. Start by offering your services in Äž1 markets, for example, to receive your first income.",
   "qr-scanner-title": "Scan the QR of someone",
   "copy_contact_key": "Copy",
   "nothing_found": "Nothing found",
@@ -88,5 +88,6 @@
   "please_confirm_sent_desc": "Please confirm that you wish to send {amount} Äž1 to {to}",
   "yes_sent": "YES, SEND IT",
   "receive_g1": "Receive Äž1",
-  "insufficient balance": "Oops, insufficient balance to pay this"
+  "insufficient balance": "Oops, insufficient balance to pay this",
+  "language_switch_title": "Select your language"
 }
diff --git a/assets/translations/es.json b/assets/translations/es.json
index 2a788d81a749d0f9aa5165794c3a49ac08bf9b5a..082d49fc6fb87debbf5d8528491737b4d3725963 100644
--- a/assets/translations/es.json
+++ b/assets/translations/es.json
@@ -56,7 +56,7 @@
   "data_load_error": "Error al cargar los datos",
   "add_contact": "Añadir contacto",
   "contact_added": "Contacto añadido",
-  "no_transactions": "No tiene todavía ninguna transacción",
+  "no_transactions": "Este monedero no tiene saldo. Empieza por ejemplo a ofrecer tus servicios en mercados Äž1 para recibir tus primeros ingresos",
   "qr-scanner-title": "Escanea el QR de alguien",
   "copy_contact_key": "Copiar",
   "nothing_found": "No se ha encontrado nada",
@@ -87,5 +87,6 @@
   "please_confirm_sent_desc": "Por favor confirma que quieres enviar {amount} Äž1 a {to}",
   "yes_sent": "SÍ, ENVÍALO",
   "receive_g1": "Recibe Junas",
-  "insufficient balance": "Upps, balance insuficiente para hacer este pago"
+  "insufficient balance": "Upps, balance insuficiente para hacer este pago",
+  "language_switch_title": "Selecciona tu idioma"
 }
diff --git a/assets/translations/fr.json b/assets/translations/fr.json
index 6a0f5ceeec4a74feb4cdc2382099a03c27be52c5..165273fc7496761db7b8b52d285c2b185eca239e 100644
--- a/assets/translations/fr.json
+++ b/assets/translations/fr.json
@@ -19,7 +19,7 @@
   "g1_form_pay_hint": "Entrez une description (facultatif)",
   "code_card_title": "Dépôt de code",
   "intro_1_title": "Bienvenue dans notre portefeuille Äž1!",
-  "intro_1_description": "Avec ce portefeuille, vous pouvez facilement et en toute sécurité stocker, envoyer et recevoir de la monnaie Ğ1 (également connue sous le nom de 'Juin').",
+  "intro_1_description": "Avec ce portefeuille, vous pouvez facilement et en toute sécurité stocker, envoyer et recevoir de la monnaie Ğ1 (également connue sous le nom de 'June').",
   "intro_2_title": "Une monnaie numérique libre créée par le peuple, pour le peuple",
   "intro_2_description": "Ğ1 ne dépend d'aucun gouvernement ou entreprise et est écologique (car elle consomme peu d'énergie), transparente et équitable pour tous.",
   "intro_3_title": "La monnaie Ğ1 fonctionne sur le réseau Duniter",
@@ -63,4 +63,4 @@
   "intro_some_pattern_to_export": "Motif pour importer/exporter votre portefeuille",
   "confirm_pattern": "Confirmer le motif",
   "draw_pattern": "Dessiner le motif"
-}
\ No newline at end of file
+}
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 69c8dbd170162daa391861ea8334cf5808a9d6ff..cb6950551df449258d980761203c7a5ff1b0daaa 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -46,6 +46,7 @@
     	<string>en</string>
     	<string>es</string>
     	<string>fr</string>
+    	<string>ca</string>
     </array>
     <key>LSApplicationQueriesSchemes</key>
     <array>
diff --git a/lib/data/models/app_state.dart b/lib/data/models/app_state.dart
index 76c8b2ca76f8da0a938a1ffa62f076b2f333e595..99d588d4bf0b26136a76a0b810f4b86e0f4909a0 100644
--- a/lib/data/models/app_state.dart
+++ b/lib/data/models/app_state.dart
@@ -11,6 +11,7 @@ class AppState extends Equatable implements IsJsonSerializable<AppState> {
     this.introViewed = false,
     this.warningViewed = false,
     this.expertMode = false,
+    this.locale = 'en',
   });
 
   factory AppState.fromJson(Map<String, dynamic> json) =>
@@ -19,16 +20,19 @@ class AppState extends Equatable implements IsJsonSerializable<AppState> {
   final bool introViewed;
   final bool warningViewed;
   final bool expertMode;
+  final String locale;
 
   AppState copyWith({
     bool? introViewed,
     bool? warningViewed,
     bool? expertMode,
+    String? locale,
   }) {
     return AppState(
         introViewed: introViewed ?? this.introViewed,
         warningViewed: warningViewed ?? this.warningViewed,
-        expertMode: expertMode ?? this.expertMode);
+        expertMode: expertMode ?? this.expertMode,
+        locale: locale ?? this.locale);
   }
 
   @override
@@ -38,5 +42,6 @@ class AppState extends Equatable implements IsJsonSerializable<AppState> {
   Map<String, dynamic> toJson() => _$AppStateToJson(this);
 
   @override
-  List<Object?> get props => <Object>[introViewed, warningViewed, expertMode];
+  List<Object?> get props =>
+      <Object>[introViewed, warningViewed, expertMode, locale];
 }
diff --git a/lib/data/models/app_state.g.dart b/lib/data/models/app_state.g.dart
index dca06c2fc3f6db2daa603fd305b2ad99e6141664..8e1120d54c2e362818cc95429e7e4ba91c038ab0 100644
--- a/lib/data/models/app_state.g.dart
+++ b/lib/data/models/app_state.g.dart
@@ -10,10 +10,12 @@ AppState _$AppStateFromJson(Map<String, dynamic> json) => AppState(
       introViewed: json['introViewed'] as bool? ?? false,
       warningViewed: json['warningViewed'] as bool? ?? false,
       expertMode: json['expertMode'] as bool? ?? false,
+      locale: json['locale'] as String? ?? 'en',
     );
 
 Map<String, dynamic> _$AppStateToJson(AppState instance) => <String, dynamic>{
       'introViewed': instance.introViewed,
       'warningViewed': instance.warningViewed,
       'expertMode': instance.expertMode,
+      'locale': instance.locale,
     };
diff --git a/lib/data/models/node_list_cubit.dart b/lib/data/models/node_list_cubit.dart
index 2136aea828f9aef2af092acad789efea76e8c958..c6e213ac48ca440c2018c6e88948986a869ab133 100644
--- a/lib/data/models/node_list_cubit.dart
+++ b/lib/data/models/node_list_cubit.dart
@@ -6,34 +6,6 @@ import 'node_list_state.dart';
 class NodeListCubit extends HydratedCubit<NodeListState> {
   NodeListCubit() : super(NodeListState());
 
-  void addDuniterNode(Node node) {
-    if (!_find(node)) {
-      // Does not exists, so add it
-      emit(state.copyWith(duniterNodes: <Node>[...state.duniterNodes, node]));
-    } else {
-      // it exists
-      updateDuniterNode(node);
-    }
-  }
-
-  bool _find(Node node) => state.duniterNodes.contains(node);
-
-  void insertDuniterNode(Node node) {
-    if (!_find(node)) {
-      emit(state.copyWith(duniterNodes: <Node>[node, ...state.duniterNodes]));
-    } else {
-      // it exists
-      updateDuniterNode(node);
-    }
-  }
-
-  void updateDuniterNode(Node updatedNode) {
-    final List<Node> updatedDuniterNodes = state.duniterNodes.map((Node n) {
-      return n.url == updatedNode.url ? updatedNode : n;
-    }).toList();
-    emit(state.copyWith(duniterNodes: updatedDuniterNodes));
-  }
-
   void setDuniterNodes(List<Node> nodes) {
     emit(state.copyWith(duniterNodes: nodes));
   }
@@ -42,9 +14,8 @@ class NodeListCubit extends HydratedCubit<NodeListState> {
     emit(state.copyWith(cesiumPlusNodes: nodes));
   }
 
-  void addCesiumPlusNode(Node node) {
-    emit(state
-        .copyWith(cesiumPlusNodes: <Node>[...state.cesiumPlusNodes, node]));
+  void setGvaNodes(List<Node> nodes) {
+    emit(state.copyWith(gvaNodes: nodes));
   }
 
   List<Node> get duniterNodes => state.duniterNodes;
diff --git a/lib/data/models/node_manager.dart b/lib/data/models/node_manager.dart
index ccf9e3825fe565ca6878c31e7f584eaf38e153e3..4f2383e71a53bea35abddf6b99861c2552deb476 100644
--- a/lib/data/models/node_manager.dart
+++ b/lib/data/models/node_manager.dart
@@ -119,5 +119,6 @@ class NodeManagerObserver {
   void update(NodeManager nodeManager) {
     cubit.setDuniterNodes(nodeManager.duniterNodes);
     cubit.setCesiumPlusNodes(nodeManager.cesiumPlusNodes);
+    cubit.setGvaNodes(nodeManager.gvaNodes);
   }
 }
diff --git a/lib/data/models/payment_cubit.dart b/lib/data/models/payment_cubit.dart
index 43f048449eaa3377f308b05fcf4a26b98d5623a4..184812277b65fa0bb8dcd1747f9ca5b05d3b817a 100644
--- a/lib/data/models/payment_cubit.dart
+++ b/lib/data/models/payment_cubit.dart
@@ -29,7 +29,7 @@ class PaymentCubit extends HydratedCubit<PaymentState> {
 
   void selectKeyAmount(String publicKey, double amount) {
     final PaymentState newState =
-        PaymentState(publicKey: publicKey, amount: amount);
+    PaymentState(publicKey: publicKey, amount: amount);
     emit(newState);
   }
 
@@ -72,7 +72,7 @@ class PaymentCubit extends HydratedCubit<PaymentState> {
     emit(newState);
   }
 
-  void setDescription(String description) {
-    emit(state.copyWith(comment: description));
+  void setComment(String comment) {
+    emit(state.copyWith(comment: comment));
   }
 }
diff --git a/lib/data/models/transaction.dart b/lib/data/models/transaction.dart
index 4218a9e04a22d8af5ed8b0bad8a018f0e911469d..9fec0435f076455b287bc17bc4b4bb6d0647facc 100644
--- a/lib/data/models/transaction.dart
+++ b/lib/data/models/transaction.dart
@@ -30,7 +30,7 @@ class Transaction extends Equatable {
   @JsonKey(fromJson: uIntFromList, toJson: uIntToList)
   final Uint8List? toAvatar;
   final String? toNick;
-  final int amount;
+  final double amount;
   @JsonKey(fromJson: uIntFromList, toJson: uIntToList)
   final Uint8List? fromAvatar;
   final String? fromNick;
@@ -65,7 +65,7 @@ class TransactionsAndBalanceState extends Equatable {
   factory TransactionsAndBalanceState.fromJson(Map<String, dynamic> json) =>
       _$TransactionsAndBalanceStateFromJson(json);
   final List<Transaction> transactions;
-  final int balance;
+  final double balance;
   final DateTime lastChecked;
 
   Map<String, dynamic> toJson() => _$TransactionsAndBalanceStateToJson(this);
diff --git a/lib/data/models/transaction.g.dart b/lib/data/models/transaction.g.dart
index 992e707be310c1fcce75b6cc6367ac8324f0a4e5..62df6223e9f799e27394b8285adccc5afb16aca5 100644
--- a/lib/data/models/transaction.g.dart
+++ b/lib/data/models/transaction.g.dart
@@ -11,7 +11,7 @@ abstract class _$TransactionCWProxy {
 
   Transaction to(String to);
 
-  Transaction amount(int amount);
+  Transaction amount(double amount);
 
   Transaction comment(String comment);
 
@@ -34,7 +34,7 @@ abstract class _$TransactionCWProxy {
   Transaction call({
     String? from,
     String? to,
-    int? amount,
+    double? amount,
     String? comment,
     DateTime? time,
     Uint8List? toAvatar,
@@ -57,7 +57,7 @@ class _$TransactionCWProxyImpl implements _$TransactionCWProxy {
   Transaction to(String to) => this(to: to);
 
   @override
-  Transaction amount(int amount) => this(amount: amount);
+  Transaction amount(double amount) => this(amount: amount);
 
   @override
   Transaction comment(String comment) => this(comment: comment);
@@ -108,7 +108,7 @@ class _$TransactionCWProxyImpl implements _$TransactionCWProxy {
       amount: amount == const $CopyWithPlaceholder() || amount == null
           ? _value.amount
           // ignore: cast_nullable_to_non_nullable
-          : amount as int,
+          : amount as double,
       comment: comment == const $CopyWithPlaceholder() || comment == null
           ? _value.comment
           // ignore: cast_nullable_to_non_nullable
@@ -146,7 +146,7 @@ extension $TransactionCopyWith on Transaction {
 abstract class _$TransactionsAndBalanceStateCWProxy {
   TransactionsAndBalanceState transactions(List<Transaction> transactions);
 
-  TransactionsAndBalanceState balance(int balance);
+  TransactionsAndBalanceState balance(double balance);
 
   TransactionsAndBalanceState lastChecked(DateTime lastChecked);
 
@@ -158,7 +158,7 @@ abstract class _$TransactionsAndBalanceStateCWProxy {
   /// ````
   TransactionsAndBalanceState call({
     List<Transaction>? transactions,
-    int? balance,
+    double? balance,
     DateTime? lastChecked,
   });
 }
@@ -175,7 +175,7 @@ class _$TransactionsAndBalanceStateCWProxyImpl
       this(transactions: transactions);
 
   @override
-  TransactionsAndBalanceState balance(int balance) => this(balance: balance);
+  TransactionsAndBalanceState balance(double balance) => this(balance: balance);
 
   @override
   TransactionsAndBalanceState lastChecked(DateTime lastChecked) =>
@@ -203,7 +203,7 @@ class _$TransactionsAndBalanceStateCWProxyImpl
       balance: balance == const $CopyWithPlaceholder() || balance == null
           ? _value.balance
           // ignore: cast_nullable_to_non_nullable
-          : balance as int,
+          : balance as double,
       lastChecked:
           lastChecked == const $CopyWithPlaceholder() || lastChecked == null
               ? _value.lastChecked
@@ -227,7 +227,7 @@ extension $TransactionsAndBalanceStateCopyWith on TransactionsAndBalanceState {
 Transaction _$TransactionFromJson(Map<String, dynamic> json) => Transaction(
       from: json['from'] as String,
       to: json['to'] as String,
-      amount: json['amount'] as int,
+      amount: (json['amount'] as num).toDouble(),
       comment: json['comment'] as String,
       time: DateTime.parse(json['time'] as String),
       toAvatar: uIntFromList(json['toAvatar'] as List<int>),
@@ -255,7 +255,7 @@ TransactionsAndBalanceState _$TransactionsAndBalanceStateFromJson(
       transactions: (json['transactions'] as List<dynamic>)
           .map((e) => Transaction.fromJson(e as Map<String, dynamic>))
           .toList(),
-      balance: json['balance'] as int,
+      balance: (json['balance'] as num).toDouble(),
       lastChecked: DateTime.parse(json['lastChecked'] as String),
     );
 
diff --git a/lib/data/models/transaction_cubit.dart b/lib/data/models/transaction_cubit.dart
index 0f2ea8560dfbf087eb300b55bf396b38e7e6367c..6e6282451c463ba7bc2b4ec5be5895e3f40d452d 100644
--- a/lib/data/models/transaction_cubit.dart
+++ b/lib/data/models/transaction_cubit.dart
@@ -19,28 +19,19 @@ class TransactionsCubit extends HydratedCubit<TransactionsAndBalanceState> {
     final TransactionsAndBalanceState currentState = state;
     final List<Transaction> newTransactions =
         List<Transaction>.of(currentState.transactions)..add(transaction);
-    final int newBalance = currentState.balance + transaction.amount;
+    final double newBalance = currentState.balance + transaction.amount;
     emit(currentState.copyWith(
         transactions: newTransactions, balance: newBalance));
   }
 
-  void updateTransactions(List<Transaction> newTransactions, int newBalance) {
+  void updateTransactions(
+      List<Transaction> newTransactions, double newBalance) {
     emit(state.copyWith(transactions: newTransactions, balance: newBalance));
   }
 
   Future<void> fetchTransactions(NodeListCubit cubit) async {
-    // Future<TransactionsAndBalance> _loadTransactions(NodeListCubit cubit) async {
-    // carga de datos asíncrona
-    // ...
-    // disabled, as we have to change the nodes
-    // https://g1.asycn.io/gva
-    // https://duniter.pini.fr/gva
-    /* Gva(node: 'https://g1.asycn.io/gva')
-        .balance(SharedPreferencesHelper().getPubKey())
-        .then((double currentBal) => setState(() {
-              _balanceAmount = currentBal;
-            })); */
     logger('Loading transactions');
+    logger('GVA balance: ${gvaBalance()}');
     final String txData = txDebugging
         ? await getTxHistory('6DrGg8cftpkgffv4Y4Lse9HSjgc8coEQor3yvMPHAnVH')
         : await getTxHistory(SharedPreferencesHelper().getPubKey());
@@ -61,7 +52,7 @@ class TransactionsCubit extends HydratedCubit<TransactionsAndBalanceState> {
 
   List<Transaction> get transactions => state.transactions;
 
-  int get balance => state.balance;
+  double get balance => state.balance;
 
   DateTime get lastChecked => state.lastChecked;
 }
diff --git a/lib/g1/api.dart b/lib/g1/api.dart
index cfe6dcf5382db0039a388ae6c73d94f7ae529e5b..8773f85a040bc55615b2d290773f5d27af718404 100644
--- a/lib/g1/api.dart
+++ b/lib/g1/api.dart
@@ -405,17 +405,11 @@ Future<http.Response> _requestWithRetry(
 
 Future<String> pay(
     {required String to, required double amount, String? comment}) async {
-  final List<Node> nodes = nodesWorkingList(NodeType.gva);
-  if (nodes.isNotEmpty) {
-    // reorder list to use others
-    nodes.shuffle();
-
+  final String output = getGvaNode();
+  if (Uri.tryParse(output) != null) {
+    final String node = output;
     try {
-      // Reference of working proxy 'https://g1demo.comunes.net/proxy/g1v1.p2p.legal/gva/';
-      final String node =
-          'https://g1demo.comunes.net/proxy/${nodes.first.url.replaceFirst('https://', '').replaceFirst('http://', '')}/';
       final Gva gva = Gva(node: node);
-
       logger('Trying $node to get balance');
       final CesiumWallet wallet = await SharedPreferencesHelper().getWallet();
       logger('Current balance ${await gva.balance(wallet.pubkey)}');
@@ -430,11 +424,45 @@ Future<String> pay(
       logger('GVA replied with "$response"');
       return response;
     } catch (e, stacktrace) {
-      // move logger outside main
       logger(e);
       logger(stacktrace);
       return "Oops! the payment failed. Something didn't work as expected";
     }
   }
-  return 'Sorry: I cannot find a working node to send the transaction';
+  return output;
+}
+
+String getGvaNode() {
+  final List<Node> nodes = nodesWorkingList(NodeType.gva);
+  if (nodes.isNotEmpty) {
+// reorder list to use others
+    nodes.shuffle();
+// Reference of working proxy 'https://g1demo.comunes.net/proxy/g1v1.p2p.legal/gva/';
+    final String node =
+        'https://g1demo.comunes.net/proxy/${nodes.first.url.replaceFirst('https://', '').replaceFirst('http://', '')}/';
+    return node;
+  } else {
+    return 'Sorry: I cannot find a working node to send the transaction';
+  }
+}
+
+Future<double> gvaBalance() async {
+  final String output = getGvaNode();
+  if (Uri.tryParse(output) != null) {
+    final String node = output;
+    try {
+      final Gva gva = Gva(node: node);
+      logger('Trying $node to get balance');
+      final CesiumWallet wallet = await SharedPreferencesHelper().getWallet();
+      final double balance = await gva.balance(wallet.pubkey);
+      logger('Current balance $balance');
+      return balance;
+    } catch (e, stacktrace) {
+      // move logger outside main
+      logger(e);
+      logger(stacktrace);
+      throw Exception('Oops! failed to obtain balance');
+    }
+  }
+  throw Exception('Sorry: I cannot find a working node to get your balance');
 }
diff --git a/lib/g1/transaction_parser.dart b/lib/g1/transaction_parser.dart
index dd021a8cc404eacc70b53b83e1a6a9b5871372c0..cfcbdc43314e8ea57fb5b27d73245cd031bf3290 100644
--- a/lib/g1/transaction_parser.dart
+++ b/lib/g1/transaction_parser.dart
@@ -10,14 +10,14 @@ TransactionsAndBalanceState transactionParser(String txData) {
   final String pubKey = parsedTxData['pubkey'] as String;
   final List<dynamic> listReceived = (parsedTxData['history']
       as Map<String, dynamic>)['received'] as List<dynamic>;
-  int balance = 0;
+  double balance = 0;
   final List<Transaction> tx = <Transaction>[];
   for (final dynamic receivedRaw in listReceived) {
     final Map<String, dynamic> received = receivedRaw as Map<String, dynamic>;
     final int timestamp = received['blockstampTime'] as int;
     final String comment = received['comment'] as String;
     final List<dynamic> outputs = received['outputs'] as List<dynamic>;
-    final int amount = int.parse((outputs[0] as String).split(':')[0]);
+    final double amount = double.parse((outputs[0] as String).split(':')[0]);
     final String? address1 = exp.firstMatch(outputs[0] as String)!.group(1);
     final String? address2 = exp.firstMatch(outputs[1] as String)!.group(1);
     if (pubKey == address1) {
diff --git a/lib/main.dart b/lib/main.dart
index 85cc6fb8d14dc01dd68b21612baad27f3e0df54b..d24385f3156726a7a00e3e455b50f704265e5600 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -78,6 +78,7 @@ void main() async {
             Locale('en'),
             Locale('es'),
             Locale('fr'),
+            Locale('ca'),
           ],
           fallbackLocale: const Locale('en'),
           useFallbackTranslations: true,
@@ -144,7 +145,8 @@ class _AppIntro extends State<AppIntro> {
                   createPageViewModel(
                       'intro_${i}_title',
                       'intro_${i}_description',
-                      'assets/img/undraw_intro_$i.png'),
+                      'assets/img/undraw_intro_$i.png',
+                      context),
               ],
               onDone: () => _onIntroEnd(buildContext),
               showSkipButton: true,
@@ -169,15 +171,26 @@ class _AppIntro extends State<AppIntro> {
 }
 
 PageViewModel createPageViewModel(
-    String title, String body, String imageAsset) {
+    String title, String body, String imageAsset, BuildContext context) {
+  final ColorScheme colorScheme = Theme.of(context).colorScheme;
+  final TextStyle titleStyle = TextStyle(
+    color: colorScheme.primary,
+    fontWeight: FontWeight.bold,
+    fontSize: 24.0,
+  );
+  final TextStyle bodyStyle = TextStyle(
+    color: colorScheme.onSurface,
+    fontSize: 18.0,
+  );
+
   return PageViewModel(
     title: tr(title),
     body: tr(body),
     image: Image.asset(imageAsset),
-    decoration: const PageDecoration(
-      pageColor: Colors.white,
-      bodyTextStyle: TextStyle(fontSize: 18),
-      titleTextStyle: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
+    decoration: PageDecoration(
+      titleTextStyle: titleStyle,
+      bodyTextStyle: bodyStyle,
+      pageColor: colorScheme.background,
     ),
   );
 }
diff --git a/lib/shared_prefs.dart b/lib/shared_prefs.dart
index 20401c207b3f130c2f9d2eb792015f415f5763ff..780f5612f68f979f96e2c459f91b88af70679202 100644
--- a/lib/shared_prefs.dart
+++ b/lib/shared_prefs.dart
@@ -82,7 +82,6 @@ class SharedPreferencesHelper {
   String getPubKey() {
     // At this point should exists
     final String? pubKey = _prefs.getString(_pubKey);
-    logger('Public key: $pubKey');
     return pubKey!;
   }
 
diff --git a/lib/ui/screens/fifth_screen.dart b/lib/ui/screens/fifth_screen.dart
index 98e197949cf1adaf2099fd6ce7ba16451535b3db..400169203659036bb6be80e5e72db67bb66a404e 100644
--- a/lib/ui/screens/fifth_screen.dart
+++ b/lib/ui/screens/fifth_screen.dart
@@ -28,6 +28,38 @@ class FifthScreen extends StatelessWidget {
                   padding: const EdgeInsets.symmetric(horizontal: 16),
                   physics: const BouncingScrollPhysics(),
                   children: <Widget>[
+                    const SizedBox(height: 10),
+                    DropdownButtonFormField<Locale>(
+                      value: context.locale,
+                      decoration: InputDecoration(
+                        labelText: tr('language_switch_title'),
+                        icon: const Icon(Icons.language),
+                        border: const OutlineInputBorder(),
+                      ),
+                      onChanged: (Locale? newLocale) {
+                        context.setLocale(newLocale!);
+                      },
+                      items: const <DropdownMenuItem<Locale>>[
+                        DropdownMenuItem<Locale>(
+                          value: Locale('ca'),
+                          child: Text('Català'),
+                        ),
+                        DropdownMenuItem<Locale>(
+                          value: Locale('en'),
+                          child: Text('English'),
+                        ),
+                        DropdownMenuItem<Locale>(
+                          value: Locale('es'),
+                          child: Text('Español'),
+                        ),
+                        DropdownMenuItem<Locale>(
+                          value: Locale('fr'),
+                          child: Text('Français'),
+                        ),
+
+                        // Add more DropdownMenuItem for more languages
+                      ],
+                    ),
                     const TextDivider(text: 'key_tools_title'),
                     GridView.count(
                         physics: const NeverScrollableScrollPhysics(),
diff --git a/lib/ui/screens/first_screen.dart b/lib/ui/screens/first_screen.dart
index ddd1b72044fc25fae0d072120a65aadb90ce2948..74ba6f2dff15db5d49cd028eed340e6b713e7bad 100644
--- a/lib/ui/screens/first_screen.dart
+++ b/lib/ui/screens/first_screen.dart
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import '../../data/models/app_cubit.dart';
+import '../../data/models/app_state.dart';
 import '../../data/models/payment_cubit.dart';
 import '../../data/models/payment_state.dart';
 import '../widgets/bottom_widget.dart';
@@ -20,94 +21,66 @@ class FirstScreen extends StatefulWidget {
 
 class _FirstScreenState extends State<FirstScreen> {
   @override
-  Widget build(BuildContext context) {
-    WidgetsBinding.instance.addPostFrameCallback((_) async {
-      if (!context.read<AppCubit>().isWarningViewed) {
-        ScaffoldMessenger.of(context).showSnackBar(
-          SnackBar(
-            content: Text(tr('demo_desc')),
-            action: SnackBarAction(
-              label: 'OK',
-              onPressed: () {
-                ScaffoldMessenger.of(context).hideCurrentSnackBar();
-                context.read<AppCubit>().warningViewed();
-              },
-            ),
-          ),
-        );
-      }
-    });
-    return BlocBuilder<PaymentCubit, PaymentState>(
-        builder: (BuildContext context, PaymentState state) =>
-            Stack(children: <Widget>[
-              Scaffold(
-                  appBar: AppBar(title: Text(tr('credit_card_title'))),
-                  drawer: const CardDrawer(),
-                  body: ListView(
-                      padding: const EdgeInsets.symmetric(horizontal: 16),
-                      //physics: const AlwaysScrollableScrollPhysics(),
-                      //controller: _controller,
-                      // shrinkWrap: true,
-                      children: <Widget>[
-                        CreditCard(),
-                        const SizedBox(height: 8),
-                        Padding(
-                          padding: const EdgeInsets.symmetric(horizontal: 24),
-                          child: Divider(
-                            color: Theme.of(context)
-                                .colorScheme
-                                .onBackground
-                                .withOpacity(.4),
+  Widget build(BuildContext context) =>
+      BlocBuilder<AppCubit, AppState>(
+          builder: (BuildContext context, AppState state) {
+            WidgetsBinding.instance.addPostFrameCallback((_) async {
+              if (!state.warningViewed) {
+                ScaffoldMessenger.of(context).showSnackBar(
+                  SnackBar(
+                    content: Text(tr('demo_desc')),
+                    action: SnackBarAction(
+                      label: 'OK',
+                      onPressed: () {
+                        ScaffoldMessenger.of(context).hideCurrentSnackBar();
+                        context.read<AppCubit>().warningViewed();
+                      },
+                    ),
+                  ),
+                );
+              }
+            });
+            return BlocBuilder<PaymentCubit, PaymentState>(
+                builder: (BuildContext context, PaymentState state) =>
+                    Stack(children: <Widget>[
+                      Scaffold(
+                          appBar: AppBar(title: Text(tr('credit_card_title'))),
+                          drawer: const CardDrawer(),
+                          body: ListView(
+                              padding: const EdgeInsets.symmetric(
+                                  horizontal: 16),
+                              //physics: const AlwaysScrollableScrollPhysics(),
+                              //controller: _controller,
+                              // shrinkWrap: true,
+                              children: <Widget>[
+                                CreditCard(),
+                                const SizedBox(height: 8),
+                                Padding(
+                                  padding: const EdgeInsets.symmetric(
+                                      horizontal: 24),
+                                  child: Divider(
+                                    color: Theme
+                                        .of(context)
+                                        .colorScheme
+                                        .onBackground
+                                        .withOpacity(.4),
+                                  ),
+                                ),
+                                const SizedBox(height: 10),
+                                const PayContactSearchButton(),
+                                const SizedBox(height: 10),
+                                const PayForm(),
+                                const BottomWidget()
+                              ])),
+                      Visibility(
+                        visible: state.status == PaymentStatus.sending,
+                        child: Container(
+                          color: Colors.black.withOpacity(0.5),
+                          child: const Center(
+                            child: CircularProgressIndicator(),
                           ),
                         ),
-                        const SizedBox(height: 10),
-                        const PayContactSearchButton(),
-                        const SizedBox(height: 10),
-                        const PayForm(),
-                        const BottomWidget()
-                      ])),
-              Visibility(
-                visible: state.status == PaymentStatus.sending,
-                child: Container(
-                  color: Colors.black.withOpacity(0.5),
-                  child: const Center(
-                    child: CircularProgressIndicator(),
-                  ),
-                ),
-              )
-            ]));
-  }
+                      )
+                    ]));
+          });
 }
-/*
-Scaffold(
-  appBar: AppBar(
-    leading: IconButton(
-      icon: Icon(Icons.menu),
-      onPressed: () => Scaffold.of(context).openDrawer(),
-    ),
-    title: Text('My App'),
-  ),
-  drawerEnableOpenDragGesture: true,
-  drawer: CustomDrawer(),
-  body: // ...
-);
-
-class Screen1 extends StatelessWidget {
-  const Screen1({Key? key}) : super(key: key);
-
-  @override
-  Widget build(BuildContext context) {
-    return Scaffold(
-      appBar: AppBar(title: Text('Screen 1')),
-      drawer: CustomDrawer(),
-      body: Center(
-        child: ElevatedButton(
-          child: Text('Open Drawer'),
-          onPressed: () {
-            Scaffold.of(context).openDrawer();
-          },
-        ),
-      ),
-    );
-  }
-} */
diff --git a/lib/ui/screens/fourth_screen.dart b/lib/ui/screens/fourth_screen.dart
index 680ca6aefc5064690f439420367a0a08c84ebcf7..7a67c4b058b03b03ac5609b4f0fd4fb77d319c68 100644
--- a/lib/ui/screens/fourth_screen.dart
+++ b/lib/ui/screens/fourth_screen.dart
@@ -1,7 +1,5 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 
-import '../widgets/card_drawer.dart';
 import '../widgets/fourth_screen/transaction_page.dart';
 
 class FourthScreen extends StatelessWidget {
@@ -9,9 +7,6 @@ class FourthScreen extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Scaffold(
-        appBar: AppBar(title: Text(tr('transactions'))),
-        drawer: const CardDrawer(),
-        body: const TransactionsAndBalanceWidget());
+    return const TransactionsAndBalanceWidget();
   }
 }
diff --git a/lib/ui/screens/pay_form.dart b/lib/ui/screens/pay_form.dart
index 3a629950770c24dc1f48e64ac8e7557ef1977a0c..af51e2f6afc613cda65c8cb3cd22f781592a6d71 100644
--- a/lib/ui/screens/pay_form.dart
+++ b/lib/ui/screens/pay_form.dart
@@ -1,5 +1,6 @@
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import '../../data/models/payment_cubit.dart';
@@ -36,9 +37,12 @@ class _PayFormState extends State<PayForm> {
             const SizedBox(height: 10.0),
             TextField(
               controller: _commentController,
+              inputFormatters: <TextInputFormatter>[
+                Iso88591TextInputFormatter()
+              ],
               onChanged: (String? value) {
                 if (value != null) {
-                  context.read<PaymentCubit>().setDescription(value);
+                  context.read<PaymentCubit>().setComment(value);
                 }
               },
               decoration: InputDecoration(
@@ -139,3 +143,18 @@ class _PayFormState extends State<PayForm> {
     );
   }
 }
+
+class Iso88591TextInputFormatter extends TextInputFormatter {
+  static final RegExp _iso88591RegExp = RegExp('^[\u0000-\u00FF]*\$');
+  static final RegExp _englishRegExp = RegExp('^[\u0000-\u007F]*\$');
+
+  @override
+  TextEditingValue formatEditUpdate(
+      TextEditingValue oldValue, TextEditingValue newValue) {
+    if (_englishRegExp.hasMatch(newValue.text)) {
+      return newValue;
+    } else {
+      return oldValue;
+    }
+  }
+}
diff --git a/lib/ui/ui_helpers.dart b/lib/ui/ui_helpers.dart
index da2c3924b73e8ff663f39bf1cf31a55c7bd02bfb..b3f5a916a30b09e230dc68e1b26713f8daa3d8f4 100644
--- a/lib/ui/ui_helpers.dart
+++ b/lib/ui/ui_helpers.dart
@@ -70,8 +70,14 @@ Widget humanizePubKeyAsWidget(String pubKey) => Text(
       ),
     );
 
-Color tileColor(int index, [bool inverse = false]) =>
-    (inverse ? index.isOdd : index.isEven) ? Colors.grey[200]! : Colors.white;
+Color tileColor(int index, BuildContext context, [bool inverse = false]) {
+  final ColorScheme colorScheme = Theme.of(context).colorScheme;
+  final Color selectedColor = colorScheme.primary.withOpacity(0.1);
+  final Color unselectedColor = colorScheme.surface;
+  return (inverse ? index.isOdd : index.isEven)
+      ? selectedColor
+      : unselectedColor;
+}
 
 String? humanizeTime(DateTime time, String locale) =>
     timeago.format(time, locale: locale, clock: DateTime.now());
@@ -85,3 +91,7 @@ bool bigScreen(BuildContext context) =>
 
 bool smallScreen(BuildContext context) =>
     MediaQuery.of(context).size.width <= smallScreenWidth;
+
+String formatAmount(double amount) => amount.toStringAsFixed(2);
+
+String formatKAmount(double amount) => formatAmount(amount / 100);
diff --git a/lib/ui/widgets/fifth_screen/import_dialog.dart b/lib/ui/widgets/fifth_screen/import_dialog.dart
index b113eeefe6b6a1ec15b6e6401f8ab32ba5020da8..9d4bdc89a0110dae5bda6cc7c959204f4cb16ece 100644
--- a/lib/ui/widgets/fifth_screen/import_dialog.dart
+++ b/lib/ui/widgets/fifth_screen/import_dialog.dart
@@ -75,7 +75,7 @@ class _ImportDialogState extends State<ImportDialog> {
                             context.replaceSnackbar(
                               content: Text(
                                 tr('wallet_imported'),
-                                style: const TextStyle(color: Colors.blue),
+                                style: const TextStyle(color: Colors.white),
                               ),
                             );
                           }
diff --git a/lib/ui/widgets/first_screen/credit_card.dart b/lib/ui/widgets/first_screen/credit_card.dart
index 07b82d03cc976be075ab47f120b6f4f9488a7a3e..8e3be06b27f7f47683833c75a0b1f4b55ced042e 100644
--- a/lib/ui/widgets/first_screen/credit_card.dart
+++ b/lib/ui/widgets/first_screen/credit_card.dart
@@ -158,17 +158,25 @@ class CreditCard extends StatelessWidget {
                 child: Padding(
                     padding: const EdgeInsets.all(16.0),
                     child: GestureDetector(
-                      onTap: () => copyPublicKeyToClipboard(context),
-                      child: Column(children: <Widget>[
-                        Text(tr('show_qr_to_client')),
-                        QrImage(
-                          data: publicKey,
-                          size: MediaQuery.of(context).size.width * 0.8,
-                          gapless: false,
-                          foregroundColor: Colors.brown,
-                        ),
-                      ]),
-                    ))));
+                        onTap: () => copyPublicKeyToClipboard(context),
+                        child: Container(
+                          color: Theme.of(context).brightness == Brightness.dark
+                              ? Colors.grey[900]
+                              : Colors.grey[100],
+                          padding: const EdgeInsets.all(16.0),
+                          child: Column(children: <Widget>[
+                            Text(tr('show_qr_to_client')),
+                            QrImage(
+                              data: publicKey,
+                              size: MediaQuery.of(context).size.width * 0.8,
+                              gapless: false,
+                              foregroundColor: Theme.of(context).brightness ==
+                                      Brightness.dark
+                                  ? Colors.white
+                                  : Colors.black,
+                            ),
+                          ]),
+                        )))));
       },
     );
   }
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 c55905d9f2ed4f1718cf223a8ed75f54f09775ab..31adea51209efc4ee54ca9dbee3a30b25a0efb09 100644
--- a/lib/ui/widgets/first_screen/pay_contact_search_page.dart
+++ b/lib/ui/widgets/first_screen/pay_contact_search_page.dart
@@ -200,7 +200,7 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> {
     return ListTile(
       title: Text(title),
       subtitle: subtitle,
-      tileColor: tileColor(index),
+      tileColor: tileColor(index, context),
       onTap: () {
         context.read<PaymentCubit>().selectUser(pubKey,
             contact.nick ?? contact.name, hasAvatar ? contact.avatar : null);
@@ -208,8 +208,8 @@ class _PayContactSearchPageState extends State<PayContactSearchPage> {
       },
       leading: avatar(
         contact.avatar,
-        bgColor: tileColor(index),
-        color: tileColor(index, true),
+        bgColor: tileColor(index, context),
+        color: tileColor(index, context, true),
       ),
       trailing: BlocBuilder<ContactsCubit, ContactsState>(
           builder: (BuildContext context, ContactsState state) {
diff --git a/lib/ui/widgets/fourth_screen/transaction_page.dart b/lib/ui/widgets/fourth_screen/transaction_page.dart
index 713757361a39a9569edeece8c1651791f759998d..6a596a74850602999da20f7caa32b1d78f147dae 100644
--- a/lib/ui/widgets/fourth_screen/transaction_page.dart
+++ b/lib/ui/widgets/fourth_screen/transaction_page.dart
@@ -11,6 +11,7 @@ import '../../../data/models/transaction.dart';
 import '../../../data/models/transaction_cubit.dart';
 import '../../../shared_prefs.dart';
 import '../../ui_helpers.dart';
+import '../card_drawer.dart';
 import '../header.dart';
 import '../loading_box.dart';
 import '../third_screen/contacts_page.dart';
@@ -28,6 +29,9 @@ class _TransactionsAndBalanceWidgetState
     extends State<TransactionsAndBalanceWidget>
     with SingleTickerProviderStateMixin {
   final ScrollController _transScrollController = ScrollController();
+  final DraggableScrollableController _draggableScrollableController =
+      DraggableScrollableController();
+
   late NodeListCubit nodeListCubit;
   late TransactionsCubit transCubit;
   bool isLoading = false;
@@ -52,16 +56,20 @@ class _TransactionsAndBalanceWidgetState
     if (_transScrollController.position.pixels ==
             _transScrollController.position.maxScrollExtent ||
         _transScrollController.offset == 0) {
-      setState(() {
-        isLoading = true;
-      });
-      await transCubit.fetchTransactions(nodeListCubit);
-      setState(() {
-        isLoading = false;
-      });
+      await _refreshTransactions();
     }
   }
 
+  Future<void> _refreshTransactions() async {
+    setState(() {
+      isLoading = true;
+    });
+    await transCubit.fetchTransactions(nodeListCubit);
+    setState(() {
+      isLoading = false;
+    });
+  }
+
   @override
   Widget build(BuildContext context) {
     final String myPubKey = !txDebugging
@@ -73,148 +81,181 @@ class _TransactionsAndBalanceWidgetState
       // TODO(vjrj): Only fetch last transactions and used persisted ones
       final ContactsCubit contactsCubit = context.read<ContactsCubit>();
       final List<Transaction> transactions = transBalanceState.transactions;
-      final int balance = transBalanceState.balance;
+      final double balance = transBalanceState.balance;
       if (!isLoading) {
-        return Stack(children: <Widget>[
-          Column(crossAxisAlignment: CrossAxisAlignment.start, children: <
-              Widget>[
-            /* Container(
+        return Scaffold(
+            appBar: AppBar(
+              title: Text(tr('transactions')),
+              actions: <Widget>[
+                IconButton(
+                  icon: const Icon(Icons.refresh),
+                  onPressed: () {
+                    _refreshTransactions();
+                  },
+                ),
+                if (!kReleaseMode)
+                  IconButton(
+                    onPressed: () {
+                      if (_draggableScrollableController.size != null) {
+                        _draggableScrollableController.animateTo(
+                          100,
+                          duration: const Duration(milliseconds: 500),
+                          curve: Curves.easeInOut,
+                        );
+                      }
+                    },
+                    icon: const Icon(Icons.savings),
+                  ),
+              ],
+            ),
+            drawer: const CardDrawer(),
+            body: Stack(children: <Widget>[
+              Column(crossAxisAlignment: CrossAxisAlignment.start, children: <
+                  Widget>[
+                /* Container(
                 color: Theme.of(context).colorScheme.surfaceVariant,
                 height: 90,
                 width: double.infinity,
                 child: const Padding(
                     padding: EdgeInsets.symmetric(horizontal: 16),
                     child: Header(text: 'transactions'))), */
-            Expanded(
-              child: Padding(
-                  padding: const EdgeInsets.fromLTRB(0, 0, 0, 50),
-                  child: transactions.isEmpty
-                      ? Column(children: const <Widget>[
-                          NoElements(text: 'no_transactions')
-                        ])
-                      : ListView.builder(
-                          physics: const AlwaysScrollableScrollPhysics(),
-                          shrinkWrap: true,
-                          controller: _transScrollController,
-                          itemCount: transactions.length,
-                          // Size of elements
-                          // itemExtent: 100,
-                          itemBuilder: (BuildContext context, int index) {
-                            return Slidable(
-                                // Specify a key if the Slidable is dismissible.
-                                key: const ValueKey<int>(0),
-                                // The end action pane is the one at the right or the bottom side.
-                                endActionPane: ActionPane(
-                                  motion: const ScrollMotion(),
-                                  children: <SlidableAction>[
-                                    SlidableAction(
-                                      onPressed: (BuildContext c) {
-                                        _addContact(transactions, index,
-                                            myPubKey, contactsCubit);
-                                        // FIXME i18n
-                                        ScaffoldMessenger.of(context)
-                                            .showSnackBar(
-                                          SnackBar(
-                                            content: Text(tr('contact_added')),
-                                          ),
-                                        );
-                                      },
-                                      backgroundColor:
-                                          Theme.of(context).primaryColor,
-                                      foregroundColor: Colors.white,
-                                      icon: Icons.contacts,
-                                      label: tr('add_contact'),
+                Expanded(
+                  child: Padding(
+                      padding: const EdgeInsets.fromLTRB(0, 0, 0, 50),
+                      child: transactions.isEmpty
+                          ? Column(children: const <Widget>[
+                              NoElements(text: 'no_transactions')
+                            ])
+                          : ListView.builder(
+                              physics: const AlwaysScrollableScrollPhysics(),
+                              shrinkWrap: true,
+                              controller: _transScrollController,
+                              itemCount: transactions.length,
+                              // Size of elements
+                              // itemExtent: 100,
+                              itemBuilder: (BuildContext context, int index) {
+                                return Slidable(
+                                    // Specify a key if the Slidable is dismissible.
+                                    key: const ValueKey<int>(0),
+                                    // The end action pane is the one at the right or the bottom side.
+                                    endActionPane: ActionPane(
+                                      motion: const ScrollMotion(),
+                                      children: <SlidableAction>[
+                                        SlidableAction(
+                                          onPressed: (BuildContext c) {
+                                            _addContact(transactions, index,
+                                                myPubKey, contactsCubit);
+                                            // FIXME i18n
+                                            ScaffoldMessenger.of(context)
+                                                .showSnackBar(
+                                              SnackBar(
+                                                content:
+                                                    Text(tr('contact_added')),
+                                              ),
+                                            );
+                                          },
+                                          backgroundColor:
+                                              Theme.of(context).primaryColor,
+                                          foregroundColor: Colors.white,
+                                          icon: Icons.contacts,
+                                          label: tr('add_contact'),
+                                        ),
+                                      ],
                                     ),
-                                  ],
-                                ),
-                                child: ListTile(
-                                  title: Text(tr('transaction_from_to',
-                                      namedArgs: <String, String>{
-                                        'from': humanizeFromToPubKey(
-                                            myPubKey, transactions[index].from),
-                                        'to': humanizeFromToPubKey(
-                                            myPubKey, transactions[index].to)
-                                      })),
-                                  subtitle: Column(
-                                      crossAxisAlignment:
-                                          CrossAxisAlignment.start,
-                                      children: <Widget>[
-                                        if (transactions[index]
-                                            .comment
-                                            .isNotEmpty)
-                                          Text(
-                                            transactions[index].comment,
-                                            style: const TextStyle(
-                                              fontStyle: FontStyle.italic,
-                                            ),
-                                          ),
-                                        Text(humanizeTime(
-                                            transactions[index].time,
-                                            context.locale.toString())!)
-                                      ]),
-                                  tileColor: tileColor(index),
-                                  trailing: Text(
-                                      '${transactions[index].amount < 0 ? "" : "+"}${(transactions[index].amount / 100).toStringAsFixed(2)} Äž1',
-                                      style: TextStyle(
-                                          color: transactions[index].amount < 0
-                                              ? Colors.red
-                                              : Colors.blue)),
-                                ));
-                          },
-                        )),
-            )
-          ]),
-          Padding(
-              padding: const EdgeInsets.symmetric(horizontal: 10),
-              child: DraggableScrollableSheet(
-                  initialChildSize: 0.12,
-                  minChildSize: 0.12,
-                  maxChildSize: 0.9,
-                  builder: (BuildContext context,
-                          ScrollController scrollController) =>
-                      Container(
-                        decoration: BoxDecoration(
-                          color: Theme.of(context).colorScheme.inversePrimary,
-                          border: Border.all(
+                                    child: ListTile(
+                                      title: Text(tr('transaction_from_to',
+                                          namedArgs: <String, String>{
+                                            'from': humanizeFromToPubKey(
+                                                myPubKey,
+                                                transactions[index].from),
+                                            'to': humanizeFromToPubKey(myPubKey,
+                                                transactions[index].to)
+                                          })),
+                                      subtitle: Column(
+                                          crossAxisAlignment:
+                                              CrossAxisAlignment.start,
+                                          children: <Widget>[
+                                            if (transactions[index]
+                                                .comment
+                                                .isNotEmpty)
+                                              Text(
+                                                transactions[index].comment,
+                                                style: const TextStyle(
+                                                  fontStyle: FontStyle.italic,
+                                                ),
+                                              ),
+                                            Text(humanizeTime(
+                                                transactions[index].time,
+                                                context.locale.toString())!)
+                                          ]),
+                                      tileColor: tileColor(index, context),
+                                      trailing: Text(
+                                          '${transactions[index].amount < 0 ? "" : "+"}${(transactions[index].amount / 100).toStringAsFixed(2)} Äž1',
+                                          style: TextStyle(
+                                              color:
+                                                  transactions[index].amount < 0
+                                                      ? Colors.red
+                                                      : Colors.blue)),
+                                    ));
+                              },
+                            )),
+                )
+              ]),
+              Padding(
+                  padding: const EdgeInsets.symmetric(horizontal: 10),
+                  child: DraggableScrollableSheet(
+                      controller: _draggableScrollableController,
+                      initialChildSize: 0.12,
+                      minChildSize: 0.12,
+                      maxChildSize: 0.9,
+                      builder: (BuildContext context,
+                              ScrollController scrollController) =>
+                          Container(
+                            decoration: BoxDecoration(
                               color:
                                   Theme.of(context).colorScheme.inversePrimary,
-                              width: 3),
-                          borderRadius: const BorderRadius.only(
-                            topLeft: Radius.circular(8),
-                            topRight: Radius.circular(8),
-                          ),
-                        ),
-                        child: Scrollbar(
-                            child: ListView(
-                          controller: scrollController,
-                          children: <Widget>[
-                            const Padding(
-                                padding: EdgeInsets.symmetric(horizontal: 16),
-                                child: Header(
-                                  text: 'balance',
-                                  // topPadding: 0,
-                                )),
-                            Padding(
-                              padding:
-                                  const EdgeInsets.symmetric(vertical: 10.0),
-                              child: Center(
-                                  child: Text(
-                                '${(balance / 100).toStringAsFixed(2)} Äž1',
-                                style: TextStyle(
-                                    fontSize: 36.0,
-                                    color: balance == 0
-                                        ? Colors.lightBlue
-                                        : Colors.lightBlue,
-                                    fontWeight: FontWeight.bold),
-                              )),
+                              border: Border.all(
+                                  color: Theme.of(context)
+                                      .colorScheme
+                                      .inversePrimary,
+                                  width: 3),
+                              borderRadius: const BorderRadius.only(
+                                topLeft: Radius.circular(8),
+                                topRight: Radius.circular(8),
+                              ),
                             ),
-                            if (!kReleaseMode) TransactionChart()
-                            /*BalanceChart(
+                            child: Scrollbar(
+                                child: ListView(
+                              controller: scrollController,
+                              children: <Widget>[
+                                const Padding(
+                                    padding:
+                                        EdgeInsets.symmetric(horizontal: 16),
+                                    child: Header(
+                                      text: 'balance',
+                                      // topPadding: 0,
+                                    )),
+                                Padding(
+                                  padding: const EdgeInsets.symmetric(
+                                      vertical: 10.0),
+                                  child: Center(
+                                      child: Text(
+                                    '${formatKAmount(balance)} Äž1',
+                                    style: TextStyle(
+                                        fontSize: 36.0,
+                                        color: balance == 0
+                                            ? Colors.lightBlue
+                                            : Colors.lightBlue,
+                                        fontWeight: FontWeight.bold),
+                                  )),
+                                ),
+                                if (!kReleaseMode) TransactionChart()
+                                /*BalanceChart(
                                     transactions: .transactions),*/
-                          ],
-                        )),
-                      )))
-        ]);
+                              ],
+                            )),
+                          )))
+            ]));
       } else {
         return const LoadingScreen();
       }
diff --git a/lib/ui/widgets/third_screen/contacts_page.dart b/lib/ui/widgets/third_screen/contacts_page.dart
index b9589f6cd5be377f85435fd1565a2af696bf269e..19c0bdd892f7932446dc489bb02830e48ee74d6f 100644
--- a/lib/ui/widgets/third_screen/contacts_page.dart
+++ b/lib/ui/widgets/third_screen/contacts_page.dart
@@ -138,10 +138,10 @@ class _ContactsPageState extends State<ContactsPage> {
                             : null,
                         leading: avatar(
                           contact.avatar,
-                          bgColor: tileColor(index),
-                          color: tileColor(index, true),
+                          bgColor: tileColor(index, context),
+                          color: tileColor(index, context, true),
                         ),
-                        tileColor: tileColor(index),
+                        tileColor: tileColor(index, context),
                       ),
                     );
                   },
diff --git a/pubspec.lock b/pubspec.lock
index e6a83fdc51864e5580e7033d6467234fda20534a..34bcdc43e160763e68ea388ba8afa506a12b2bc7 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -49,6 +49,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "2.10.0"
+  backdrop:
+    dependency: "direct main"
+    description:
+      name: backdrop
+      sha256: fdef5a7c1b601a20484df607d852757ebc57f4959832ba77cde5e4d736c91900
+      url: "https://pub.dev"
+    source: hosted
+    version: "0.8.1"
   bip32_ed25519:
     dependency: transitive
     description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 33f80a245e8a0915b3a91aa2e25f04fa873d868c..b9d39b4725643211384a00f43eb3d7374ca1c0cc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -62,6 +62,7 @@ dependencies:
   timeago: ^3.3.0
   once: ^1.5.1
   pattern_lock: ^2.0.0
+  backdrop: ^0.8.1
 
 dev_dependencies:
   flutter_test:
diff --git a/web/favicon.ico b/web/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..02c4440d0e540f7d28fa188e6a47d7c573c5c5ea
Binary files /dev/null and b/web/favicon.ico differ
diff --git a/web/favicon.png b/web/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..bc6aa05607752193de7656dc5420aa5d5a12069a
Binary files /dev/null and b/web/favicon.png differ
diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png
new file mode 100644
index 0000000000000000000000000000000000000000..e58fd125e0483446a22bd4fae74821fe5f38f732
Binary files /dev/null and b/web/icons/Icon-192.png differ
diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png
new file mode 100644
index 0000000000000000000000000000000000000000..c0f49fdf9aa9f6154a36525aca939ce1d54d103d
Binary files /dev/null and b/web/icons/Icon-512.png differ
diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png
new file mode 100644
index 0000000000000000000000000000000000000000..74464e32bcd52b0f6cf8c8f84c4045b31a10c81b
Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ
diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png
new file mode 100644
index 0000000000000000000000000000000000000000..63122823a15081454802ffe5434054073033bf79
Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ
diff --git a/web/index.html b/web/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..583fb498184d110fa735902723a6906a7139032b
--- /dev/null
+++ b/web/index.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <!--
+    If you are serving your web app in a path other than the root, change the
+    href value below to reflect the base path you are serving from.
+
+    The path provided below has to start and end with a slash "/" in order for
+    it to work correctly.
+
+    For more details:
+    * https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
+
+    This is a placeholder for base href that will be replaced by the value of
+    the `--base-href` argument provided to `flutter build`.
+  -->
+  <base href="$FLUTTER_BASE_HREF">
+
+  <meta charset="UTF-8">
+  <meta content="IE=Edge" http-equiv="X-UA-Compatible">
+  <meta content="Äž1nkgo" name="description">
+
+  <!-- iOS meta tags & icons -->
+  <meta name="apple-mobile-web-app-capable" content="yes">
+  <meta name="apple-mobile-web-app-status-bar-style" content="black">
+  <meta name="apple-mobile-web-app-title" content="Äžinkgo">
+  <link rel="apple-touch-icon" href="icons/Icon-192.png">
+
+  <!-- Favicon -->
+  <link rel="icon" type="image/png" href="favicon.png"/>
+
+  <title>Äžinkgo</title>
+  <link rel="manifest" href="manifest.json">
+
+    <style>
+  #splash-container {
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+  }
+
+    </style>
+  <script>
+    // The value below is injected by flutter build, do not touch.
+    var serviceWorkerVersion = null;
+  </script>
+  <!-- This script adds the flutter initialization JS code -->
+  <script src="flutter.js" defer></script>
+</head>
+<body>
+<div id="splash-container">
+    <img alt="Logo" src="assets/img/logo.png">
+</div>
+  <script>
+    window.addEventListener('load', function(ev) {
+      // Download main.dart.js
+      _flutter.loader.loadEntrypoint({
+        serviceWorker: {
+          serviceWorkerVersion: serviceWorkerVersion,
+        },
+        onEntrypointLoaded: function(engineInitializer) {
+          engineInitializer.initializeEngine().then(function(appRunner) {
+            appRunner.runApp();
+          });
+        }
+      });
+    });
+  </script>
+</body>
+</html>
diff --git a/web/manifest.json b/web/manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..88c69a4a38616fdebe16349c8e768189918ffa30
--- /dev/null
+++ b/web/manifest.json
@@ -0,0 +1,35 @@
+{
+    "name": "G1nkgo",
+    "short_name": "G1nkgo",
+    "start_url": ".",
+    "display": "standalone",
+    "background_color": "#0175C2",
+    "theme_color": "#0175C2",
+    "description": "Äž1nkgo (aka Ginkgo) is a lightweight Äž1 wallet",
+    "orientation": "portrait-primary",
+    "prefer_related_applications": false,
+    "icons": [
+        {
+            "src": "icons/Icon-192.png",
+            "sizes": "192x192",
+            "type": "image/png"
+        },
+        {
+            "src": "icons/Icon-512.png",
+            "sizes": "512x512",
+            "type": "image/png"
+        },
+        {
+            "src": "icons/Icon-maskable-192.png",
+            "sizes": "192x192",
+            "type": "image/png",
+            "purpose": "maskable"
+        },
+        {
+            "src": "icons/Icon-maskable-512.png",
+            "sizes": "512x512",
+            "type": "image/png",
+            "purpose": "maskable"
+        }
+    ]
+}