diff --git a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
index ccf4bf2ba..324a3d02a 100644
--- a/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
+++ b/lib/pages/settings_views/global_settings_view/manage_nodes_views/add_edit_node_view.dart
@@ -10,6 +10,7 @@
 
 import 'dart:async';
 
+import 'package:barcode_scan2/barcode_scan2.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -26,6 +27,8 @@ import '../../../../utilities/assets.dart';
 import '../../../../utilities/constants.dart';
 import '../../../../utilities/enums/sync_type_enum.dart';
 import '../../../../utilities/flutter_secure_storage_interface.dart';
+import '../../../../utilities/logger.dart';
+import '../../../../utilities/node_uri_util.dart';
 import '../../../../utilities/test_node_connection.dart';
 import '../../../../utilities/text_styles.dart';
 import '../../../../utilities/tor_plain_net_option_enum.dart';
@@ -38,7 +41,9 @@ import '../../../../widgets/conditional_parent.dart';
 import '../../../../widgets/custom_buttons/app_bar_icon_button.dart';
 import '../../../../widgets/desktop/desktop_dialog.dart';
 import '../../../../widgets/desktop/primary_button.dart';
+import '../../../../widgets/desktop/qr_code_scanner_dialog.dart';
 import '../../../../widgets/desktop/secondary_button.dart';
+import '../../../../widgets/icon_widgets/qrcode_icon.dart';
 import '../../../../widgets/icon_widgets/x_icon.dart';
 import '../../../../widgets/stack_dialog.dart';
 import '../../../../widgets/stack_text_field.dart';
@@ -73,6 +78,8 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
   late final String? nodeId;
   late final bool isDesktop;
 
+  (NodeModel, String)? _scannedResult;
+
   late bool saveEnabled;
   late bool testConnectionEnabled;
 
@@ -330,6 +337,77 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
     }
   }
 
+  void _scanQr() async {
+    if (Util.isDesktop) {
+      try {
+        await showDialog<void>(
+          context: context,
+          builder: (context) {
+            return QrCodeScannerDialog(
+              onQrCodeDetected: (qrCodeData) {
+                try {
+                  _processQrData(qrCodeData);
+                } catch (e, s) {
+                  Logging.instance.log(
+                    "Error processing QR code data: $e\n$s",
+                    level: LogLevel.Error,
+                  );
+                }
+              },
+            );
+          },
+        );
+      } catch (e, s) {
+        Logging.instance.log(
+          "Error opening QR code scanner dialog: $e\n$s",
+          level: LogLevel.Error,
+        );
+      }
+    } else {
+      try {
+        final result = await BarcodeScanner.scan();
+        await _processQrData(result.rawContent);
+      } catch (e, s) {
+        Logging.instance.log(
+          "$e\n$s",
+          level: LogLevel.Warning,
+        );
+      }
+    }
+  }
+
+  Future<void> _processQrData(String data) async {
+    try {
+      final nodeQrData = NodeQrUtil.decodeUri(data);
+      if (mounted) {
+        setState(() {
+          _scannedResult = (
+            NodeModel(
+              host: nodeQrData.host,
+              port: nodeQrData.port,
+              name: nodeQrData.label ?? "",
+              id: const Uuid().v1(),
+              useSSL: nodeQrData.scheme == "https",
+              enabled: true,
+              coinName: coin.identifier,
+              isFailover: true,
+              isDown: false,
+              torEnabled: true,
+              clearnetEnabled: !nodeQrData.host.endsWith(".onion"),
+              loginName: (nodeQrData as LibMoneroNodeQrData?)?.user,
+            ),
+            (nodeQrData as LibMoneroNodeQrData?)?.password ?? ""
+          );
+        });
+      }
+    } catch (e, s) {
+      Logging.instance.log(
+        "$e\n$s",
+        level: LogLevel.Warning,
+      );
+    }
+  }
+
   @override
   void initState() {
     isDesktop = Util.isDesktop;
@@ -390,6 +468,35 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
               style: STextStyles.navBarTitle(context),
             ),
             actions: [
+              if (viewType == AddEditNodeViewType.add &&
+                  coin
+                      is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future
+                Padding(
+                  padding: const EdgeInsets.only(
+                    top: 10,
+                    bottom: 10,
+                    right: 10,
+                  ),
+                  child: AspectRatio(
+                    aspectRatio: 1,
+                    child: AppBarIconButton(
+                      key: const Key("qrNodeAppBarButtonKey"),
+                      size: 36,
+                      shadows: const [],
+                      color: Theme.of(context)
+                          .extension<StackColors>()!
+                          .background,
+                      icon: QrCodeIcon(
+                        width: 20,
+                        height: 20,
+                        color: Theme.of(context)
+                            .extension<StackColors>()!
+                            .accentColorDark,
+                      ),
+                      onPressed: _scanQr,
+                    ),
+                  ),
+                ),
               if (viewType == AddEditNodeViewType.edit &&
                   ref
                           .watch(
@@ -473,19 +580,47 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
           child: Column(
             mainAxisSize: MainAxisSize.min,
             children: [
+              const SizedBox(
+                height: 8,
+              ),
               Row(
+                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                 children: [
-                  const SizedBox(
-                    width: 8,
-                  ),
-                  const AppBarBackButton(
-                    iconSize: 24,
-                    size: 40,
-                  ),
-                  Text(
-                    "Add new node",
-                    style: STextStyles.desktopH3(context),
+                  Row(
+                    children: [
+                      const SizedBox(
+                        width: 8,
+                      ),
+                      const AppBarBackButton(
+                        iconSize: 24,
+                        size: 40,
+                      ),
+                      Text(
+                        "Add new node",
+                        style: STextStyles.desktopH3(context),
+                      ),
+                    ],
                   ),
+                  if (coin
+                      is CryptonoteCurrency) // TODO: [prio=low] do something other than `coin is CryptonoteCurrency` in the future
+                    Padding(
+                      padding: const EdgeInsets.only(right: 32),
+                      child: AppBarIconButton(
+                        size: 40,
+                        color: isDesktop
+                            ? Theme.of(context)
+                                .extension<StackColors>()!
+                                .textFieldDefaultBG
+                            : Theme.of(context)
+                                .extension<StackColors>()!
+                                .background,
+                        icon: const QrCodeIcon(
+                          width: 21,
+                          height: 21,
+                        ),
+                        onPressed: _scanQr,
+                      ),
+                    ),
                 ],
               ),
               Padding(
@@ -504,7 +639,9 @@ class _AddEditNodeViewState extends ConsumerState<AddEditNodeView> {
           crossAxisAlignment: CrossAxisAlignment.stretch,
           children: [
             NodeForm(
-              node: node,
+              key: Key((node ?? _scannedResult?.$1)?.id ?? "none"),
+              node: node ?? _scannedResult?.$1,
+              scannedPw: _scannedResult?.$2,
               secureStore: ref.read(secureStoreProvider),
               readOnly: false,
               coin: widget.coin,
@@ -629,6 +766,7 @@ class NodeForm extends ConsumerStatefulWidget {
   const NodeForm({
     super.key,
     this.node,
+    this.scannedPw,
     required this.secureStore,
     required this.readOnly,
     required this.coin,
@@ -636,6 +774,7 @@ class NodeForm extends ConsumerStatefulWidget {
   });
 
   final NodeModel? node;
+  final String? scannedPw;
   final SecureStorageInterface secureStore;
   final bool readOnly;
   final CryptoCurrency coin;
@@ -738,13 +877,15 @@ class _NodeFormState extends ConsumerState<NodeForm> {
     if (widget.node != null) {
       final node = widget.node!;
       if (enableAuthFields) {
-        node.getPassword(widget.secureStore).then((value) {
-          if (value is String) {
-            _passwordController.text = value;
-          }
-        });
-
-        _usernameController.text = node.loginName ?? "";
+        if (widget.scannedPw == null) {
+          node.getPassword(widget.secureStore).then((value) {
+            if (value is String) {
+              _passwordController.text = value;
+            }
+          });
+        } else {
+          _passwordController.text = widget.scannedPw!;
+        }
       }
 
       _nameController.text = node.name;