diff --git a/.github/workflows/reusable-build.yml b/.github/workflows/reusable-build.yml
index 4dc4475735..1dafcd89d7 100644
--- a/.github/workflows/reusable-build.yml
+++ b/.github/workflows/reusable-build.yml
@@ -119,6 +119,13 @@ jobs:
./app_config.sh
popd
+ - name: Build PIVX Sapling Lib
+ run: |
+ set -x -e
+ pushd scripts/android
+ ./build_pivx.sh
+ popd
+
- name: Install Flutter dependencies
run: |
flutter pub get
diff --git a/.gitignore b/.gitignore
index 2b437f06ed..b38dbc96f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -145,6 +145,7 @@ lib/dogecoin/dogecoin.dart
lib/base/base.dart
lib/arbitrum/arbitrum.dart
lib/evm/evm.dart
+lib/pivx/pivx.dart
lib/zcash/zcash.dart
ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
diff --git a/assets/images/pivx_chain_qr.svg b/assets/images/pivx_chain_qr.svg
new file mode 100644
index 0000000000..894412317c
--- /dev/null
+++ b/assets/images/pivx_chain_qr.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/images/pivx_icon.png b/assets/images/pivx_icon.png
index 0b3b80eb13..fa70fa7370 100644
Binary files a/assets/images/pivx_icon.png and b/assets/images/pivx_icon.png differ
diff --git a/assets/pivx_electrum_server_list.yml b/assets/pivx_electrum_server_list.yml
new file mode 100644
index 0000000000..4047ab636e
--- /dev/null
+++ b/assets/pivx_electrum_server_list.yml
@@ -0,0 +1,17 @@
+-
+ uri: electrum02.chainster.org:50002
+ is_default: true
+ useSSL: true
+ isEnabledForAutoSwitching: true
+-
+ uri: electrum01.chainster.org:50002
+ useSSL: true
+ isEnabledForAutoSwitching: true
+-
+ uri: electrum02.chainster.org:50001
+ useSSL: false
+ isEnabledForAutoSwitching: true
+-
+ uri: electrum01.chainster.org:50001
+ useSSL: false
+ isEnabledForAutoSwitching: true
diff --git a/cw_bitcoin/lib/electrum.dart b/cw_bitcoin/lib/electrum.dart
index b3bc6e843d..d8f700afb4 100644
--- a/cw_bitcoin/lib/electrum.dart
+++ b/cw_bitcoin/lib/electrum.dart
@@ -106,12 +106,17 @@ class ElectrumClient {
(Uint8List event) {
try {
final msg = utf8.decode(event.toList());
- final messagesList = msg.split("\n");
- for (var message in messagesList) {
- if (message.isEmpty) {
- continue;
+ // Accumulate across reads; large responses span multiple TCP packets.
+ unterminatedString += msg;
+
+ while (unterminatedString.contains('\n')) {
+ final newlineIndex = unterminatedString.indexOf('\n');
+ final completeLine = unterminatedString.substring(0, newlineIndex);
+ unterminatedString = unterminatedString.substring(newlineIndex + 1);
+
+ if (completeLine.isNotEmpty) {
+ _parseResponse(completeLine);
}
- _parseResponse(message);
}
} catch (e) {
printV("socket.listen: $e");
@@ -637,6 +642,15 @@ class ElectrumClient {
id: 'blockchain.headers.subscribe', method: 'blockchain.headers.subscribe');
}
+ // PIVX Sapling 0-conf mempool push feed: initial snapshot then the same
+ // envelope on every change.
+ BehaviorSubject