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)