mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
use ffi for mweb (#2456)
* chore: add ffi and ffigen dependencies to pubspec.yaml * refactor: replace method channel with FFI implementation for MWeb module * fix: correct `cd` command in build_mwebd.sh script * chore: add go.sum file with dependency checksums * fix: ensure ANDROID_NDK_VERSION is set before building and dynamically update NDK_BIN path * fix: update NDK_BIN path to dynamically detect platform in build_mwebd.sh script * refactor: remove unused mwebd dependencies and clean up CwMwebPlugin code * Update scripts/android/build_mwebd.sh Co-authored-by: cyan <cyjan@mrcyjanek.net> * refactor: replace iOS MoneroWallet framework with Mwebd.xcframework and clean up plugin implementation [skip-ci] * fix: mwebd ffi ios * refactor: update MWebFfi class to use non-nullable `lib` and improve address debug logging * chore: remove unused iOS/Android build scripts for mwebd * refactor: replace mweb.so with libmweb.so, use sync methods in MWebFfi, and update iOS/Android frameworks/scripts accordingly * chore: unify mwebd build process in workflows, remove unused gomobile init command --------- Co-authored-by: cyan <cyjan@mrcyjanek.net>
This commit is contained in:
co-authored by
cyan
parent
52e778f275
commit
309ad1836e
@@ -254,7 +254,6 @@ jobs:
|
||||
export MWEBD_HASH=$(cat scripts/android/build_mwebd.sh | grep 'git reset --hard' | xargs | awk '{ print $4 }')
|
||||
echo MWEBD_HASH=$MWEBD_HASH >> /etc/environment
|
||||
pushd scripts/android
|
||||
gomobile init;
|
||||
./build_mwebd.sh --dont-install
|
||||
popd
|
||||
|
||||
|
||||
@@ -232,6 +232,15 @@ jobs:
|
||||
run: |
|
||||
flutter pub get
|
||||
|
||||
- name: Build mwebd
|
||||
run: |
|
||||
set -x -e
|
||||
export MWEBD_HASH=$(cat scripts/android/build_mwebd.sh | grep 'git reset --hard' | xargs | awk '{ print $4 }')
|
||||
echo MWEBD_HASH=$MWEBD_HASH >> /etc/environment
|
||||
pushd scripts/android
|
||||
./build_mwebd.sh --dont-install
|
||||
popd
|
||||
|
||||
- name: Build generated code
|
||||
run: |
|
||||
./model_generator.sh async
|
||||
|
||||
@@ -6,7 +6,6 @@ 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/bitcoin_unspent.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/unspent_coin_type.dart';
|
||||
@@ -84,8 +83,7 @@ abstract class LitecoinWalletAddressesBase extends ElectrumWalletAddresses with
|
||||
generating = true;
|
||||
try {
|
||||
while (mwebAddrs.length <= (index + 1)) {
|
||||
final addresses =
|
||||
await CwMweb.addresses(scan, spend, mwebAddrs.length, mwebAddrs.length + 50);
|
||||
final addresses = CwMweb.addresses(scan, spend, mwebAddrs.length, mwebAddrs.length + 50);
|
||||
printV("generated up to index ${mwebAddrs.length}");
|
||||
// sleep for a bit to avoid making the main thread unresponsive:
|
||||
await Future.delayed(Duration(milliseconds: 200));
|
||||
|
||||
@@ -21,14 +21,6 @@ allprojects {
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.allprojects {
|
||||
repositories {
|
||||
flatDir {
|
||||
dirs project(':cw_mweb').file('libs')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
@@ -74,7 +66,3 @@ android {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation (name: 'mwebd', ext: 'aar')
|
||||
}
|
||||
|
||||
@@ -8,9 +8,6 @@ import io.flutter.plugin.common.MethodChannel
|
||||
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
|
||||
import io.flutter.plugin.common.MethodChannel.Result
|
||||
|
||||
import mwebd.Mwebd
|
||||
import mwebd.Server
|
||||
|
||||
/** CwMwebPlugin */
|
||||
class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// The MethodChannel that will the communication between Flutter and native Android
|
||||
@@ -18,8 +15,6 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
|
||||
/// This local reference serves to register the plugin with the Flutter Engine and unregister it
|
||||
/// when the Flutter Engine is detached from the Activity
|
||||
private lateinit var channel : MethodChannel
|
||||
private var server: Server? = null
|
||||
private var port: Long? = null
|
||||
|
||||
override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cw_mweb")
|
||||
@@ -27,40 +22,10 @@ class CwMwebPlugin: FlutterPlugin, MethodCallHandler {
|
||||
}
|
||||
|
||||
override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
|
||||
if (call.method == "start") {
|
||||
server?.stop()
|
||||
val dataDir = call.argument("dataDir") ?: ""
|
||||
val nodeUri = call.argument("nodeUri") ?: ""
|
||||
server = server ?: Mwebd.newServer("", dataDir, nodeUri)
|
||||
port = server?.start(0)
|
||||
result.success(port)
|
||||
} else if (call.method == "stop") {
|
||||
server?.stop()
|
||||
server = null
|
||||
port = null
|
||||
result.success(null)
|
||||
} else if (call.method == "address") {
|
||||
// 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.address(scanSecret, spendPub, index)
|
||||
// result.success(res)
|
||||
} else if (call.method == "addresses") {
|
||||
val scanSecret: ByteArray = call.argument<ByteArray>("scanSecret") ?: ByteArray(0)
|
||||
val spendPub: ByteArray = call.argument<ByteArray>("spendPub") ?: ByteArray(0)
|
||||
val fromIndex: Int = call.argument<Int>("fromIndex") ?: 0
|
||||
val toIndex: Int = call.argument<Int>("toIndex") ?: 0
|
||||
val res = Mwebd.addresses(scanSecret, spendPub, fromIndex, toIndex)
|
||||
result.success(res)
|
||||
} else {
|
||||
result.notImplemented()
|
||||
}
|
||||
result.notImplemented()
|
||||
}
|
||||
|
||||
override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
|
||||
channel.setMethodCallHandler(null)
|
||||
server?.stop()
|
||||
server = null
|
||||
port = null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# yaml-language-server: $schema=../../ffigen.schema.json
|
||||
|
||||
name: MWebFlutter
|
||||
description: Bindings to `go/mweb.h`.
|
||||
output: 'lib/generated_bindings.g.dart'
|
||||
headers:
|
||||
entry-points:
|
||||
- 'android/src/main/jniLibs/arm64-v8a/libmweb.h'
|
||||
@@ -0,0 +1,50 @@
|
||||
module github.com/cake-tech/cake_wallet/cw_mweb/go
|
||||
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/aead/siphash v1.0.1 // indirect
|
||||
github.com/alitto/pond/v2 v2.2.0 // indirect
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/decred/dcrd/lru v1.1.2 // indirect
|
||||
github.com/ethereum/go-ethereum v1.14.8 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.4.2 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/holiman/uint256 v1.3.1 // indirect
|
||||
github.com/kkdai/bstream v1.0.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/ltcmweb/coinswapd v0.1.0 // indirect
|
||||
github.com/ltcmweb/ltcd v0.25.6 // indirect
|
||||
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 // indirect
|
||||
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 // indirect
|
||||
github.com/ltcmweb/mwebd v0.1.8 // indirect
|
||||
github.com/ltcmweb/neutrino v0.17.4 // indirect
|
||||
github.com/ltcmweb/neutrino/cache v1.1.0 // indirect
|
||||
github.com/ltcmweb/secp256k1 v0.1.1 // indirect
|
||||
github.com/ltcsuite/lnd/queue v1.1.0 // indirect
|
||||
github.com/ltcsuite/lnd/ticker v1.1.0 // indirect
|
||||
github.com/ltcsuite/ltcwallet/walletdb v1.3.5 // indirect
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
go.etcd.io/bbolt v1.3.10 // indirect
|
||||
golang.org/x/crypto v0.33.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect
|
||||
google.golang.org/grpc v1.63.2 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
)
|
||||
@@ -0,0 +1,97 @@
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/alitto/pond/v2 v2.2.0 h1:hX3B1Lu4b5PjSHR+IWNRDKD0Jfw2ew8V25J7Vu5j7RM=
|
||||
github.com/alitto/pond/v2 v2.2.0/go.mod h1:xkjYEgQ05RSpWdfSd1nM3OVv7TBhLdy7rMp3+2Nq+yE=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set/v2 v2.6.0 h1:XfcQbWM1LlMB8BsJ8N9vW5ehnnPVIw0je80NsVHagjM=
|
||||
github.com/deckarep/golang-set/v2 v2.6.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/decred/dcrd/lru v1.1.2 h1:KdCzlkxppuoIDGEvCGah1fZRicrDH36IipvlB1ROkFY=
|
||||
github.com/decred/dcrd/lru v1.1.2/go.mod h1:gEdCVgXs1/YoBvFWt7Scgknbhwik3FgVSzlnCcXL2N8=
|
||||
github.com/ethereum/go-ethereum v1.14.8 h1:NgOWvXS+lauK+zFukEvi85UmmsS/OkV0N23UZ1VTIig=
|
||||
github.com/ethereum/go-ethereum v1.14.8/go.mod h1:TJhyuDq0JDppAkFXgqjwpdlQApywnu/m10kFPxh8vvs=
|
||||
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/holiman/uint256 v1.3.1 h1:JfTzmih28bittyHM8z360dCjIA9dbPIBlcTI6lmctQs=
|
||||
github.com/holiman/uint256 v1.3.1/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||
github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=
|
||||
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/ltcmweb/coinswapd v0.1.0 h1:M6eoz4g7fDpsQeNA8wWbBh6PY1xykrihyLU44SgljeI=
|
||||
github.com/ltcmweb/coinswapd v0.1.0/go.mod h1:CY5cVSympaLrMO8fHWXO+e/iuPLs2L0U9daMCRTstEM=
|
||||
github.com/ltcmweb/ltcd v0.25.6 h1:96aC38ZEyNVztylrBBqYnVZJ6cuF7IUvL2knhbMxs3Y=
|
||||
github.com/ltcmweb/ltcd v0.25.6/go.mod h1:jQbvPfnT4bBXJKRwU5SdD9ZUopwmSvhngdjeopv2cIU=
|
||||
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3 h1:gJc1ljDPCBtwBKFcC4SW44BFoJqoZzkeagndMYdqKKE=
|
||||
github.com/ltcmweb/ltcd/btcec/v2 v2.3.3/go.mod h1:NRr2WtpiSiSO29TkdZhbGNRA/Q16DV2eNbORf+M2ykI=
|
||||
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3 h1:CAPyzHI3bCFRrrVHZkDUR2i3Awj6l/aqAZIEi0E/nfM=
|
||||
github.com/ltcmweb/ltcd/chaincfg/chainhash v1.0.3/go.mod h1:zB+HhI2IbIwTGpdAhdzpm1GVX4ShcWTgN42+ar9HXrg=
|
||||
github.com/ltcmweb/mwebd v0.1.8 h1:5TJgrM76H3s6kWUJ6CsU1L+DaafcAZ1edDlkyJ+GWt0=
|
||||
github.com/ltcmweb/mwebd v0.1.8/go.mod h1:KPf+lXEvEMuG0NaHume0imWMb9Cvr15SNPujZO6EAv4=
|
||||
github.com/ltcmweb/neutrino v0.17.4 h1:ZsguBvicTM5CtZDsKg+OBFuPUCKjfEJ3lRSGXPjF2oM=
|
||||
github.com/ltcmweb/neutrino v0.17.4/go.mod h1:KktZ+McIwHuTHe0K8JK9Wv4qgv8orkA21a0ZOU4SwJ4=
|
||||
github.com/ltcmweb/neutrino/cache v1.1.0 h1:C0Qn2p8ogcskRPfrBKPUayjn3m/CUJqI7otopNScvhk=
|
||||
github.com/ltcmweb/neutrino/cache v1.1.0/go.mod h1:HddBIjnWaEvrDSnpMIBKkxCJaoRMlg2DfVdNFM0y+ME=
|
||||
github.com/ltcmweb/secp256k1 v0.1.1 h1:hsGpnFcZ5zmjSxg7AswZp8ygo5NiY06OYWJk97hFizI=
|
||||
github.com/ltcmweb/secp256k1 v0.1.1/go.mod h1:Kdj2WHIAc0Y1apPtVY7nVxImRWiRTQue2vs1gt1VoEc=
|
||||
github.com/ltcsuite/lnd/queue v1.1.0 h1:/aVgox4Lz74xBU8BSw5HDau7hHl2irJs5M9u1SPQ2E0=
|
||||
github.com/ltcsuite/lnd/queue v1.1.0/go.mod h1:DJrxK2gPC2FjJAVYxPOcnY2CplI3rhL2PEq7IexlTWQ=
|
||||
github.com/ltcsuite/lnd/ticker v1.0.1/go.mod h1:WZKpekfDVAVv7Gsrr0GAWC/U1XURfGesFg9sQYJbeL4=
|
||||
github.com/ltcsuite/lnd/ticker v1.1.0 h1:3zYM/JlKNqq+DotW8jiEdHVeY5Yl7n7cUb2bTof1yXM=
|
||||
github.com/ltcsuite/lnd/ticker v1.1.0/go.mod h1:K2qQ3EPe8enztYvn/VAbLafCPy13XHMuCRPsySoAbt8=
|
||||
github.com/ltcsuite/ltcwallet/walletdb v1.3.5 h1:WymVw0FBQ8KJgH7B88ujRqBOJ9R0en9K9urpJW4atAE=
|
||||
github.com/ltcsuite/ltcwallet/walletdb v1.3.5/go.mod h1:29SBzxA55wNxY3ctFw6t5PgsULwf3NMwg2MiGQgtrJE=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU=
|
||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
go.etcd.io/bbolt v1.3.5-0.20200615073812-232d8fc87f50/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/bbolt v1.3.10 h1:+BqfJTcCzTItrop8mq/lbzL8wSGtj94UO/3U31shqG0=
|
||||
go.etcd.io/bbolt v1.3.10/go.mod h1:bK3UQLPJZly7IlNmV7uVHJDxfe5aK9Ll93e/74Y9oEQ=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 h1:umK/Ey0QEzurTNlsV3R+MfxHAb78HCEX/IkuR+zH4WQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
|
||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
@@ -0,0 +1,58 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"C"
|
||||
"unsafe"
|
||||
|
||||
"github.com/ltcmweb/mwebd"
|
||||
)
|
||||
|
||||
var server *mwebd.Server
|
||||
|
||||
//export StartServer
|
||||
func StartServer(chain *C.char, dataDir *C.char, nodeUri *C.char) C.int {
|
||||
if server != nil {
|
||||
server.Stop()
|
||||
}
|
||||
goChain := C.GoString(chain)
|
||||
goDataDir := C.GoString(dataDir)
|
||||
goNodeUri := C.GoString(nodeUri)
|
||||
|
||||
var err error
|
||||
server, err = mwebd.NewServer(goChain, goDataDir, goNodeUri)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
start, err := server.Start(0)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
return C.int(start)
|
||||
}
|
||||
|
||||
//export StopServer
|
||||
func StopServer() {
|
||||
if server == nil {
|
||||
return
|
||||
}
|
||||
server.Stop()
|
||||
server = nil
|
||||
}
|
||||
|
||||
//export Addresses
|
||||
func Addresses(scanSecret *C.char, scanSecretLen C.int, spendPubKey *C.char, spendPubKeyLen C.int, i C.int, j C.int) *C.char {
|
||||
// Convert C pointers to Go byte slices
|
||||
goScanSecret := C.GoBytes(unsafe.Pointer(scanSecret), scanSecretLen)
|
||||
goSpendPubKey := C.GoBytes(unsafe.Pointer(spendPubKey), spendPubKeyLen)
|
||||
|
||||
// Call the original Go function
|
||||
addr := mwebd.Addresses(goScanSecret, goSpendPubKey, int32(i), int32(j))
|
||||
|
||||
// Convert the resulting Go string to a C string
|
||||
// The C code must free this memory
|
||||
return C.CString(addr)
|
||||
}
|
||||
|
||||
func main() {}
|
||||
@@ -1,6 +1,5 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
import Mwebd
|
||||
|
||||
public class CwMwebPlugin: NSObject, FlutterPlugin {
|
||||
public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
@@ -9,92 +8,8 @@ public static func register(with registrar: FlutterPluginRegistrar) {
|
||||
registrar.addMethodCallDelegate(instance, channel: channel)
|
||||
}
|
||||
|
||||
private static var server: MwebdServer?
|
||||
private static var port: Int = 0
|
||||
private static var dataDir: String?
|
||||
private static var nodeUri: String?
|
||||
|
||||
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"]
|
||||
let nodeUri = args?["nodeUri"]
|
||||
CwMwebPlugin.dataDir = dataDir
|
||||
CwMwebPlugin.nodeUri = nodeUri
|
||||
startServer(result: result)
|
||||
break
|
||||
case "stop":
|
||||
stopServer()
|
||||
result(nil)
|
||||
break
|
||||
// case "address":
|
||||
// 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
|
||||
case "addresses":
|
||||
let args = call.arguments as! [String: Any]
|
||||
let scanSecret = args["scanSecret"] as! FlutterStandardTypedData
|
||||
let spendPub = args["spendPub"] as! FlutterStandardTypedData
|
||||
let fromIndex = args["fromIndex"] as! Int32
|
||||
let toIndex = args["toIndex"] as! Int32
|
||||
|
||||
let scanSecretData = scanSecret.data
|
||||
let spendPubData = spendPub.data
|
||||
result(MwebdAddresses(scanSecretData, spendPubData, fromIndex, toIndex))
|
||||
break
|
||||
default:
|
||||
result(FlutterMethodNotImplemented)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func startServer(result: @escaping FlutterResult) {
|
||||
if CwMwebPlugin.server == nil {
|
||||
var error: NSError?
|
||||
CwMwebPlugin.server = MwebdNewServer("", CwMwebPlugin.dataDir, CwMwebPlugin.nodeUri, &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)
|
||||
}
|
||||
}
|
||||
|
||||
private func stopServer() {
|
||||
print("Stopping server")
|
||||
CwMwebPlugin.server?.stop()
|
||||
CwMwebPlugin.server = nil
|
||||
CwMwebPlugin.port = 0
|
||||
}
|
||||
|
||||
deinit {
|
||||
stopServer()
|
||||
result(FlutterMethodNotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-13
@@ -5,9 +5,9 @@ import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cw_core/utils/print_verbose.dart';
|
||||
import 'package:cw_mweb/mweb_ffi.dart';
|
||||
import 'package:grpc/grpc.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'cw_mweb_platform_interface.dart';
|
||||
import 'mwebd.pbgrpc.dart';
|
||||
|
||||
class CwMweb {
|
||||
@@ -58,7 +58,7 @@ class CwMweb {
|
||||
String debugLogPath = "${appDir.path}/logs/debug.log";
|
||||
readFileWithTimer(debugLogPath);
|
||||
|
||||
_port = await CwMwebPlatform.instance.start(appDir.path, nodeUriOverride ?? ltcNodeUri);
|
||||
_port = MWebFfi.instance.start(appDir.path, nodeUriOverride ?? ltcNodeUri);
|
||||
if (_port == null || _port == 0) {
|
||||
throw Exception("Failed to start server");
|
||||
}
|
||||
@@ -109,7 +109,7 @@ class CwMweb {
|
||||
|
||||
static Future<void> stop() async {
|
||||
try {
|
||||
await CwMwebPlatform.instance.stop();
|
||||
MWebFfi.instance.stop();
|
||||
await cleanup();
|
||||
} on GrpcError catch (e) {
|
||||
printV('Caught grpc error: ${e.message}');
|
||||
@@ -118,11 +118,9 @@ class CwMweb {
|
||||
}
|
||||
}
|
||||
|
||||
static Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
|
||||
static String? address(Uint8List scanSecret, Uint8List spendPub, int index) {
|
||||
try {
|
||||
return (await CwMwebPlatform.instance.addresses(scanSecret, spendPub, index, index + 1))
|
||||
?.split(',')
|
||||
.first;
|
||||
return MWebFfi.instance.addresses(scanSecret, spendPub, index, index + 1).split(',').first;
|
||||
} on GrpcError catch (e) {
|
||||
printV('Caught grpc error: ${e.message}');
|
||||
} catch (e) {
|
||||
@@ -131,15 +129,14 @@ class CwMweb {
|
||||
return null;
|
||||
}
|
||||
|
||||
static Future<List<String>?> addresses(
|
||||
Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) async {
|
||||
static List<String>? addresses(
|
||||
Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) {
|
||||
try {
|
||||
return (await CwMwebPlatform.instance.addresses(scanSecret, spendPub, fromIndex, toIndex))
|
||||
?.split(',');
|
||||
return MWebFfi.instance.addresses(scanSecret, spendPub, fromIndex, toIndex).split(',');
|
||||
} on GrpcError catch (e) {
|
||||
log('Caught grpc error: ${e.message}');
|
||||
printV('Caught grpc error: ${e.message}');
|
||||
} catch (e) {
|
||||
log("Error getting addresses: $e");
|
||||
printV("Error getting addresses: $e");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'cw_mweb_platform_interface.dart';
|
||||
|
||||
/// An implementation of [CwMwebPlatform] that uses method channels.
|
||||
class MethodChannelCwMweb extends CwMwebPlatform {
|
||||
/// The method channel used to interact with the native platform.
|
||||
@visibleForTesting
|
||||
final methodChannel = const MethodChannel('cw_mweb');
|
||||
|
||||
@override
|
||||
Future<int?> start(String dataDir, String nodeUri) async {
|
||||
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
|
||||
return null;
|
||||
}
|
||||
final result =
|
||||
await methodChannel.invokeMethod<int>('start', {'dataDir': dataDir, 'nodeUri': nodeUri});
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
|
||||
return;
|
||||
}
|
||||
await methodChannel.invokeMethod<void>('stop');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) async {
|
||||
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
|
||||
return null;
|
||||
}
|
||||
final result = await methodChannel.invokeMethod<String>('address', {
|
||||
'scanSecret': scanSecret,
|
||||
'spendPub': spendPub,
|
||||
'index': index,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> addresses(Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) async {
|
||||
if (Platform.isLinux || Platform.isMacOS || Platform.isWindows) {
|
||||
return null;
|
||||
}
|
||||
final result = await methodChannel.invokeMethod<String>('addresses', {
|
||||
'scanSecret': scanSecret,
|
||||
'spendPub': spendPub,
|
||||
'fromIndex': fromIndex,
|
||||
'toIndex': toIndex,
|
||||
});
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:plugin_platform_interface/plugin_platform_interface.dart';
|
||||
|
||||
import 'cw_mweb_method_channel.dart';
|
||||
|
||||
abstract class CwMwebPlatform extends PlatformInterface {
|
||||
/// Constructs a CwMwebPlatform.
|
||||
CwMwebPlatform() : super(token: _token);
|
||||
|
||||
static final Object _token = Object();
|
||||
|
||||
static CwMwebPlatform _instance = MethodChannelCwMweb();
|
||||
|
||||
/// The default instance of [CwMwebPlatform] to use.
|
||||
///
|
||||
/// Defaults to [MethodChannelCwMweb].
|
||||
static CwMwebPlatform get instance => _instance;
|
||||
|
||||
/// Platform-specific implementations should set this with their own
|
||||
/// platform-specific class that extends [CwMwebPlatform] when
|
||||
/// they register themselves.
|
||||
static set instance(CwMwebPlatform instance) {
|
||||
PlatformInterface.verifyToken(instance, _token);
|
||||
_instance = instance;
|
||||
}
|
||||
|
||||
Future<int?> start(String dataDir, String nodeUri) {
|
||||
throw UnimplementedError('start() has not been implemented.');
|
||||
}
|
||||
|
||||
Future<void> stop() {
|
||||
throw UnimplementedError('stop() has not been implemented.');
|
||||
}
|
||||
|
||||
Future<String?> address(Uint8List scanSecret, Uint8List spendPub, int index) {
|
||||
throw UnimplementedError('address(int) has not been implemented.');
|
||||
}
|
||||
|
||||
Future<String?> addresses(Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) {
|
||||
throw UnimplementedError('addresses has not been implemented.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
import 'dart:ffi';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:cw_mweb/generated_bindings.g.dart';
|
||||
import 'package:ffi/ffi.dart';
|
||||
|
||||
String libPath = (() {
|
||||
if (Platform.isWindows) return 'mweb.dll';
|
||||
if (Platform.isMacOS) return 'mweb.dylib';
|
||||
if (Platform.isIOS) return 'Mwebd.framework/Mwebd';
|
||||
if (Platform.isAndroid) return 'libmweb.so';
|
||||
return 'libmweb.so';
|
||||
})();
|
||||
|
||||
class MWebFfi {
|
||||
late final MWebFlutter lib;
|
||||
|
||||
MWebFfi() : lib = MWebFlutter(DynamicLibrary.open(libPath));
|
||||
|
||||
static MWebFfi instance = MWebFfi();
|
||||
|
||||
int start(String dataDir, String nodeUri) {
|
||||
final chain = "".toNativeUtf8().cast<Char>();
|
||||
final dataDir_ = dataDir.toNativeUtf8().cast<Char>();
|
||||
final nodeUri_ = nodeUri.toNativeUtf8().cast<Char>();
|
||||
|
||||
final port = lib.StartServer(chain, dataDir_, nodeUri_);
|
||||
|
||||
calloc.free(chain);
|
||||
calloc.free(dataDir_);
|
||||
calloc.free(nodeUri_);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void stop() => lib.StopServer();
|
||||
|
||||
String addresses(
|
||||
Uint8List scanSecret, Uint8List spendPub, int fromIndex, int toIndex) {
|
||||
final scanSecretPtr = malloc.allocate<Uint8>(scanSecret.length);
|
||||
for (int k = 0; k < scanSecret.length; k++) {
|
||||
scanSecretPtr[k] = scanSecret[k];
|
||||
}
|
||||
|
||||
final spendPubKeyPtr = malloc.allocate<Uint8>(spendPub.length);
|
||||
for (int k = 0; k < spendPub.length; k++) {
|
||||
spendPubKeyPtr[k] = spendPub[k];
|
||||
}
|
||||
|
||||
final Pointer<Char> resultPtr = lib.Addresses(
|
||||
scanSecretPtr.cast(),
|
||||
scanSecret.length,
|
||||
spendPubKeyPtr.cast(),
|
||||
spendPub.length,
|
||||
fromIndex,
|
||||
toIndex,
|
||||
);
|
||||
|
||||
final result = resultPtr.cast<Utf8>().toDartString();
|
||||
|
||||
malloc.free(scanSecretPtr);
|
||||
malloc.free(spendPubKeyPtr);
|
||||
malloc.free(resultPtr);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,13 @@ dependencies:
|
||||
plugin_platform_interface: ^2.0.2
|
||||
cw_core:
|
||||
path: ../cw_core
|
||||
ffi: ^2.1.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^2.0.0
|
||||
ffigen:
|
||||
|
||||
# For information on the generic Dart part of this file, see the
|
||||
# following page: https://dart.dev/tools/pub/pubspec
|
||||
|
||||
@@ -69,6 +69,8 @@ PODS:
|
||||
- Flutter
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- in_app_review (2.0.0):
|
||||
- Flutter
|
||||
- integration_test (0.0.1):
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
CFEFC24F82F78FE747DF1D22 /* LnurlPayInfo.swift in Resources */ = {isa = PBXBuildFile; fileRef = 58C22CBD8C22B9D6023D59F8 /* LnurlPayInfo.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
|
||||
D0D7A0D4E13F31C4E02E235B /* ReceivePayment.swift in Resources */ = {isa = PBXBuildFile; fileRef = 91C524F800843E0A3F17E004 /* ReceivePayment.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
|
||||
D3AD73A327249AFE8F016A51 /* BreezSDK.swift in Resources */ = {isa = PBXBuildFile; fileRef = ABD6FCBB0F4244B090459128 /* BreezSDK.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
|
||||
D7FC97372E4F66CF0077F194 /* Mwebd.xcframework in CopyFiles */ = {isa = PBXBuildFile; fileRef = D7FC97362E4F66CF0077F194 /* Mwebd.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||
F5EE19868D6F10D814BF73AD /* SDKNotificationService.swift in Resources */ = {isa = PBXBuildFile; fileRef = 41102141140E57B1DC27FBA1 /* SDKNotificationService.swift */; settings = {ASSET_TAGS = (BreezSDK, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -43,6 +44,7 @@
|
||||
dstPath = "";
|
||||
dstSubfolderSpec = 10;
|
||||
files = (
|
||||
D7FC97372E4F66CF0077F194 /* Mwebd.xcframework in CopyFiles */,
|
||||
CE918BF82D533ECE007F186E /* MoneroWallet.xcframework in CopyFiles */,
|
||||
CE918BFA2D533ED4007F186E /* WowneroWallet.xcframework in CopyFiles */,
|
||||
CE918BFC2D533ED8007F186E /* ZanoWallet.xcframework in CopyFiles */,
|
||||
@@ -90,6 +92,7 @@
|
||||
CE918BFB2D533ED8007F186E /* ZanoWallet.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = ZanoWallet.xcframework; sourceTree = "<group>"; };
|
||||
D139E30AEB36740C21C00A9E /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
D7CD6B6020744E8FA471915D /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D7FC97362E4F66CF0077F194 /* Mwebd.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; name = Mwebd.xcframework; path = ../cw_mweb/go/Mwebd.xcframework; sourceTree = "<group>"; };
|
||||
DCEA540E3586164FB47AD13E /* LnurlPayInvoice.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = LnurlPayInvoice.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/Task/LnurlPayInvoice.swift"; sourceTree = "<group>"; };
|
||||
F42258C3697CFE3C8C8D1933 /* ServiceLogger.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ServiceLogger.swift; path = "../.symlinks/plugins/breez_sdk/ios/bindings-swift/Sources/BreezSDK/ServiceLogger.swift"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -163,6 +166,7 @@
|
||||
97C146E51CF9000F007C117D = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D7FC97362E4F66CF0077F194 /* Mwebd.xcframework */,
|
||||
0C44A7182518EF4A00B570ED /* CakeWallet */,
|
||||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
|
||||
@@ -6,14 +6,43 @@ else
|
||||
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.24.1.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
|
||||
fi
|
||||
|
||||
# build mwebd:
|
||||
git clone https://github.com/ltcmweb/mwebd
|
||||
cd mwebd
|
||||
git reset --hard f75cb9edef07d03360ee2d33e6edae4243a890b1
|
||||
gomobile bind -target=android -androidapi 21 .
|
||||
mkdir -p ../../../cw_mweb/android/libs/
|
||||
cp ./mwebd.aar $_
|
||||
cd ../../cw_mweb/go
|
||||
|
||||
if [[ "x$ANDROID_NDK_VERSION" == "x" ]];
|
||||
then
|
||||
echo "ANDROID_NDK_VERSION is missing, please declare it before building"
|
||||
echo "You have these versions installed on your system currently:"
|
||||
ls ${ANDROID_HOME}/ndk/ | cat | awk '{ print "- " $1 }'
|
||||
echo "echo > ~/.zprofile"
|
||||
echo "echo 'export ANDROID_NDK_VERSION=..... > ~/.zprofile"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
export ANDROID_OUT=../android/src/main/jniLibs
|
||||
export ANDROID_SDK="${HOME}/Library/Android/sdk"
|
||||
export NDK_BIN="${ANDROID_HOME}/ndk/${ANDROID_NDK_VERSION}/toolchains/llvm/prebuilt/$(uname | tr '[:upper:]' '[:lower:]')-x86_64/bin"
|
||||
|
||||
# Compile for x86_64 architecture and place the binary file in the android/src/main/jniLibs/x86_64 folder
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=android \
|
||||
GOARCH=amd64 \
|
||||
CC=${NDK_BIN}/x86_64-linux-android21-clang \
|
||||
go build -buildmode=c-shared -o ${ANDROID_OUT}/x86_64/libmweb.so .
|
||||
|
||||
# Compile for arm64 architecture and place the binary file in the android/src/main/jniLibs/arm64-v8a folder
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=android \
|
||||
GOARCH=arm64 \
|
||||
CC=${NDK_BIN}/aarch64-linux-android21-clang \
|
||||
go build -buildmode=c-shared -o ${ANDROID_OUT}/arm64-v8a/libmweb.so .
|
||||
|
||||
# Compile for armv7a architecture and place the binary file in the android/src/main/jniLibs/armeabi-v7a folder
|
||||
CGO_ENABLED=1 \
|
||||
GOOS=android \
|
||||
GOARCH=arm \
|
||||
CC=${NDK_BIN}/armv7a-linux-androideabi21-clang \
|
||||
go build -buildmode=c-shared -o ${ANDROID_OUT}/armeabi-v7a/libmweb.so .
|
||||
cd ../
|
||||
dart run ffigen --config ffigen_config.yaml
|
||||
|
||||
+258
-11
@@ -1,20 +1,267 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e -x
|
||||
|
||||
if [[ "$1" == "--dont-install" ]]; then
|
||||
echo "Skipping Go installation as per --dont-install flag"
|
||||
else
|
||||
# install go > 1.24:
|
||||
brew install go
|
||||
export PATH=$PATH:~/go/bin
|
||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
||||
gomobile init
|
||||
fi
|
||||
|
||||
# build mwebd:
|
||||
git clone https://github.com/ltcmweb/mwebd
|
||||
cd mwebd
|
||||
git reset --hard f75cb9edef07d03360ee2d33e6edae4243a890b1
|
||||
gomobile bind -target=ios .
|
||||
mv -fn ./Mwebd.xcframework ../../../cw_mweb/ios/
|
||||
# cleanup:
|
||||
cd ..
|
||||
rm -rf mwebd
|
||||
BASE_DIR="$(pwd)"
|
||||
MWEB_GO_DIR="${BASE_DIR}/../../cw_mweb/go"
|
||||
IOS_OUTPUT_DIR="${BASE_DIR}/../../cw_mweb/ios"
|
||||
TMP_DIR="${BASE_DIR}/tmp_mweb_frameworks"
|
||||
FRAMEWORK_NAME="Mwebd"
|
||||
|
||||
rm -rf "$TMP_DIR"
|
||||
mkdir -p "$TMP_DIR"
|
||||
|
||||
mkdir -p "$IOS_OUTPUT_DIR"
|
||||
|
||||
write_info_plist() {
|
||||
local framework_bundle="$1"
|
||||
local framework_name="$2"
|
||||
local target="$3"
|
||||
local arch="$4"
|
||||
local plist_path="${framework_bundle}/Info.plist"
|
||||
|
||||
local platform min_os_version dtplatformname dtsdkname
|
||||
|
||||
if [[ "$target" == "ios-simulator" ]]; then
|
||||
platform="iPhoneSimulator"
|
||||
dtplatformname="iphonesimulator"
|
||||
dtsdkname="iphonesimulator17.4"
|
||||
min_os_version="12.0"
|
||||
elif [[ "$target" == "ios" ]]; then
|
||||
platform="iPhoneOS"
|
||||
dtplatformname="iphoneos"
|
||||
dtsdkname="iphoneos17.4"
|
||||
min_os_version="12.0"
|
||||
else
|
||||
echo "Unknown target: $target"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "$plist_path" <<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>BuildMachineOSBuild</key>
|
||||
<string>23F79</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>${framework_name}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.cakewallet.${framework_name}</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>${framework_name}</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>${platform}</string>
|
||||
</array>
|
||||
<key>DTCompiler</key>
|
||||
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||
<key>DTPlatformName</key>
|
||||
<string>${dtplatformname}</string>
|
||||
<key>DTPlatformVersion</key>
|
||||
<string>17.4</string>
|
||||
<key>DTSDKBuild</key>
|
||||
<string>21E213</string>
|
||||
<key>DTSDKName</key>
|
||||
<string>${dtsdkname}</string>
|
||||
<key>DTSDKVersion</key>
|
||||
<string>17.4</string>
|
||||
<key>DTXcode</key>
|
||||
<string>1530</string>
|
||||
<key>DTXcodeBuild</key>
|
||||
<string>15E204a</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>${min_os_version}</string>
|
||||
<key>UIDeviceFamily</key>
|
||||
<array>
|
||||
<integer>1</integer>
|
||||
<integer>2</integer>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
}
|
||||
|
||||
build_go_library() {
|
||||
local goos="$1"
|
||||
local goarch="$2"
|
||||
local cc_target="$3"
|
||||
local sdk="$4"
|
||||
local output_file="$5"
|
||||
|
||||
echo "Building Go library for ${goos}/${goarch} with target ${cc_target}..."
|
||||
|
||||
cd "$MWEB_GO_DIR"
|
||||
|
||||
export GOOS="$goos"
|
||||
export GOARCH="$goarch"
|
||||
export CGO_ENABLED=1
|
||||
export CGO_CFLAGS="-fembed-bitcode"
|
||||
|
||||
if [[ "$sdk" == "iphoneos" ]]; then
|
||||
export CC="$(xcrun -f clang) -target $cc_target -mios-version-min=12 --sysroot $(xcrun --sdk iphoneos --show-sdk-path)"
|
||||
else
|
||||
export CC="$(xcrun -f clang) -target $cc_target -mios-simulator-version-min=12 --sysroot $(xcrun --sdk iphonesimulator --show-sdk-path)"
|
||||
fi
|
||||
|
||||
go build -buildmode=c-archive -trimpath -o "$output_file" mweb.go
|
||||
|
||||
echo "Built: $output_file"
|
||||
cd - > /dev/null
|
||||
}
|
||||
|
||||
create_framework() {
|
||||
local archive_path="$1"
|
||||
local framework_name="$2"
|
||||
local target="$3"
|
||||
local out_dir="$4"
|
||||
local arch="$5"
|
||||
|
||||
echo "Creating ${framework_name}.framework for target ${target} (${arch}) in ${out_dir}..."
|
||||
|
||||
local framework_bundle="${out_dir}/${framework_name}.framework"
|
||||
|
||||
rm -rf "$framework_bundle"
|
||||
mkdir -p "$framework_bundle"
|
||||
|
||||
if [[ ! -f "$archive_path" ]]; then
|
||||
echo "Error: Input archive not found: $archive_path"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
local temp_dir="${TMP_DIR}/temp_${arch}"
|
||||
mkdir -p "$temp_dir"
|
||||
|
||||
pushd "$temp_dir"
|
||||
ar x "$archive_path"
|
||||
|
||||
if [[ "$target" == "ios" ]]; then
|
||||
xcrun -sdk iphoneos clang -dynamiclib -arch "${arch}" -mios-version-min=12 \
|
||||
-install_name "@rpath/${framework_name}.framework/${framework_name}" \
|
||||
-framework CoreFoundation -framework Security -lresolv \
|
||||
-o "${framework_bundle}/${framework_name}" ./*.o
|
||||
else
|
||||
xcrun -sdk iphonesimulator clang -dynamiclib -arch "${arch}" -mios-simulator-version-min=12 \
|
||||
-install_name "@rpath/${framework_name}.framework/${framework_name}" \
|
||||
-framework CoreFoundation -framework Security -lresolv \
|
||||
-o "${framework_bundle}/${framework_name}" ./*.o
|
||||
fi
|
||||
popd
|
||||
|
||||
echo "Created binary: ${framework_bundle}/${framework_name}"
|
||||
|
||||
write_info_plist "$framework_bundle" "$framework_name" "$target" "$arch"
|
||||
|
||||
mkdir -p "${framework_bundle}/Headers"
|
||||
local header_file="${archive_path%.a}.h"
|
||||
if [[ -f "$header_file" ]]; then
|
||||
cp "$header_file" "${framework_bundle}/Headers/${framework_name}.h"
|
||||
echo "Copied header: ${framework_bundle}/Headers/${framework_name}.h"
|
||||
fi
|
||||
|
||||
echo "Framework created: ${framework_bundle}"
|
||||
}
|
||||
|
||||
create_xcframework() {
|
||||
local framework_name="$1"
|
||||
local xcframework_output="$2"
|
||||
shift 2
|
||||
local frameworks=("$@")
|
||||
|
||||
echo "Creating ${xcframework_output} by bundling:"
|
||||
for fw in "${frameworks[@]}"; do
|
||||
echo " Framework: ${fw}"
|
||||
done
|
||||
|
||||
local xcodebuild_args=()
|
||||
for fw in "${frameworks[@]}"; do
|
||||
xcodebuild_args+=("-framework" "$fw")
|
||||
done
|
||||
|
||||
rm -rf "$xcframework_output"
|
||||
xcodebuild -create-xcframework "${xcodebuild_args[@]}" -output "$xcframework_output"
|
||||
|
||||
echo "Created XCFramework: ${xcframework_output}"
|
||||
}
|
||||
|
||||
echo "Building MWEB XCFramework for iOS..."
|
||||
|
||||
IOS_DEVICE_OUT="${TMP_DIR}/ios_device"
|
||||
IOS_SIMULATOR_ARM64_OUT="${TMP_DIR}/ios_simulator_arm64"
|
||||
IOS_SIMULATOR_X86_64_OUT="${TMP_DIR}/ios_simulator_x86_64"
|
||||
|
||||
mkdir -p "$IOS_DEVICE_OUT" "$IOS_SIMULATOR_ARM64_OUT" "$IOS_SIMULATOR_X86_64_OUT"
|
||||
|
||||
IOS_DEVICE_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_device.a"
|
||||
IOS_SIMULATOR_ARM64_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_sim_arm64.a"
|
||||
IOS_SIMULATOR_X86_64_ARCHIVE="${TMP_DIR}/${FRAMEWORK_NAME}_sim_x86_64.a"
|
||||
|
||||
build_go_library "ios" "arm64" "aarch64-apple-ios" "iphoneos" "$IOS_DEVICE_ARCHIVE"
|
||||
build_go_library "ios" "arm64" "aarch64-apple-ios-simulator" "iphonesimulator" "$IOS_SIMULATOR_ARM64_ARCHIVE"
|
||||
build_go_library "ios" "amd64" "x86_64-apple-ios-simulator" "iphonesimulator" "$IOS_SIMULATOR_X86_64_ARCHIVE"
|
||||
|
||||
create_framework "$IOS_DEVICE_ARCHIVE" "$FRAMEWORK_NAME" "ios" "$IOS_DEVICE_OUT" "arm64"
|
||||
create_framework "$IOS_SIMULATOR_ARM64_ARCHIVE" "$FRAMEWORK_NAME" "ios-simulator" "$IOS_SIMULATOR_ARM64_OUT" "arm64"
|
||||
create_framework "$IOS_SIMULATOR_X86_64_ARCHIVE" "$FRAMEWORK_NAME" "ios-simulator" "$IOS_SIMULATOR_X86_64_OUT" "x86_64"
|
||||
|
||||
IOS_SIMULATOR_UNIVERSAL_OUT="${TMP_DIR}/ios_simulator_universal"
|
||||
mkdir -p "$IOS_SIMULATOR_UNIVERSAL_OUT"
|
||||
|
||||
SIMULATOR_UNIVERSAL_FRAMEWORK="${IOS_SIMULATOR_UNIVERSAL_OUT}/${FRAMEWORK_NAME}.framework"
|
||||
mkdir -p "$SIMULATOR_UNIVERSAL_FRAMEWORK"
|
||||
|
||||
lipo -create \
|
||||
"${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" \
|
||||
"${IOS_SIMULATOR_X86_64_OUT}/${FRAMEWORK_NAME}.framework/${FRAMEWORK_NAME}" \
|
||||
-output "${SIMULATOR_UNIVERSAL_FRAMEWORK}/${FRAMEWORK_NAME}"
|
||||
|
||||
echo "Created universal simulator binary: ${SIMULATOR_UNIVERSAL_FRAMEWORK}/${FRAMEWORK_NAME}"
|
||||
|
||||
cp -r "${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/Info.plist" "${SIMULATOR_UNIVERSAL_FRAMEWORK}/"
|
||||
cp -r "${IOS_SIMULATOR_ARM64_OUT}/${FRAMEWORK_NAME}.framework/Headers" "${SIMULATOR_UNIVERSAL_FRAMEWORK}/"
|
||||
|
||||
IOS_DEVICE_FRAMEWORK="${IOS_DEVICE_OUT}/${FRAMEWORK_NAME}.framework"
|
||||
IOS_SIMULATOR_FRAMEWORK="${SIMULATOR_UNIVERSAL_FRAMEWORK}"
|
||||
|
||||
IOS_XCFRAMEWORK="${IOS_OUTPUT_DIR}/${FRAMEWORK_NAME}.xcframework"
|
||||
create_xcframework "$FRAMEWORK_NAME" "$IOS_XCFRAMEWORK" "$IOS_DEVICE_FRAMEWORK" "$IOS_SIMULATOR_FRAMEWORK"
|
||||
|
||||
echo ""
|
||||
echo "XCFramework created successfully:"
|
||||
echo " iOS XCFramework: ${IOS_XCFRAMEWORK}"
|
||||
echo ""
|
||||
|
||||
FFIGEN_CONFIG="${BASE_DIR}/../../cw_mweb/ffigen_config.yaml"
|
||||
if [[ -f "$FFIGEN_CONFIG" ]]; then
|
||||
echo "Updating ffigen configuration..."
|
||||
sed -i.bak "s|android/src/main/jniLibs/arm64-v8a/mweb.h|ios/${FRAMEWORK_NAME}.xcframework/ios-arm64/${FRAMEWORK_NAME}.framework/Headers/${FRAMEWORK_NAME}.h|g" "$FFIGEN_CONFIG"
|
||||
mv "$FFIGEN_CONFIG.bak" "$FFIGEN_CONFIG"
|
||||
echo "Updated ffigen config to use XCFramework header"
|
||||
fi
|
||||
|
||||
cd "${BASE_DIR}/../../cw_mweb"
|
||||
echo "Generating Dart FFI bindings..."
|
||||
dart run ffigen --config ffigen_config.yaml
|
||||
|
||||
echo "Build completed successfully!"
|
||||
|
||||
rm -rf "$TMP_DIR"
|
||||
echo "Temporary files cleaned up."
|
||||
Reference in New Issue
Block a user