From 5ec0e264ced153fee9e195533a8c9842915870f8 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Wed, 4 Sep 2024 11:06:52 -0700
Subject: [PATCH 1/7] [skip ci] wip adress generation

---
 .github/workflows/pr_test_build_android.yml   |   1 +
 cw_bitcoin/lib/litecoin_wallet_addresses.dart | 102 ++++++++++++++++--
 cw_bitcoin/pubspec.yaml                       |   5 +
 3 files changed, 102 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index fb44b2fde..904802f26 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -112,6 +112,7 @@ jobs:
           # build mwebd:
           cd /opt/android/cake_wallet
           git clone https://github.com/ltcmweb/mwebd
+          git reset --hard 49c42597ce5036fe1065200c3c056d0aba5f1a58
           cd /opt/android/cake_wallet/mwebd
           gomobile bind -target=android -androidapi 21 .
           mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index 7db9d7bae..49ca81476 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -1,4 +1,3 @@
-import 'package:convert/convert.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/utils.dart';
@@ -8,10 +7,88 @@ import 'package:cw_mweb/cw_mweb.dart';
 import 'package:cw_mweb/mwebd.pb.dart';
 import 'package:mobx/mobx.dart';
 
+import 'dart:typed_data';
+import 'package:bech32/bech32.dart';
+import 'package:r_crypto/r_crypto.dart';
+
 part 'litecoin_wallet_addresses.g.dart';
 
-class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
 
+
+
+class Keychain {
+  final ECPrivate scan;
+  ECPrivate? spend;
+  ECPublic? spendPubKey;
+
+
+  Keychain({required this.scan, this.spend, this.spendPubKey}) {
+    if (this.spend != null) {
+      spendPubKey = this.spend!.getPublic();
+    }
+  }
+
+
+  static const HashTagAddress = 'A';
+
+  ECPrivate mi(int index) {
+    final input = BytesBuilder();
+
+    // Write HashTagAddress to the input
+    input.addByte(HashTagAddress.codeUnitAt(0));
+
+    // Write index to the input in little endian
+    final indexBytes = Uint8List(4);
+    final byteData = ByteData.view(indexBytes.buffer);
+    byteData.setUint32(0, index, Endian.little);
+    input.add(indexBytes);
+
+    // Write scan to the input
+    input.add(scan.prive.raw);
+
+    // Hash the input using Blake3 with a length of 32 bytes
+    final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
+
+    // Return the hash digest
+    var res = Uint8List.fromList(hash);
+    return ECPrivate.fromBytes(res);
+  }
+
+  Keychain address(int index) {
+
+    final miPub = this.mi(index).getPublic();
+    final Bi = spendPubKey!.pubkeyAdd(miPub);
+    final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
+    // final miPubKey = ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
+    // final Bi = spendPubKey + miPubKey;
+    // return Uint8List.fromList(Ai.getEncoded(compressed: true) + Bi.getEncoded(compressed: true));
+    final AiPriv = ECPrivate.fromBytes(Ai.toBytes());
+    final BiPriv = ECPrivate.fromBytes(Bi.toBytes());
+
+    return Keychain(scan: AiPriv, spend: BiPriv);
+  }
+
+  String addressString(int index) {
+    final address = this.address(index);
+    List<int> bytes = [];
+    bytes.addAll(address.scan.toBytes());
+    bytes.addAll(address.spend!.toBytes());
+    return encodeMwebAddress(bytes);
+  }
+
+  // Uint8List spendKey(int index) {
+  //   final mi = this.mi(index);
+  //   final spendKey = spend + ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
+  //   return spendKey.getEncoded(compressed: true);
+  // }
+
+  String encodeMwebAddress(List<int> scriptPubKey) {
+    return bech32.encode(Bech32("ltcmweb", scriptPubKey));
+  }
+}
+
+
+class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
 abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
   LitecoinWalletAddressesBase(
     WalletInfo walletInfo, {
@@ -40,21 +117,34 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
       mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
 
   List<String> mwebAddrs = [];
+  List<String> oldMwebAddrs = [];
+
 
   Future<void> topUpMweb(int index) async {
     final stub = await CwMweb.stub();
-    while (mwebAddrs.length - index < 1000) {
-      final length = mwebAddrs.length;
+    while (oldMwebAddrs.length - index < 1000) {
+      final length = oldMwebAddrs.length;
       final resp = await stub.addresses(AddressRequest(
         fromIndex: length,
         toIndex: index + 1000,
         scanSecret: scanSecret,
         spendPubkey: spendPubkey,
       ));
-      if (mwebAddrs.length == length) {
-        mwebAddrs.addAll(resp.address);
+      if (oldMwebAddrs.length == length) {
+        oldMwebAddrs.addAll(resp.address);
       }
     }
+
+
+    Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
+
+
+    for (int i = 0; i < 10; i++) {
+      final address = k.addressString(i + 1000);
+      mwebAddrs.add(address);
+    }
+    print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
+
   }
 
   @override
diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index 29d178319..b121a9538 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -41,6 +41,10 @@ dependencies:
     git:
       url: https://github.com/rafael-xmr/sp_scanner
       ref: sp_v4.0.0
+  bech32:
+    git:
+      url: https://github.com/cake-tech/bech32.git
+  r_crypto: ^0.5.0
 
 dev_dependencies:
   flutter_test:
@@ -62,6 +66,7 @@ dependency_overrides:
       url: https://github.com/cake-tech/bitcoin_base
       ref: cake-update-v6
   pointycastle: 3.7.4
+  ffi: 2.1.0
 
 # For information on the generic Dart part of this file, see the
 # following page: https://dart.dev/tools/pub/pubspec

From 7b5c36e5a714e5aa4788656a158289a258ba41dd Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Wed, 4 Sep 2024 15:50:56 -0700
Subject: [PATCH 2/7] wip

---
 cw_bitcoin/lib/litecoin_wallet_addresses.dart | 139 +++++++++--------
 .../com/cakewallet/mweb/CwMwebPlugin.kt       |   6 +
 cw_mweb/ios/Classes/CwMwebPlugin.swift        | 144 ++++++++++--------
 cw_mweb/lib/cw_mweb.dart                      |   9 ++
 cw_mweb/lib/cw_mweb_method_channel.dart       |  10 ++
 cw_mweb/lib/cw_mweb_platform_interface.dart   |   4 +
 pubspec_base.yaml                             |   1 +
 7 files changed, 185 insertions(+), 128 deletions(-)

diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index 49ca81476..c0940ca5d 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -1,4 +1,6 @@
+import 'package:bech32/bech32.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:blockchain_utils/bech32/bech32_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/utils.dart';
 import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
@@ -7,88 +9,91 @@ import 'package:cw_mweb/cw_mweb.dart';
 import 'package:cw_mweb/mwebd.pb.dart';
 import 'package:mobx/mobx.dart';
 
-import 'dart:typed_data';
-import 'package:bech32/bech32.dart';
-import 'package:r_crypto/r_crypto.dart';
+// import 'dart:typed_data';
+// import 'package:bech32/bech32.dart';
+// import 'package:r_crypto/r_crypto.dart';
 
 part 'litecoin_wallet_addresses.g.dart';
 
+// class Keychain {
+//   // ECPrivate scan;
+//   // ECPrivate? spend;
+//   ECPrivate scan;
+//   ECPrivate? spend;
+//   ECPublic? spendPubKey;
 
+//   Keychain({required this.scan, this.spend, this.spendPubKey}) {
+//     if (this.spend != null) {
+//       spendPubKey = this.spend!.getPublic();
+//     }
+//   }
 
+//   static const HashTagAddress = 'A';
 
-class Keychain {
-  final ECPrivate scan;
-  ECPrivate? spend;
-  ECPublic? spendPubKey;
+//   ECPrivate mi(int index) {
+//     final input = BytesBuilder();
 
+//     // Write HashTagAddress to the input
+//     input.addByte(HashTagAddress.codeUnitAt(0));
 
-  Keychain({required this.scan, this.spend, this.spendPubKey}) {
-    if (this.spend != null) {
-      spendPubKey = this.spend!.getPublic();
-    }
-  }
+//     // Write index to the input in little endian
+//     final indexBytes = Uint8List(4);
+//     final byteData = ByteData.view(indexBytes.buffer);
+//     byteData.setUint32(0, index, Endian.little);
+//     input.add(indexBytes);
 
+//     // Write scan to the input
+//     input.add(scan.prive.raw);
 
-  static const HashTagAddress = 'A';
+//     // Hash the input using Blake3 with a length of 32 bytes
+//     final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
 
-  ECPrivate mi(int index) {
-    final input = BytesBuilder();
+//     // Return the hash digest
+//     var res = Uint8List.fromList(hash);
+//     return ECPrivate.fromBytes(res);
+//   }
 
-    // Write HashTagAddress to the input
-    input.addByte(HashTagAddress.codeUnitAt(0));
+//   Keychain address(int index) {
 
-    // Write index to the input in little endian
-    final indexBytes = Uint8List(4);
-    final byteData = ByteData.view(indexBytes.buffer);
-    byteData.setUint32(0, index, Endian.little);
-    input.add(indexBytes);
+//     final miPub = this.mi(index).getPublic();
+//     final Bi = spendPubKey!.pubkeyAdd(miPub);
+//     // final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
+//     final Ai = Bi.tweakMul(scan.toBigInt());
 
-    // Write scan to the input
-    input.add(scan.prive.raw);
+//     // final miPubKey = ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
+//     // final Bi = spendPubKey + miPubKey;
+//     // return Uint8List.fromList(Ai.getEncoded(compressed: true) + Bi.getEncoded(compressed: true));
+//     final AiPriv = ECPrivate.fromBytes(Ai.toBytes());
+//     final BiPriv = ECPrivate.fromBytes(Bi.toBytes());
 
-    // Hash the input using Blake3 with a length of 32 bytes
-    final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
+//     return Keychain(scan: AiPriv, spend: BiPriv);
+//   }
 
-    // Return the hash digest
-    var res = Uint8List.fromList(hash);
-    return ECPrivate.fromBytes(res);
-  }
+//   String addressString(int index) {
+//     final address = this.address(index);
+//     List<int> bytes = [];
+//     bytes.addAll(address.scan.toBytes());
+//     bytes.addAll(address.spend!.toBytes());
+//     return encodeMwebAddress(bytes);
+//   }
 
-  Keychain address(int index) {
+//   // Uint8List spendKey(int index) {
+//   //   final mi = this.mi(index);
+//   //   final spendKey = spend + ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
+//   //   return spendKey.getEncoded(compressed: true);
+//   // }
 
-    final miPub = this.mi(index).getPublic();
-    final Bi = spendPubKey!.pubkeyAdd(miPub);
-    final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
-    // final miPubKey = ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
-    // final Bi = spendPubKey + miPubKey;
-    // return Uint8List.fromList(Ai.getEncoded(compressed: true) + Bi.getEncoded(compressed: true));
-    final AiPriv = ECPrivate.fromBytes(Ai.toBytes());
-    final BiPriv = ECPrivate.fromBytes(Bi.toBytes());
+//   String encodeMwebAddress(List<int> scriptPubKey) {
+//     return bech32.encode(Bech32("ltcmweb", scriptPubKey));
+//   }
+// }
 
-    return Keychain(scan: AiPriv, spend: BiPriv);
-  }
-
-  String addressString(int index) {
-    final address = this.address(index);
-    List<int> bytes = [];
-    bytes.addAll(address.scan.toBytes());
-    bytes.addAll(address.spend!.toBytes());
-    return encodeMwebAddress(bytes);
-  }
-
-  // Uint8List spendKey(int index) {
-  //   final mi = this.mi(index);
-  //   final spendKey = spend + ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
-  //   return spendKey.getEncoded(compressed: true);
-  // }
-
-  String encodeMwebAddress(List<int> scriptPubKey) {
-    return bech32.encode(Bech32("ltcmweb", scriptPubKey));
-  }
+String encodeMwebAddress(List<int> scriptPubKey) {
+  return bech32.encode(Bech32("ltcmweb1", scriptPubKey), 250);
 }
 
-
 class LitecoinWalletAddresses = LitecoinWalletAddressesBase with _$LitecoinWalletAddresses;
+
 abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with Store {
   LitecoinWalletAddressesBase(
     WalletInfo walletInfo, {
@@ -119,7 +124,6 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
   List<String> mwebAddrs = [];
   List<String> oldMwebAddrs = [];
 
-
   Future<void> topUpMweb(int index) async {
     final stub = await CwMweb.stub();
     while (oldMwebAddrs.length - index < 1000) {
@@ -135,16 +139,19 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
       }
     }
 
-
-    Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
-
+    // Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
 
     for (int i = 0; i < 10; i++) {
-      final address = k.addressString(i + 1000);
+      // final address = k.addressString(i + 1000);
+      final addressHex =
+          await CwMweb.address(hex.encode(scanSecret), hex.encode(spendPubkey), index);
+      // print(addressHex);
+      // print(hex.decode(addressHex!).length);
+      // return;
+      final address = encodeMwebAddress(hex.decode(addressHex!));
       mwebAddrs.add(address);
     }
     print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
-
   }
 
   @override
diff --git a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
index b1180dd4a..228725ef1 100644
--- a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
+++ b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
@@ -40,6 +40,12 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
       server = null
       port = null
       result.success(null)
+    } else if (call.method == "address") {
+      val scanSecret: String = call.argument<String>("scanSecret") ?: ""
+      val spendPub: String = call.argument<String>("spendPub") ?: ""
+      val index: Int = call.argument<Int>("index") ?: 0
+      val res = Mwebd.addressIndex(scanSecret, spendPub)
+      result.success(res)
     } else {
       result.notImplemented()
     }
diff --git a/cw_mweb/ios/Classes/CwMwebPlugin.swift b/cw_mweb/ios/Classes/CwMwebPlugin.swift
index ed08d6748..e68344a4b 100644
--- a/cw_mweb/ios/Classes/CwMwebPlugin.swift
+++ b/cw_mweb/ios/Classes/CwMwebPlugin.swift
@@ -3,70 +3,90 @@ import UIKit
 import Mwebd
 
 public class CwMwebPlugin: NSObject, FlutterPlugin {
-  public static func register(with registrar: FlutterPluginRegistrar) {
-    let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger())
-    let instance = CwMwebPlugin()
-    registrar.addMethodCallDelegate(instance, channel: channel)
-  }
+public static func register(with registrar: FlutterPluginRegistrar) {
+        let channel = FlutterMethodChannel(name: "cw_mweb", binaryMessenger: registrar.messenger())
+        let instance = CwMwebPlugin()
+        registrar.addMethodCallDelegate(instance, channel: channel)
+    }
 
-  private static var server: MwebdServer?
-  private static var port: Int = 0
-  private static var dataDir: String?
-    
-  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
-      switch call.method {
-        case "getPlatformVersion":
-            result("iOS " + UIDevice.current.systemVersion)
-        case "start":
-            stopServer()
-            let args = call.arguments as? [String: String]
-            let dataDir = args?["dataDir"]
-            CwMwebPlugin.dataDir = dataDir
-            startServer(result: result)
-        case "stop":
-            stopServer()
-            result(nil)
-        default:
-            result(FlutterMethodNotImplemented)
-      }
-  }
+    private static var server: MwebdServer?
+    private static var port: Int = 0
+    private static var dataDir: String?
 
-  private func startServer(result: @escaping FlutterResult) {
-      if CwMwebPlugin.server == nil {
-          var error: NSError?
-          CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, "", &error)
-          
-          if let server = CwMwebPlugin.server {
-              do {
-                  print("Starting server...")
-                  try server.start(0, ret0_: &CwMwebPlugin.port)
-                  print("Server started successfully on port: \(CwMwebPlugin.port)")
-                  result(CwMwebPlugin.port)
-              } catch let startError as NSError {
-                  print("Server Start Error: \(startError.localizedDescription)")
-                  result(FlutterError(code: "Server Start Error", message: startError.localizedDescription, details: nil))
-              }
-          } else if let error = error {
-              print("Server Creation Error: \(error.localizedDescription)")
-              result(FlutterError(code: "Server Creation Error", message: error.localizedDescription, details: nil))
-          } else {
-              print("Unknown Error: Failed to create server")
-              result(FlutterError(code: "Unknown Error", message: "Failed to create server", details: nil))
-          }
-      } else {
-          print("Server already running on port: \(CwMwebPlugin.port)")
-          result(CwMwebPlugin.port)
-      }
-  }
+    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
+        switch call.method {
+            case "getPlatformVersion":
+                result("iOS " + UIDevice.current.systemVersion)
+                break
+            case "start":
+                stopServer()
+                let args = call.arguments as? [String: String]
+                let dataDir = args?["dataDir"]
+                CwMwebPlugin.dataDir = dataDir
+                startServer(result: result)
+                break
+            case "stop":
+                stopServer()
+                result(nil)
+                break
+            case "address":
+                let args = call.arguments as? [String: String]
+                let scanSecret = args?["scanSecret"]
+                let spendPub = args?["spendPub"]
+                let index = args?["index"]
+                result(address(scanSecret, spendPub, index))
+                break
+            default:
+                result(FlutterMethodNotImplemented)
+                break
+        }
+    }
 
-  private func stopServer() {
-      print("Stopping server")
-      CwMwebPlugin.server?.stop()
-      CwMwebPlugin.server = nil
-      CwMwebPlugin.port = 0
-  }
+    private func startServer(result: @escaping FlutterResult) {
+        if CwMwebPlugin.server == nil {
+            var error: NSError?
+            CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, "", &error)
 
-  deinit {
-      stopServer()
-  }
+            if let server = CwMwebPlugin.server {
+                do {
+                    print("Starting server...")
+                try server.start(0, ret0_: &CwMwebPlugin.port)
+                    print("Server started successfully on port: \(CwMwebPlugin.port)")
+                    result(CwMwebPlugin.port)
+                } catch let startError as NSError {
+                    print("Server Start Error: \(startError.localizedDescription)")
+                    result(FlutterError(code: "Server Start Error", message: startError.localizedDescription, details: nil))
+                }
+            } else if let error = error {
+                print("Server Creation Error: \(error.localizedDescription)")
+                result(FlutterError(code: "Server Creation Error", message: error.localizedDescription, details: nil))
+            } else {
+                print("Unknown Error: Failed to create server")
+                result(FlutterError(code: "Unknown Error", message: "Failed to create server", details: nil))
+            }
+        } else {
+            print("Server already running on port: \(CwMwebPlugin.port)")
+            result(CwMwebPlugin.port)
+        }
+    }
+
+    private func stopServer() {
+        print("Stopping server")
+        CwMwebPlugin.server?.stop()
+        CwMwebPlugin.server = nil
+        CwMwebPlugin.port = 0
+    }
+
+    private func address(_ scanSecret: String?, _ spendPub: String?, _ index: Int?) -> String? {
+        guard let scanSecret = scanSecret, let spendPub = spendPub, let index = index else {
+            print("Invalid arguments for address function")
+            return nil
+        }
+
+        return MwebdAddressIndex(scanSecret, spendPub, UInt32(index))
+    }
+
+    deinit {
+        stopServer()
+    }
 }
\ No newline at end of file
diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart
index df3300379..46ae512a0 100644
--- a/cw_mweb/lib/cw_mweb.dart
+++ b/cw_mweb/lib/cw_mweb.dart
@@ -53,6 +53,15 @@ class CwMweb {
     await cleanup();
   }
 
+  static Future<String?> address(String scanSecret, String spendPub, int index) async {
+    // try {
+    //   return (await CwMwebPlatform.instance.address(scan, spendPub, index))!;
+    // } catch (e) {
+    //   print("error generating address!: $e");
+    // }
+    return CwMwebPlatform.instance.address(scanSecret, spendPub, index);
+  }
+
   static Future<void> cleanup() async {
     await _clientChannel?.terminate();
     _rpcClient = null;
diff --git a/cw_mweb/lib/cw_mweb_method_channel.dart b/cw_mweb/lib/cw_mweb_method_channel.dart
index 9451db310..6f7ad2279 100644
--- a/cw_mweb/lib/cw_mweb_method_channel.dart
+++ b/cw_mweb/lib/cw_mweb_method_channel.dart
@@ -19,4 +19,14 @@ class MethodChannelCwMweb extends CwMwebPlatform {
   Future<void> stop() async {
     await methodChannel.invokeMethod<void>('stop');
   }
+
+  @override
+  Future<String?> address(String scanSecret, String spendPub, int index) async {
+    final result = await methodChannel.invokeMethod<String>('address', {
+      'scanSecret': scanSecret,
+      'spendPub': spendPub,
+      'index': index,
+    });
+    return result;
+  }
 }
diff --git a/cw_mweb/lib/cw_mweb_platform_interface.dart b/cw_mweb/lib/cw_mweb_platform_interface.dart
index a5a46adbc..a63319341 100644
--- a/cw_mweb/lib/cw_mweb_platform_interface.dart
+++ b/cw_mweb/lib/cw_mweb_platform_interface.dart
@@ -30,4 +30,8 @@ abstract class CwMwebPlatform extends PlatformInterface {
   Future<void> stop() {
     throw UnimplementedError('stop() has not been implemented.');
   }
+
+  Future<String?> address(String scanSecret, String spendPub, int index) {
+    throw UnimplementedError('address(int) has not been implemented.');
+  }
 }
diff --git a/pubspec_base.yaml b/pubspec_base.yaml
index 6e07b989b..f05654009 100644
--- a/pubspec_base.yaml
+++ b/pubspec_base.yaml
@@ -136,6 +136,7 @@ dependency_overrides:
     git:
       url: https://github.com/cake-tech/bitcoin_base
       ref: cake-update-v6
+  ffi: 2.1.0
 
 flutter_icons:
   image_path: "assets/images/app_logo.png"

From aa6cac897e9bbd8479bd79f02708438be8946ecc Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Wed, 4 Sep 2024 17:48:56 -0700
Subject: [PATCH 3/7] wip

---
 cw_bitcoin/lib/electrum_wallet.dart           |  11 +-
 cw_bitcoin/lib/electrum_wallet_addresses.dart |   3 +-
 cw_bitcoin/lib/litecoin_wallet_addresses.dart | 133 ++++++------------
 cw_bitcoin/pubspec.yaml                       |   1 -
 .../com/cakewallet/mweb/CwMwebPlugin.kt       |   4 +-
 5 files changed, 54 insertions(+), 98 deletions(-)

diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 521384e53..ea99c6cd8 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -4,6 +4,7 @@ import 'dart:io';
 import 'dart:isolate';
 
 import 'package:bitcoin_base/bitcoin_base.dart';
+import 'package:cw_bitcoin/litecoin_wallet_addresses.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 import 'package:cw_core/encryption_file_utils.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
@@ -795,7 +796,10 @@ abstract class ElectrumWalletBase
       throw BitcoinTransactionWrongBalanceException();
     }
 
-    final changeAddress = await walletAddresses.getChangeAddress();
+    final changeAddress = await walletAddresses.getChangeAddress(
+      outputs: outputs,
+      utxoDetails: utxoDetails,
+    );
     final address = addressTypeFromStr(changeAddress, network);
     outputs.add(BitcoinOutput(
       address: address,
@@ -2061,7 +2065,8 @@ abstract class ElectrumWalletBase
       _isTryingToConnect = true;
 
       Timer(Duration(seconds: 10), () {
-        if (this.syncStatus is NotConnectedSyncStatus || this.syncStatus is LostConnectionSyncStatus) {
+        if (this.syncStatus is NotConnectedSyncStatus ||
+            this.syncStatus is LostConnectionSyncStatus) {
           this.electrumClient.connectToUri(
                 node!.uri,
                 useSSL: node!.useSSL ?? false,
@@ -2387,6 +2392,8 @@ class PublicKeyWithDerivationPath {
 }
 
 BitcoinBaseAddress addressTypeFromStr(String address, BasedUtxoNetwork network) {
+  // print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
+  // print(network);
   if (network is BitcoinCashNetwork) {
     if (!address.startsWith("bitcoincash:") &&
         (address.startsWith("q") || address.startsWith("p"))) {
diff --git a/cw_bitcoin/lib/electrum_wallet_addresses.dart b/cw_bitcoin/lib/electrum_wallet_addresses.dart
index 388b3d468..e442a03e8 100644
--- a/cw_bitcoin/lib/electrum_wallet_addresses.dart
+++ b/cw_bitcoin/lib/electrum_wallet_addresses.dart
@@ -1,6 +1,7 @@
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
 import 'package:cw_bitcoin/bitcoin_address_record.dart';
+import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:cw_core/wallet_addresses.dart';
 import 'package:cw_core/wallet_info.dart';
 import 'package:cw_core/wallet_type.dart';
@@ -239,7 +240,7 @@ abstract class ElectrumWalletAddressesBase extends WalletAddresses with Store {
   }
 
   @action
-  Future<String> getChangeAddress() async {
+  Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
     updateChangeAddresses();
 
     if (changeAddresses.isEmpty) {
diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index c0940ca5d..ed321841e 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -2,6 +2,7 @@ import 'package:bech32/bech32.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/bech32/bech32_base.dart';
 import 'package:blockchain_utils/blockchain_utils.dart';
+import 'package:cw_bitcoin/electrum_wallet.dart';
 import 'package:cw_bitcoin/utils.dart';
 import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
 import 'package:cw_core/wallet_info.dart';
@@ -15,79 +16,6 @@ import 'package:mobx/mobx.dart';
 
 part 'litecoin_wallet_addresses.g.dart';
 
-// class Keychain {
-//   // ECPrivate scan;
-//   // ECPrivate? spend;
-//   ECPrivate scan;
-//   ECPrivate? spend;
-//   ECPublic? spendPubKey;
-
-//   Keychain({required this.scan, this.spend, this.spendPubKey}) {
-//     if (this.spend != null) {
-//       spendPubKey = this.spend!.getPublic();
-//     }
-//   }
-
-//   static const HashTagAddress = 'A';
-
-//   ECPrivate mi(int index) {
-//     final input = BytesBuilder();
-
-//     // Write HashTagAddress to the input
-//     input.addByte(HashTagAddress.codeUnitAt(0));
-
-//     // Write index to the input in little endian
-//     final indexBytes = Uint8List(4);
-//     final byteData = ByteData.view(indexBytes.buffer);
-//     byteData.setUint32(0, index, Endian.little);
-//     input.add(indexBytes);
-
-//     // Write scan to the input
-//     input.add(scan.prive.raw);
-
-//     // Hash the input using Blake3 with a length of 32 bytes
-//     final hash = rHash.hashString(HashType.blake3(length: 32), input.toString());
-
-//     // Return the hash digest
-//     var res = Uint8List.fromList(hash);
-//     return ECPrivate.fromBytes(res);
-//   }
-
-//   Keychain address(int index) {
-
-//     final miPub = this.mi(index).getPublic();
-//     final Bi = spendPubKey!.pubkeyAdd(miPub);
-//     // final Ai = Bi.pubkeyMult(ECPublic.fromBytes(scan.toBytes()));
-//     final Ai = Bi.tweakMul(scan.toBigInt());
-
-//     // final miPubKey = ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
-//     // final Bi = spendPubKey + miPubKey;
-//     // return Uint8List.fromList(Ai.getEncoded(compressed: true) + Bi.getEncoded(compressed: true));
-//     final AiPriv = ECPrivate.fromBytes(Ai.toBytes());
-//     final BiPriv = ECPrivate.fromBytes(Bi.toBytes());
-
-//     return Keychain(scan: AiPriv, spend: BiPriv);
-//   }
-
-//   String addressString(int index) {
-//     final address = this.address(index);
-//     List<int> bytes = [];
-//     bytes.addAll(address.scan.toBytes());
-//     bytes.addAll(address.spend!.toBytes());
-//     return encodeMwebAddress(bytes);
-//   }
-
-//   // Uint8List spendKey(int index) {
-//   //   final mi = this.mi(index);
-//   //   final spendKey = spend + ECCurve_secp256k1().G * BigInt.parse(hex.encode(mi), radix: 16);
-//   //   return spendKey.getEncoded(compressed: true);
-//   // }
-
-//   String encodeMwebAddress(List<int> scriptPubKey) {
-//     return bech32.encode(Bech32("ltcmweb", scriptPubKey));
-//   }
-// }
-
 String encodeMwebAddress(List<int> scriptPubKey) {
   return bech32.encode(Bech32("ltcmweb1", scriptPubKey), 250);
 }
@@ -126,32 +54,28 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
 
   Future<void> topUpMweb(int index) async {
     final stub = await CwMweb.stub();
-    while (oldMwebAddrs.length - index < 1000) {
-      final length = oldMwebAddrs.length;
+    while (mwebAddrs.length - index < 1000) {
+      final length = mwebAddrs.length;
       final resp = await stub.addresses(AddressRequest(
         fromIndex: length,
         toIndex: index + 1000,
         scanSecret: scanSecret,
         spendPubkey: spendPubkey,
       ));
-      if (oldMwebAddrs.length == length) {
-        oldMwebAddrs.addAll(resp.address);
+      if (mwebAddrs.length == length) {
+        mwebAddrs.addAll(resp.address);
       }
     }
 
-    // Keychain k = Keychain(scan: ECPrivate.fromBytes(scanSecret), spendPubKey: ECPublic.fromBytes(spendPubkey),);
-
-    for (int i = 0; i < 10; i++) {
-      // final address = k.addressString(i + 1000);
-      final addressHex =
-          await CwMweb.address(hex.encode(scanSecret), hex.encode(spendPubkey), index);
-      // print(addressHex);
-      // print(hex.decode(addressHex!).length);
-      // return;
-      final address = encodeMwebAddress(hex.decode(addressHex!));
-      mwebAddrs.add(address);
-    }
-    print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
+    // for (int i = 0; i < 10; i++) {
+    //   final address = await CwMweb.address(
+    //     hex.encode(scanSecret),
+    //     hex.encode(spendPubkey),
+    //     index + 1000,
+    //   );
+    //   mwebAddrs.add(address!);
+    // }
+    // print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
   }
 
   @override
@@ -185,11 +109,38 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
 
   @action
   @override
-  Future<String> getChangeAddress() async {
+  Future<String> getChangeAddress({List<BitcoinOutput>? outputs, UtxoDetails? utxoDetails}) async {
+    // use regular change address on peg in, otherwise use mweb for change address:
+
+    if (outputs != null && utxoDetails != null) {
+      // check if this is a PEGIN:
+      bool outputsToMweb = false;
+      bool comesFromMweb = false;
+
+      for (var i = 0; i < outputs.length; i++) {
+        // TODO: probably not the best way to tell if this is an mweb address
+        // (but it doesn't contain the "mweb" text at this stage)
+        if (outputs[i].address.toAddress(network).length > 110) {
+          outputsToMweb = true;
+        }
+      }
+      utxoDetails.availableInputs.forEach((element) {
+        if (element.address.contains("mweb")) {
+          comesFromMweb = true;
+        }
+      });
+
+      bool isPegIn = !comesFromMweb && outputsToMweb;
+      if (isPegIn && mwebEnabled) {
+        return super.getChangeAddress();
+      }
+    }
+
     if (mwebEnabled) {
       await topUpMweb(0);
       return mwebAddrs[0];
     }
+
     return super.getChangeAddress();
   }
 }
diff --git a/cw_bitcoin/pubspec.yaml b/cw_bitcoin/pubspec.yaml
index b121a9538..8588969c4 100644
--- a/cw_bitcoin/pubspec.yaml
+++ b/cw_bitcoin/pubspec.yaml
@@ -44,7 +44,6 @@ dependencies:
   bech32:
     git:
       url: https://github.com/cake-tech/bech32.git
-  r_crypto: ^0.5.0
 
 dev_dependencies:
   flutter_test:
diff --git a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
index 228725ef1..fea382487 100644
--- a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
+++ b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
@@ -30,8 +30,6 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
     if (call.method == "start") {
       server?.stop()
       val dataDir = call.argument("dataDir") ?: ""
-      // server = server ?: Mwebd.newServer("", dataDir, "")
-      // port = port ?: server?.start(0)
       server = server ?: Mwebd.newServer("", dataDir, "")
       port = server?.start(0)
       result.success(port)
@@ -44,7 +42,7 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
       val scanSecret: String = call.argument<String>("scanSecret") ?: ""
       val spendPub: String = call.argument<String>("spendPub") ?: ""
       val index: Int = call.argument<Int>("index") ?: 0
-      val res = Mwebd.addressIndex(scanSecret, spendPub)
+      val res = Mwebd.addressIndex(scanSecret, spendPub, index.toString())
       result.success(res)
     } else {
       result.notImplemented()

From c8aa159f69dd1c29b01a2c13a92ffe351ca0cc92 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Thu, 5 Sep 2024 11:02:16 -0700
Subject: [PATCH 4/7] [skip ci] wip

---
 cw_bitcoin/lib/litecoin_wallet_addresses.dart | 38 ++++++-------------
 .../com/cakewallet/mweb/CwMwebPlugin.kt       |  6 +--
 cw_mweb/ios/Classes/CwMwebPlugin.swift        | 13 +------
 cw_mweb/lib/cw_mweb.dart                      |  3 +-
 cw_mweb/lib/cw_mweb_method_channel.dart       |  2 +-
 cw_mweb/lib/cw_mweb_platform_interface.dart   |  4 +-
 6 files changed, 22 insertions(+), 44 deletions(-)

diff --git a/cw_bitcoin/lib/litecoin_wallet_addresses.dart b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
index ed321841e..dcdf4ca1b 100644
--- a/cw_bitcoin/lib/litecoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/litecoin_wallet_addresses.dart
@@ -1,3 +1,5 @@
+import 'dart:typed_data';
+
 import 'package:bech32/bech32.dart';
 import 'package:bitcoin_base/bitcoin_base.dart';
 import 'package:blockchain_utils/bech32/bech32_base.dart';
@@ -50,32 +52,18 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
       mwebHd.childKey(Bip32KeyIndex(0x80000001)).publicKey.pubKey.compressed;
 
   List<String> mwebAddrs = [];
-  List<String> oldMwebAddrs = [];
 
   Future<void> topUpMweb(int index) async {
-    final stub = await CwMweb.stub();
+    // generate up to index + 1000 addresses:
     while (mwebAddrs.length - index < 1000) {
       final length = mwebAddrs.length;
-      final resp = await stub.addresses(AddressRequest(
-        fromIndex: length,
-        toIndex: index + 1000,
-        scanSecret: scanSecret,
-        spendPubkey: spendPubkey,
-      ));
-      if (mwebAddrs.length == length) {
-        mwebAddrs.addAll(resp.address);
-      }
+      final address = await CwMweb.address(
+        Uint8List.fromList(scanSecret),
+        Uint8List.fromList(spendPubkey),
+        length,
+      );
+      mwebAddrs.add(address!);
     }
-
-    // for (int i = 0; i < 10; i++) {
-    //   final address = await CwMweb.address(
-    //     hex.encode(scanSecret),
-    //     hex.encode(spendPubkey),
-    //     index + 1000,
-    //   );
-    //   mwebAddrs.add(address!);
-    // }
-    // print("old function: ${oldMwebAddrs.first} new function!: ${mwebAddrs.first}");
   }
 
   @override
@@ -84,7 +72,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
     required Bip32Slip10Secp256k1 hd,
     BitcoinAddressType? addressType,
   }) {
-    if (addressType == SegwitAddresType.mweb && mwebEnabled) {
+    if (addressType == SegwitAddresType.mweb) {
       topUpMweb(index);
       return hd == sideHd ? mwebAddrs[0] : mwebAddrs[index + 1];
     }
@@ -97,11 +85,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
     required Bip32Slip10Secp256k1 hd,
     BitcoinAddressType? addressType,
   }) async {
-    // if mweb isn't enabled we'll just return the regular address type which does effectively nothing
-    // sort of a hack but easier than trying to pull the mweb setting into the electrum_wallet_addresses initialization code
-    // (we want to avoid initializing the mweb.stub() if it's not enabled or we'd be starting the whole server for no reason and it's slow)
-    // TODO: find a way to do address generation without starting the whole mweb server
-    if (addressType == SegwitAddresType.mweb && mwebEnabled) {
+    if (addressType == SegwitAddresType.mweb) {
       await topUpMweb(index);
     }
     return getAddress(index: index, hd: hd, addressType: addressType);
diff --git a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
index fea382487..47f6362e6 100644
--- a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
+++ b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
@@ -39,10 +39,10 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
       port = null
       result.success(null)
     } else if (call.method == "address") {
-      val scanSecret: String = call.argument<String>("scanSecret") ?: ""
-      val spendPub: String = call.argument<String>("spendPub") ?: ""
+      val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
+      val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
       val index: Int = call.argument<Int>("index") ?: 0
-      val res = Mwebd.addressIndex(scanSecret, spendPub, index.toString())
+      val res = Mwebd.addressIndex(scanSecret, spendPub, index.toLong())
       result.success(res)
     } else {
       result.notImplemented()
diff --git a/cw_mweb/ios/Classes/CwMwebPlugin.swift b/cw_mweb/ios/Classes/CwMwebPlugin.swift
index e68344a4b..eb79d3e32 100644
--- a/cw_mweb/ios/Classes/CwMwebPlugin.swift
+++ b/cw_mweb/ios/Classes/CwMwebPlugin.swift
@@ -30,11 +30,11 @@ public static func register(with registrar: FlutterPluginRegistrar) {
                 result(nil)
                 break
             case "address":
-                let args = call.arguments as? [String: String]
+                let args = call.arguments as? [String: Any]
                 let scanSecret = args?["scanSecret"]
                 let spendPub = args?["spendPub"]
                 let index = args?["index"]
-                result(address(scanSecret, spendPub, index))
+                result(MwebdAddressIndex(scanSecret, spendPub, index))
                 break
             default:
                 result(FlutterMethodNotImplemented)
@@ -77,15 +77,6 @@ public static func register(with registrar: FlutterPluginRegistrar) {
         CwMwebPlugin.port = 0
     }
 
-    private func address(_ scanSecret: String?, _ spendPub: String?, _ index: Int?) -> String? {
-        guard let scanSecret = scanSecret, let spendPub = spendPub, let index = index else {
-            print("Invalid arguments for address function")
-            return nil
-        }
-
-        return MwebdAddressIndex(scanSecret, spendPub, UInt32(index))
-    }
-
     deinit {
         stopServer()
     }
diff --git a/cw_mweb/lib/cw_mweb.dart b/cw_mweb/lib/cw_mweb.dart
index 46ae512a0..e71ddde97 100644
--- a/cw_mweb/lib/cw_mweb.dart
+++ b/cw_mweb/lib/cw_mweb.dart
@@ -1,4 +1,5 @@
 import 'dart:io';
+import 'dart:typed_data';
 
 import 'package:grpc/grpc.dart';
 import 'package:path_provider/path_provider.dart';
@@ -53,7 +54,7 @@ class CwMweb {
     await cleanup();
   }
 
-  static Future<String?> address(String scanSecret, String spendPub, int index) async {
+  static Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
     // try {
     //   return (await CwMwebPlatform.instance.address(scan, spendPub, index))!;
     // } catch (e) {
diff --git a/cw_mweb/lib/cw_mweb_method_channel.dart b/cw_mweb/lib/cw_mweb_method_channel.dart
index 6f7ad2279..70e4a1789 100644
--- a/cw_mweb/lib/cw_mweb_method_channel.dart
+++ b/cw_mweb/lib/cw_mweb_method_channel.dart
@@ -21,7 +21,7 @@ class MethodChannelCwMweb extends CwMwebPlatform {
   }
 
   @override
-  Future<String?> address(String scanSecret, String spendPub, int index) async {
+  Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
     final result = await methodChannel.invokeMethod<String>('address', {
       'scanSecret': scanSecret,
       'spendPub': spendPub,
diff --git a/cw_mweb/lib/cw_mweb_platform_interface.dart b/cw_mweb/lib/cw_mweb_platform_interface.dart
index a63319341..8cc80f3e9 100644
--- a/cw_mweb/lib/cw_mweb_platform_interface.dart
+++ b/cw_mweb/lib/cw_mweb_platform_interface.dart
@@ -1,3 +1,5 @@
+import 'dart:typed_data';
+
 import 'package:plugin_platform_interface/plugin_platform_interface.dart';
 
 import 'cw_mweb_method_channel.dart';
@@ -31,7 +33,7 @@ abstract class CwMwebPlatform extends PlatformInterface {
     throw UnimplementedError('stop() has not been implemented.');
   }
 
-  Future<String?> address(String scanSecret, String spendPub, int index) {
+  Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) {
     throw UnimplementedError('address(int) has not been implemented.');
   }
 }

From 20fa6a0bbdda928adf2177fed470fed0032b6764 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Thu, 5 Sep 2024 13:32:06 -0700
Subject: [PATCH 5/7] updates [skip ci]

---
 .github/workflows/pr_test_build_android.yml   |  4 +--
 .github/workflows/pr_test_build_linux.yml     | 26 +++++++++++++++++++
 .../com/cakewallet/mweb/CwMwebPlugin.kt       |  2 +-
 scripts/android/build_mwebd.sh                |  1 +
 scripts/ios/build_mwebd.sh                    |  1 +
 5 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 904802f26..0ff5ef367 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -112,7 +112,7 @@ jobs:
           # build mwebd:
           cd /opt/android/cake_wallet
           git clone https://github.com/ltcmweb/mwebd
-          git reset --hard 49c42597ce5036fe1065200c3c056d0aba5f1a58
+          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
           cd /opt/android/cake_wallet/mwebd
           gomobile bind -target=android -androidapi 21 .
           mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
@@ -120,8 +120,6 @@ jobs:
           cd ..
           rm -rf mwebd
 
-
-
       - name: Generate KeyStore
         run: |
           cd /opt/android/cake_wallet/android/app
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index 7935dd177..e425cffbc 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -89,6 +89,32 @@ jobs:
           cd /opt/android/cake_wallet
           flutter pub get
 
+      - name: Install go and gomobile
+        run: |
+          # install go > 1.21:
+          wget https://go.dev/dl/go1.22.4.linux-amd64.tar.gz
+          sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.22.4.linux-amd64.tar.gz
+          export PATH=$PATH:/usr/local/go/bin
+          export PATH=$PATH:~/go/bin
+          go install golang.org/x/mobile/cmd/gomobile@latest
+          gomobile init
+
+      - name: Build mwebd
+        run: |
+          # paths are reset after each step, so we need to set them again:
+          export PATH=$PATH:/usr/local/go/bin
+          export PATH=$PATH:~/go/bin
+          # build mwebd:
+          cd /opt/android/cake_wallet
+          git clone https://github.com/ltcmweb/mwebd
+          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
+          cd /opt/android/cake_wallet/mwebd
+          gomobile bind -target=android -androidapi 21 .
+          mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
+          mv ./mwebd.aar $_
+          cd ..
+          rm -rf mwebd
+
       - name: Generate localization
         run: |
           cd /opt/android/cake_wallet
diff --git a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
index 47f6362e6..396bce589 100644
--- a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
+++ b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
@@ -42,7 +42,7 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
       val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
       val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
       val index: Int = call.argument<Int>("index") ?: 0
-      val res = Mwebd.addressIndex(scanSecret, spendPub, index.toLong())
+      val res = Mwebd.addressIndex(scanSecret, spendPub, index)
       result.success(res)
     } else {
       result.notImplemented()
diff --git a/scripts/android/build_mwebd.sh b/scripts/android/build_mwebd.sh
index d3a3bf091..269e58d8c 100755
--- a/scripts/android/build_mwebd.sh
+++ b/scripts/android/build_mwebd.sh
@@ -8,6 +8,7 @@ gomobile init
 # build mwebd:
 git clone https://github.com/ltcmweb/mwebd
 cd mwebd
+git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
 gomobile bind -target=android -androidapi 21 .
 mkdir -p ../../../cw_mweb/android/libs/
 mv ./mwebd.aar $_
diff --git a/scripts/ios/build_mwebd.sh b/scripts/ios/build_mwebd.sh
index 08dbd7cd0..ae1726f23 100755
--- a/scripts/ios/build_mwebd.sh
+++ b/scripts/ios/build_mwebd.sh
@@ -7,6 +7,7 @@ gomobile init
 # build mwebd:
 git clone https://github.com/ltcmweb/mwebd
 cd mwebd
+git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
 gomobile bind -target=ios .
 mv -fn ./Mwebd.xcframework ../../../ios/
 # cleanup:

From 14891ec4f5c57838608e4c23937433f1b9fe36f3 Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Thu, 5 Sep 2024 14:40:13 -0700
Subject: [PATCH 6/7] ios fixes

---
 .../main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt    |  2 +-
 cw_mweb/ios/Classes/CwMwebPlugin.swift                 | 10 +++++-----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
index 396bce589..57ae3d4c3 100644
--- a/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
+++ b/cw_mweb/android/src/main/kotlin/com/cakewallet/mweb/CwMwebPlugin.kt
@@ -42,7 +42,7 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
       val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
       val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
       val index: Int = call.argument<Int>("index") ?: 0
-      val res = Mwebd.addressIndex(scanSecret, spendPub, index)
+      val res = Mwebd.address(scanSecret, spendPub, index)
       result.success(res)
     } else {
       result.notImplemented()
diff --git a/cw_mweb/ios/Classes/CwMwebPlugin.swift b/cw_mweb/ios/Classes/CwMwebPlugin.swift
index eb79d3e32..81ebc4a87 100644
--- a/cw_mweb/ios/Classes/CwMwebPlugin.swift
+++ b/cw_mweb/ios/Classes/CwMwebPlugin.swift
@@ -31,10 +31,10 @@ public static func register(with registrar: FlutterPluginRegistrar) {
                 break
             case "address":
                 let args = call.arguments as? [String: Any]
-                let scanSecret = args?["scanSecret"]
-                let spendPub = args?["spendPub"]
-                let index = args?["index"]
-                result(MwebdAddressIndex(scanSecret, spendPub, index))
+                let scanSecret = args?["scanSecret"] as! Data
+                let spendPub = args?["spendPub"] as! Data
+                let index = args?["index"] as! Int32
+                result(MwebdAddress(scanSecret, spendPub, index))
                 break
             default:
                 result(FlutterMethodNotImplemented)
@@ -80,4 +80,4 @@ public static func register(with registrar: FlutterPluginRegistrar) {
     deinit {
         stopServer()
     }
-}
\ No newline at end of file
+}

From 5dbc414e33ed3a1796eb980a7dbf94b7d13becca Mon Sep 17 00:00:00 2001
From: Matthew Fosse <matt@fosse.co>
Date: Thu, 5 Sep 2024 14:48:11 -0700
Subject: [PATCH 7/7] fix workflows + ios fix

---
 .github/workflows/pr_test_build_android.yml |  2 +-
 .github/workflows/pr_test_build_linux.yml   |  2 +-
 cw_mweb/ios/Classes/CwMwebPlugin.swift      | 13 ++++++++-----
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 0ff5ef367..306eb8282 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -112,8 +112,8 @@ jobs:
           # build mwebd:
           cd /opt/android/cake_wallet
           git clone https://github.com/ltcmweb/mwebd
-          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
           cd /opt/android/cake_wallet/mwebd
+          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
           gomobile bind -target=android -androidapi 21 .
           mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
           mv ./mwebd.aar $_
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index e425cffbc..9faac2533 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -107,8 +107,8 @@ jobs:
           # build mwebd:
           cd /opt/android/cake_wallet
           git clone https://github.com/ltcmweb/mwebd
-          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
           cd /opt/android/cake_wallet/mwebd
+          git reset --hard 7f31c84eeb2e954f2c5f385b39db3b8e3b6389e3
           gomobile bind -target=android -androidapi 21 .
           mkdir -p /opt/android/cake_wallet/cw_mweb/android/libs/
           mv ./mwebd.aar $_
diff --git a/cw_mweb/ios/Classes/CwMwebPlugin.swift b/cw_mweb/ios/Classes/CwMwebPlugin.swift
index 81ebc4a87..f1fd78cd8 100644
--- a/cw_mweb/ios/Classes/CwMwebPlugin.swift
+++ b/cw_mweb/ios/Classes/CwMwebPlugin.swift
@@ -30,11 +30,14 @@ public static func register(with registrar: FlutterPluginRegistrar) {
                 result(nil)
                 break
             case "address":
-                let args = call.arguments as? [String: Any]
-                let scanSecret = args?["scanSecret"] as! Data
-                let spendPub = args?["spendPub"] as! Data
-                let index = args?["index"] as! Int32
-                result(MwebdAddress(scanSecret, spendPub, index))
+                let args = call.arguments as! [String: Any]
+                let scanSecret = args["scanSecret"] as! FlutterStandardTypedData
+                let spendPub = args["spendPub"] as! FlutterStandardTypedData
+                let index = args["index"] as! Int32
+                
+                let scanSecretData = scanSecret.data
+                let spendPubData = spendPub.data
+                result(MwebdAddress(scanSecretData, spendPubData, index))
                 break
             default:
                 result(FlutterMethodNotImplemented)