diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 18ad16e4b..272f7bbee 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -11,3 +11,4 @@ Please include a summary of the changes and which issue is fixed / feature is ad
- [ ] Format code
- [ ] Look for code duplication
- [ ] Clear naming for variables and methods
+- [ ] Manual tests in accessibility mode (TalkBack on Android) passed
diff --git a/.github/workflows/automated_integration_test.yml b/.github/workflows/automated_integration_test.yml
index 84c680dda..a26e3645d 100644
--- a/.github/workflows/automated_integration_test.yml
+++ b/.github/workflows/automated_integration_test.yml
@@ -55,7 +55,7 @@ jobs:
- name: Flutter action
uses: subosito/flutter-action@v1
with:
- flutter-version: "3.27.4"
+ flutter-version: "3.27.0"
channel: stable
- name: Install package dependencies
diff --git a/.github/workflows/pr_test_build_android.yml b/.github/workflows/pr_test_build_android.yml
index 8f6139747..cdbd7ca37 100644
--- a/.github/workflows/pr_test_build_android.yml
+++ b/.github/workflows/pr_test_build_android.yml
@@ -9,7 +9,7 @@ jobs:
PR_test_build:
runs-on: linux-amd64
container:
- image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1
+ image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
env:
STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
@@ -253,6 +253,11 @@ jobs:
- name: Build generated code
run: |
+ flutter --version
+ flutter clean
+ rm -rf .dart_tool
+ rm pubspec.lock
+ flutter pub get
./model_generator.sh async
- name: Generate key properties
diff --git a/.github/workflows/pr_test_build_linux.yml b/.github/workflows/pr_test_build_linux.yml
index a341aed0d..119cd7530 100644
--- a/.github/workflows/pr_test_build_linux.yml
+++ b/.github/workflows/pr_test_build_linux.yml
@@ -9,7 +9,7 @@ jobs:
PR_test_build:
runs-on: linux-amd64
container:
- image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1
+ image: ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
env:
STORE_PASS: test@cake_wallet
KEY_PASS: test@cake_wallet
@@ -283,6 +283,9 @@ jobs:
xmessage -timeout 30 "restore_wallet_through_seeds_flow_test" &
rm -rf ~/.local/share/com.example.cake_wallet/ ~/Documents/cake_wallet/ ~/cake_wallet
exec timeout --signal=SIGKILL 900 flutter drive --driver=test_driver/integration_test.dart --target=integration_test/test_suites/restore_wallet_through_seeds_flow_test.dart
+ - name: Test [cw_monero]
+ timeout-minutes: 2
+ run: cd cw_monero && flutter test
- name: Stop screen recording, encrypt and upload
if: always()
run: |
diff --git a/.gitignore b/.gitignore
index 89eafe975..98ac9ab3a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -143,9 +143,28 @@ lib/zano/zano.dart
lib/decred/decred.dart
lib/xelis/xelis.dart
-ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_180.png
-ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_120.png
-ios/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@2x~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon@3x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29@3x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40@3x.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x~car.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x~car.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ios-marketing.png
+ios/Runner/Assets.xcassets/AppIcon.appiconset/AppIcon~ipad.png
+
ios/Runner/Info.plist
android/app/src/main/res/mipmap-*
android/app/src/main/res/drawable/ic_launcher.png
diff --git a/Dockerfile b/Dockerfile
index 84179d645..151b7af20 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-# docker buildx build --push --pull --platform linux/amd64,linux/arm64 . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.4-go1.24.1
+# docker buildx build --push --pull --platform linux/amd64,linux/arm64 . -f Dockerfile -t ghcr.io/cake-tech/cake_wallet:debian12-flutter3.27.0-go1.24.1-ruststablenightly
# Heavily inspired by cirrusci images
# https://github.com/cirruslabs/docker-images-android/blob/master/sdk/tools/Dockerfile
@@ -15,11 +15,11 @@ LABEL org.opencontainers.image.source=https://github.com/cake-tech/cake_wallet
ENV GOLANG_VERSION=1.24.1
# Pin Flutter version to latest known-working version
-ENV FLUTTER_VERSION=3.27.4
+ENV FLUTTER_VERSION=3.27.0
# Pin Android Studio, platform, and build tools versions to latest known-working version
# Comes from https://developer.android.com/studio/#command-tools
-ENV ANDROID_SDK_TOOLS_VERSION=11076708
+ENV ANDROID_SDK_TOOLS_VERSION=13114758
# Comes from https://developer.android.com/studio/releases/build-tools
ENV ANDROID_PLATFORM_VERSION=35
ENV ANDROID_BUILD_TOOLS_VERSION=34.0.0
@@ -164,9 +164,12 @@ RUN (addgroup kvm || true) && \
ENV PATH=${HOME}/.cargo/bin:${PATH}
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y && \
cargo install cargo-ndk && \
+ for toolchain in stable nightly; \
+ do \
for target in aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android x86_64-unknown-linux-gnu aarch64-unknown-linux-gnu aarch64-unknown-linux-gnu; \
do \
- rustup target add --toolchain stable $target; \
+ rustup target add --toolchain $toolchain $target; \
+ done \
done
# Download and install Flutter
@@ -175,8 +178,11 @@ ENV FLUTTER_HOME=${HOME}/sdks/flutter/${FLUTTER_VERSION}
ENV FLUTTER_ROOT=$FLUTTER_HOME
ENV PATH=${PATH}:${FLUTTER_HOME}/bin:${FLUTTER_HOME}/bin/cache/dart-sdk/bin
-RUN git clone --depth 1 --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} \
- && yes | flutter doctor --android-licenses \
+RUN git clone --branch ${FLUTTER_VERSION} https://github.com/flutter/flutter.git ${FLUTTER_HOME} && \
+ cd ${FLUTTER_HOME} && \
+ git fetch -a
+
+RUN yes | flutter doctor --android-licenses \
&& flutter doctor \
&& chown -R root:root ${FLUTTER_HOME}
diff --git a/README.md b/README.md
index bea4c962e..1790c4e68 100644
--- a/README.md
+++ b/README.md
@@ -26,10 +26,13 @@ Cake Wallet includes support for several cryptocurrencies, including:
* Ethereum (ETH)
* Litecoin (LTC)
* Bitcoin Cash (BCH)
-* Polygon (Pol)
+* Polygon (POL)
* Solana (SOL)
+* Tron (TRX)
* Nano (XNO)
-* Haven (XHV)
+* Zano (ZANO)
+* Decred (DCR)
+* Wownero (WOW)
## Features
@@ -87,10 +90,6 @@ Cake Wallet includes support for several cryptocurrencies, including:
* Add custom tokens by asset ID
* Specify multiple recipients for batch sending
-### Haven Specific Features
-
-* Send, receive, and store XHV and all xAssets like xUSD, xEUR, xAG, etc.
-
# Monero.com by Cake Wallet for Android and iOS
## Open Source Monero-Only Wallet
diff --git a/android/app/build.gradle b/android/app/build.gradle
index c45ed9368..4a8045bb3 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -42,6 +42,14 @@ android {
disable 'InvalidPackage'
}
+ compileOptions {
+ coreLibraryDesugaringEnabled true
+
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+
+
namespace "com.cakewallet.cake_wallet"
defaultConfig {
@@ -73,10 +81,6 @@ android {
buildTypes {
release {
signingConfig signingConfigs.release
-
- shrinkResources false
- minifyEnabled false
-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
@@ -95,6 +99,7 @@ dependencies {
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
+ coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
configurations {
implementation.exclude module:'proto-google-common-protos'
diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro
index d24d7f10a..a733bae9e 100644
--- a/android/app/proguard-rules.pro
+++ b/android/app/proguard-rules.pro
@@ -5,4 +5,98 @@
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
--dontwarn io.flutter.embedding.**
\ No newline at end of file
+-dontwarn io.flutter.embedding.**
+-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication
+
+# start reown
+-dontwarn com.github.luben.zstd.BufferPool
+-dontwarn com.github.luben.zstd.ZstdInputStream
+-dontwarn com.github.luben.zstd.ZstdOutputStream
+-dontwarn com.google.api.client.http.GenericUrl
+-dontwarn com.google.api.client.http.HttpHeaders
+-dontwarn com.google.api.client.http.HttpRequest
+-dontwarn com.google.api.client.http.HttpRequestFactory
+-dontwarn com.google.api.client.http.HttpResponse
+-dontwarn com.google.api.client.http.HttpTransport
+-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder
+-dontwarn com.google.api.client.http.javanet.NetHttpTransport
+-dontwarn java.awt.Color
+-dontwarn java.awt.Dimension
+-dontwarn java.awt.Graphics2D
+-dontwarn java.awt.Graphics
+-dontwarn java.awt.Image
+-dontwarn java.awt.Point
+-dontwarn java.awt.Polygon
+-dontwarn java.awt.Shape
+-dontwarn java.awt.color.ColorSpace
+-dontwarn java.awt.geom.AffineTransform
+-dontwarn java.awt.image.BufferedImage
+-dontwarn java.awt.image.ColorModel
+-dontwarn java.awt.image.ComponentColorModel
+-dontwarn java.awt.image.ComponentSampleModel
+-dontwarn java.awt.image.DataBuffer
+-dontwarn java.awt.image.DataBufferByte
+-dontwarn java.awt.image.DataBufferInt
+-dontwarn java.awt.image.DataBufferUShort
+-dontwarn java.awt.image.ImageObserver
+-dontwarn java.awt.image.MultiPixelPackedSampleModel
+-dontwarn java.awt.image.Raster
+-dontwarn java.awt.image.RenderedImage
+-dontwarn java.awt.image.SampleModel
+-dontwarn java.awt.image.SinglePixelPackedSampleModel
+-dontwarn java.awt.image.WritableRaster
+-dontwarn java.beans.BeanInfo
+-dontwarn java.beans.FeatureDescriptor
+-dontwarn java.beans.IntrospectionException
+-dontwarn java.beans.Introspector
+-dontwarn java.beans.PropertyDescriptor
+-dontwarn java.lang.reflect.InaccessibleObjectException
+-dontwarn javax.imageio.IIOImage
+-dontwarn javax.imageio.ImageIO
+-dontwarn javax.imageio.ImageWriteParam
+-dontwarn javax.imageio.ImageWriter
+-dontwarn javax.imageio.metadata.IIOMetadata
+-dontwarn javax.imageio.stream.ImageOutputStream
+-dontwarn javax.swing.JComponent
+-dontwarn javax.swing.JFileChooser
+-dontwarn javax.swing.JFrame
+-dontwarn javax.swing.JPanel
+-dontwarn javax.swing.ProgressMonitor
+-dontwarn javax.swing.SwingUtilities
+-dontwarn org.brotli.dec.BrotliInputStream
+-dontwarn org.joda.time.Instant
+-dontwarn org.objectweb.asm.AnnotationVisitor
+-dontwarn org.objectweb.asm.Attribute
+-dontwarn org.objectweb.asm.ClassReader
+-dontwarn org.objectweb.asm.ClassVisitor
+-dontwarn org.objectweb.asm.FieldVisitor
+-dontwarn org.objectweb.asm.Label
+-dontwarn org.objectweb.asm.MethodVisitor
+-dontwarn org.objectweb.asm.Type
+-dontwarn org.tukaani.xz.ARMOptions
+-dontwarn org.tukaani.xz.ARMThumbOptions
+-dontwarn org.tukaani.xz.DeltaOptions
+-dontwarn org.tukaani.xz.FilterOptions
+-dontwarn org.tukaani.xz.FinishableOutputStream
+-dontwarn org.tukaani.xz.FinishableWrapperOutputStream
+-dontwarn org.tukaani.xz.IA64Options
+-dontwarn org.tukaani.xz.LZMA2InputStream
+-dontwarn org.tukaani.xz.LZMA2Options
+-dontwarn org.tukaani.xz.LZMAInputStream
+-dontwarn org.tukaani.xz.LZMAOutputStream
+-dontwarn org.tukaani.xz.MemoryLimitException
+-dontwarn org.tukaani.xz.PowerPCOptions
+-dontwarn org.tukaani.xz.SPARCOptions
+-dontwarn org.tukaani.xz.SingleXZInputStream
+-dontwarn org.tukaani.xz.UnsupportedOptionsException
+-dontwarn org.tukaani.xz.X86Options
+-dontwarn org.tukaani.xz.XZ
+-dontwarn org.tukaani.xz.XZInputStream
+-dontwarn org.tukaani.xz.XZOutputStream
+-dontwarn us.hebi.matlab.mat.ejml.Mat5Ejml
+-dontwarn us.hebi.matlab.mat.format.Mat5
+-dontwarn us.hebi.matlab.mat.format.Mat5File
+-dontwarn us.hebi.matlab.mat.types.Array
+-dontwarn us.hebi.matlab.mat.types.MatFile$Entry
+-dontwarn us.hebi.matlab.mat.types.MatFile
+# end reown
\ No newline at end of file
diff --git a/android/app/src/main/AndroidManifestBase.xml b/android/app/src/main/AndroidManifestBase.xml
index 9a324edf3..8283a7c8c 100644
--- a/android/app/src/main/AndroidManifestBase.xml
+++ b/android/app/src/main/AndroidManifestBase.xml
@@ -24,6 +24,10 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/images/2fa_warning_light.svg b/assets/images/2fa_warning_light.svg
new file mode 100644
index 000000000..087d8e99b
--- /dev/null
+++ b/assets/images/2fa_warning_light.svg
@@ -0,0 +1,101 @@
+
diff --git a/assets/images/birthday_cake.png b/assets/images/birthday_cake.png
index 84b084fba..293cd10f6 100644
Binary files a/assets/images/birthday_cake.png and b/assets/images/birthday_cake.png differ
diff --git a/assets/images/birthday_cake.svg b/assets/images/birthday_cake.svg
deleted file mode 100644
index b5e31dddb..000000000
--- a/assets/images/birthday_cake.svg
+++ /dev/null
@@ -1,31 +0,0 @@
-
diff --git a/assets/images/btc_lock_dark.png b/assets/images/btc_lock_dark.png
new file mode 100644
index 000000000..f5b3d7e27
Binary files /dev/null and b/assets/images/btc_lock_dark.png differ
diff --git a/assets/images/btc_lock_light.png b/assets/images/btc_lock_light.png
new file mode 100644
index 000000000..4320d96e3
Binary files /dev/null and b/assets/images/btc_lock_light.png differ
diff --git a/assets/images/buy.png b/assets/images/buy.png
index ff4549d5a..32c116e6b 100644
Binary files a/assets/images/buy.png and b/assets/images/buy.png differ
diff --git a/assets/images/cake_logo_dark.svg b/assets/images/cake_logo_dark.svg
new file mode 100644
index 000000000..095077443
--- /dev/null
+++ b/assets/images/cake_logo_dark.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/cake_logo_light.svg b/assets/images/cake_logo_light.svg
new file mode 100644
index 000000000..767e205d1
--- /dev/null
+++ b/assets/images/cake_logo_light.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/contact.png b/assets/images/contact.png
new file mode 100644
index 000000000..5cf96694b
Binary files /dev/null and b/assets/images/contact.png differ
diff --git a/assets/images/hero/cw_welcome_dark.svg b/assets/images/hero/cw_welcome_dark.svg
new file mode 100644
index 000000000..5479cb1ee
--- /dev/null
+++ b/assets/images/hero/cw_welcome_dark.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/hero/cw_welcome_light.svg b/assets/images/hero/cw_welcome_light.svg
new file mode 100644
index 000000000..ece7d1f84
--- /dev/null
+++ b/assets/images/hero/cw_welcome_light.svg
@@ -0,0 +1,5 @@
+
diff --git a/assets/images/history.svg b/assets/images/history.svg
new file mode 100644
index 000000000..f308ab7e3
--- /dev/null
+++ b/assets/images/history.svg
@@ -0,0 +1,10 @@
+
diff --git a/assets/images/home_screen_setting_icon.svg b/assets/images/home_screen_setting_icon.svg
new file mode 100644
index 000000000..7b3aa7b4c
--- /dev/null
+++ b/assets/images/home_screen_setting_icon.svg
@@ -0,0 +1,6 @@
+
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png
new file mode 100644
index 000000000..3fd15f3ce
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png
new file mode 100644
index 000000000..3fd15f3ce
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@2x~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png
new file mode 100644
index 000000000..b6ff994f6
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20@3x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png
new file mode 100644
index 000000000..4be1a2317
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-20~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png
new file mode 100644
index 000000000..219f2c6be
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png
new file mode 100644
index 000000000..ae94bb0ac
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png
new file mode 100644
index 000000000..ae94bb0ac
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@2x~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png
new file mode 100644
index 000000000..0ef9d3bbf
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29@3x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png
new file mode 100644
index 000000000..219f2c6be
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-29~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png
new file mode 100644
index 000000000..9fdb32376
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png
new file mode 100644
index 000000000..9fdb32376
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@2x~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png
new file mode 100644
index 000000000..485f8b37b
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40@3x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png
new file mode 100644
index 000000000..3fd15f3ce
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-40~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png
new file mode 100644
index 000000000..485f8b37b
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@2x~car.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png
new file mode 100644
index 000000000..50148e6dc
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-60@3x~car.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png
new file mode 100644
index 000000000..8f290ada2
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon-83.5@2x~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png
new file mode 100644
index 000000000..485f8b37b
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png
new file mode 100644
index 000000000..b11d7332f
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@2x~ipad.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png
new file mode 100644
index 000000000..50148e6dc
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon@3x.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png
new file mode 100644
index 000000000..1fce95553
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ios-marketing.png differ
diff --git a/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png
new file mode 100644
index 000000000..7d4a82186
Binary files /dev/null and b/assets/images/ios_icons/cakewallet_ios_icons/AppIcon~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png
new file mode 100644
index 000000000..7ea540caf
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png
new file mode 100644
index 000000000..7ea540caf
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@2x~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png
new file mode 100644
index 000000000..6ac773754
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-20@3x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png
new file mode 100644
index 000000000..57864a9b3
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-20~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png
new file mode 100644
index 000000000..27f817dfc
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-29.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png
new file mode 100644
index 000000000..0455b4409
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png
new file mode 100644
index 000000000..0455b4409
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@2x~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png
new file mode 100644
index 000000000..1b8a73481
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-29@3x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png
new file mode 100644
index 000000000..27f817dfc
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-29~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png
new file mode 100644
index 000000000..963612d0c
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png
new file mode 100644
index 000000000..963612d0c
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@2x~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png
new file mode 100644
index 000000000..b6da404cb
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-40@3x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png
new file mode 100644
index 000000000..7ea540caf
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-40~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png
new file mode 100644
index 000000000..b6da404cb
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@2x~car.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png
new file mode 100644
index 000000000..37f7651a5
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-60@3x~car.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png
new file mode 100644
index 000000000..21aa12463
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon-83.5@2x~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png
new file mode 100644
index 000000000..b6da404cb
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png
new file mode 100644
index 000000000..b6b63a61e
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon@2x~ipad.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png b/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png
new file mode 100644
index 000000000..37f7651a5
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon@3x.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png b/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png
new file mode 100644
index 000000000..0c977110a
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon~ios-marketing.png differ
diff --git a/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png b/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png
new file mode 100644
index 000000000..849c5612a
Binary files /dev/null and b/assets/images/ios_icons/monero_ios_icons/AppIcon~ipad.png differ
diff --git a/assets/images/menu.svg b/assets/images/menu.svg
new file mode 100644
index 000000000..0a4cc3784
--- /dev/null
+++ b/assets/images/menu.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/notif.svg b/assets/images/notif.svg
new file mode 100644
index 000000000..b1ff5b4fa
--- /dev/null
+++ b/assets/images/notif.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/images/notification_icon.svg b/assets/images/notification_icon.svg
index 099039e67..360d0b4e6 100644
--- a/assets/images/notification_icon.svg
+++ b/assets/images/notification_icon.svg
@@ -1,69 +1,3 @@
-
-
-
-
\ No newline at end of file
+
diff --git a/assets/images/passphrase_dark.png b/assets/images/passphrase_dark.png
new file mode 100644
index 000000000..f72d1e1a1
Binary files /dev/null and b/assets/images/passphrase_dark.png differ
diff --git a/assets/images/passphrase_key.svg b/assets/images/passphrase_key.svg
new file mode 100644
index 000000000..c577dc30a
--- /dev/null
+++ b/assets/images/passphrase_key.svg
@@ -0,0 +1,22 @@
+
diff --git a/assets/images/passphrase_light.png b/assets/images/passphrase_light.png
new file mode 100644
index 000000000..f86f68156
Binary files /dev/null and b/assets/images/passphrase_light.png differ
diff --git a/assets/images/payjoin.png b/assets/images/payjoin.png
new file mode 100644
index 000000000..1ba3dccdb
Binary files /dev/null and b/assets/images/payjoin.png differ
diff --git a/assets/images/qr-cake.png b/assets/images/qr-cake.png
new file mode 100644
index 000000000..7c54dedb0
Binary files /dev/null and b/assets/images/qr-cake.png differ
diff --git a/assets/images/receive.png b/assets/images/receive.png
new file mode 100644
index 000000000..180a4e5b3
Binary files /dev/null and b/assets/images/receive.png differ
diff --git a/assets/images/seed_verified_dark.png b/assets/images/seed_verified_dark.png
new file mode 100644
index 000000000..cbefa5d8c
Binary files /dev/null and b/assets/images/seed_verified_dark.png differ
diff --git a/assets/images/seed_verified_light.png b/assets/images/seed_verified_light.png
new file mode 100644
index 000000000..a51eddcd7
Binary files /dev/null and b/assets/images/seed_verified_light.png differ
diff --git a/assets/images/seed_warning_dark.svg b/assets/images/seed_warning_dark.svg
new file mode 100644
index 000000000..0a47254ff
--- /dev/null
+++ b/assets/images/seed_warning_dark.svg
@@ -0,0 +1,86 @@
+
diff --git a/assets/images/seed_warning_light.svg b/assets/images/seed_warning_light.svg
new file mode 100644
index 000000000..cab27ec31
--- /dev/null
+++ b/assets/images/seed_warning_light.svg
@@ -0,0 +1,111 @@
+
diff --git a/assets/images/send.png b/assets/images/send.png
deleted file mode 100644
index aef504999..000000000
Binary files a/assets/images/send.png and /dev/null differ
diff --git a/assets/images/send2.png b/assets/images/send2.png
new file mode 100644
index 000000000..85fc570a8
Binary files /dev/null and b/assets/images/send2.png differ
diff --git a/assets/images/swap.png b/assets/images/swap.png
new file mode 100644
index 000000000..fe3fc0893
Binary files /dev/null and b/assets/images/swap.png differ
diff --git a/assets/images/wallet_group_bright.png b/assets/images/wallet_group_bright.png
deleted file mode 100644
index 263361db6..000000000
Binary files a/assets/images/wallet_group_bright.png and /dev/null differ
diff --git a/assets/images/wallet_group_confirmed_dark.png b/assets/images/wallet_group_confirmed_dark.png
new file mode 100644
index 000000000..a047cb29c
Binary files /dev/null and b/assets/images/wallet_group_confirmed_dark.png differ
diff --git a/assets/images/wallet_group_confirmed_light.png b/assets/images/wallet_group_confirmed_light.png
new file mode 100644
index 000000000..851d32300
Binary files /dev/null and b/assets/images/wallet_group_confirmed_light.png differ
diff --git a/assets/images/wallet_group_dark.png b/assets/images/wallet_group_dark.png
deleted file mode 100644
index 7cd08d2cd..000000000
Binary files a/assets/images/wallet_group_dark.png and /dev/null differ
diff --git a/assets/images/wallet_group_empty_dark.png b/assets/images/wallet_group_empty_dark.png
new file mode 100644
index 000000000..e613d876e
Binary files /dev/null and b/assets/images/wallet_group_empty_dark.png differ
diff --git a/assets/images/wallet_group_empty_light.png b/assets/images/wallet_group_empty_light.png
new file mode 100644
index 000000000..f795648ae
Binary files /dev/null and b/assets/images/wallet_group_empty_light.png differ
diff --git a/assets/images/wallet_group_light.png b/assets/images/wallet_group_light.png
deleted file mode 100644
index 7827971e7..000000000
Binary files a/assets/images/wallet_group_light.png and /dev/null differ
diff --git a/assets/images/wallet_group_options_dark.png b/assets/images/wallet_group_options_dark.png
new file mode 100644
index 000000000..479aac57c
Binary files /dev/null and b/assets/images/wallet_group_options_dark.png differ
diff --git a/assets/images/wallet_group_options_light.png b/assets/images/wallet_group_options_light.png
new file mode 100644
index 000000000..308930520
Binary files /dev/null and b/assets/images/wallet_group_options_light.png differ
diff --git a/assets/images/wallet_name.png b/assets/images/wallet_name.png
deleted file mode 100644
index f586682bd..000000000
Binary files a/assets/images/wallet_name.png and /dev/null differ
diff --git a/assets/images/wallet_name_light.png b/assets/images/wallet_name_light.png
deleted file mode 100644
index 0199c1b30..000000000
Binary files a/assets/images/wallet_name_light.png and /dev/null differ
diff --git a/assets/images/wallet_type.png b/assets/images/wallet_type.png
deleted file mode 100644
index 4e0eba8b5..000000000
Binary files a/assets/images/wallet_type.png and /dev/null differ
diff --git a/assets/images/wallet_type_light.png b/assets/images/wallet_type_light.png
deleted file mode 100644
index e36c0d3aa..000000000
Binary files a/assets/images/wallet_type_light.png and /dev/null differ
diff --git a/assets/images/wallet_type_wallet_dark.png b/assets/images/wallet_type_wallet_dark.png
new file mode 100644
index 000000000..b840f5547
Binary files /dev/null and b/assets/images/wallet_type_wallet_dark.png differ
diff --git a/assets/images/wallet_type_wallet_light.png b/assets/images/wallet_type_wallet_light.png
new file mode 100644
index 000000000..ee759a109
Binary files /dev/null and b/assets/images/wallet_type_wallet_light.png differ
diff --git a/assets/images/wallets.png b/assets/images/wallets.png
new file mode 100644
index 000000000..62ea20039
Binary files /dev/null and b/assets/images/wallets.png differ
diff --git a/assets/images/welcome.png b/assets/images/welcome.png
deleted file mode 100644
index f1132d253..000000000
Binary files a/assets/images/welcome.png and /dev/null differ
diff --git a/assets/images/welcome_dark_theme.svg b/assets/images/welcome_dark_theme.svg
new file mode 100644
index 000000000..8f60c931a
--- /dev/null
+++ b/assets/images/welcome_dark_theme.svg
@@ -0,0 +1,215 @@
+
diff --git a/assets/images/welcome_light.png b/assets/images/welcome_light.png
deleted file mode 100644
index 6feff85d1..000000000
Binary files a/assets/images/welcome_light.png and /dev/null differ
diff --git a/assets/images/welcome_light_theme.svg b/assets/images/welcome_light_theme.svg
new file mode 100644
index 000000000..178b2853d
--- /dev/null
+++ b/assets/images/welcome_light_theme.svg
@@ -0,0 +1,14 @@
+
diff --git a/assets/images/welcome_wallet_dark.png b/assets/images/welcome_wallet_dark.png
new file mode 100644
index 000000000..771a600d3
Binary files /dev/null and b/assets/images/welcome_wallet_dark.png differ
diff --git a/assets/images/welcome_wallet_light.png b/assets/images/welcome_wallet_light.png
new file mode 100644
index 000000000..2a738be0b
Binary files /dev/null and b/assets/images/welcome_wallet_light.png differ
diff --git a/assets/images/wyre-icon.png b/assets/images/wyre-icon.png
deleted file mode 100644
index a2810948e..000000000
Binary files a/assets/images/wyre-icon.png and /dev/null differ
diff --git a/assets/images/wyre.png b/assets/images/wyre.png
deleted file mode 100644
index a16bbdc8b..000000000
Binary files a/assets/images/wyre.png and /dev/null differ
diff --git a/assets/images/yat_crypto.png b/assets/images/yat_crypto.png
deleted file mode 100644
index fbd5d2483..000000000
Binary files a/assets/images/yat_crypto.png and /dev/null differ
diff --git a/assets/node_list.yml b/assets/node_list.yml
index 49cc00a94..917dadfd9 100644
--- a/assets/node_list.yml
+++ b/assets/node_list.yml
@@ -13,9 +13,3 @@
-
uri: nodes.hashvault.pro:18081
is_default: false
--
- uri: node.c3pool.com:18081
- is_default: false
--
- uri: node.community.rino.io:18081
- is_default: false
diff --git a/assets/text/Monerocom_Release_Notes.txt b/assets/text/Monerocom_Release_Notes.txt
index 1b2cc3a6d..1176d3d8c 100644
--- a/assets/text/Monerocom_Release_Notes.txt
+++ b/assets/text/Monerocom_Release_Notes.txt
@@ -1,3 +1,3 @@
-UI/UX enhancements
-Performance improvements
+New themes and UI/UX improvements
+Ledger flow enhancements
Bug fixes
\ No newline at end of file
diff --git a/assets/text/Release_Notes.txt b/assets/text/Release_Notes.txt
index 00a65ff57..6afc88fa1 100644
--- a/assets/text/Release_Notes.txt
+++ b/assets/text/Release_Notes.txt
@@ -1,4 +1,4 @@
-New App Logo
-UI/UX enhancements
-Performance improvements
+New themes and UI/UX improvements
+Payjoin enhancements
+Ledger flow enhancements
Bug fixes
\ No newline at end of file
diff --git a/cw_bitcoin/lib/address_from_output.dart b/cw_bitcoin/lib/address_from_output.dart
index 73bc101c4..0d985b237 100644
--- a/cw_bitcoin/lib/address_from_output.dart
+++ b/cw_bitcoin/lib/address_from_output.dart
@@ -2,22 +2,37 @@ import 'package:bitcoin_base/bitcoin_base.dart';
String addressFromOutputScript(Script script, BasedUtxoNetwork network) {
try {
- switch (script.getAddressType()) {
- case P2pkhAddressType.p2pkh:
- return P2pkhAddress.fromScriptPubkey(script: script).toAddress(network);
- case P2shAddressType.p2pkInP2sh:
- return P2shAddress.fromScriptPubkey(script: script).toAddress(network);
- case SegwitAddresType.p2wpkh:
- return P2wpkhAddress.fromScriptPubkey(script: script).toAddress(network);
- case P2shAddressType.p2pkhInP2sh:
- return P2shAddress.fromScriptPubkey(script: script).toAddress(network);
- case SegwitAddresType.p2wsh:
- return P2wshAddress.fromScriptPubkey(script: script).toAddress(network);
- case SegwitAddresType.p2tr:
- return P2trAddress.fromScriptPubkey(script: script).toAddress(network);
- default:
- }
+ return addressFromScript(script, network).toAddress(network);
} catch (_) {}
return '';
}
+
+BitcoinBaseAddress addressFromScript(Script script,
+ [BasedUtxoNetwork network = BitcoinNetwork.mainnet]) {
+ final addressType = script.getAddressType();
+ if (addressType == null) {
+ throw ArgumentError("Invalid script");
+ }
+
+ switch (addressType) {
+ case P2pkhAddressType.p2pkh:
+ return P2pkhAddress.fromScriptPubkey(
+ script: script, network: BitcoinNetwork.mainnet);
+ case P2shAddressType.p2pkhInP2sh:
+ case P2shAddressType.p2pkInP2sh:
+ return P2shAddress.fromScriptPubkey(
+ script: script, network: BitcoinNetwork.mainnet);
+ case SegwitAddresType.p2wpkh:
+ return P2wpkhAddress.fromScriptPubkey(
+ script: script, network: BitcoinNetwork.mainnet);
+ case SegwitAddresType.p2wsh:
+ return P2wshAddress.fromScriptPubkey(
+ script: script, network: BitcoinNetwork.mainnet);
+ case SegwitAddresType.p2tr:
+ return P2trAddress.fromScriptPubkey(
+ script: script, network: BitcoinNetwork.mainnet);
+ }
+
+ throw ArgumentError("Invalid script");
+}
diff --git a/cw_bitcoin/lib/bitcoin_address_record.dart b/cw_bitcoin/lib/bitcoin_address_record.dart
index 7e4b5f58f..1509f913a 100644
--- a/cw_bitcoin/lib/bitcoin_address_record.dart
+++ b/cw_bitcoin/lib/bitcoin_address_record.dart
@@ -1,4 +1,5 @@
import 'dart:convert';
+import 'package:mobx/mobx.dart';
import 'package:bitcoin_base/bitcoin_base.dart';
@@ -16,7 +17,7 @@ abstract class BaseBitcoinAddressRecord {
}) : _txCount = txCount,
_balance = balance,
_name = name,
- _isUsed = isUsed;
+ _isUsed = Observable(isUsed);
@override
bool operator ==(Object o) => o is BaseBitcoinAddressRecord && address == o.address;
@@ -27,7 +28,7 @@ abstract class BaseBitcoinAddressRecord {
int _txCount;
int _balance;
String _name;
- bool _isUsed;
+ final Observable _isUsed;
BasedUtxoNetwork? network;
int get txCount => _txCount;
@@ -40,9 +41,9 @@ abstract class BaseBitcoinAddressRecord {
set balance(int value) => _balance = value;
- bool get isUsed => _isUsed;
+ bool get isUsed => _isUsed.value;
- void setAsUsed() => _isUsed = true;
+ void setAsUsed() => _isUsed.value = true;
void setNewName(String label) => _name = label;
int get hashCode => address.hashCode;
diff --git a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart
index 01e905fb0..7d6894e14 100644
--- a/cw_bitcoin/lib/bitcoin_transaction_credentials.dart
+++ b/cw_bitcoin/lib/bitcoin_transaction_credentials.dart
@@ -3,11 +3,17 @@ import 'package:cw_core/output_info.dart';
import 'package:cw_core/unspent_coin_type.dart';
class BitcoinTransactionCredentials {
- BitcoinTransactionCredentials(this.outputs,
- {required this.priority, this.feeRate, this.coinTypeToSpendFrom = UnspentCoinType.any});
+ BitcoinTransactionCredentials(
+ this.outputs, {
+ required this.priority,
+ this.feeRate,
+ this.coinTypeToSpendFrom = UnspentCoinType.any,
+ this.payjoinUri,
+ });
final List outputs;
final BitcoinTransactionPriority? priority;
final int? feeRate;
final UnspentCoinType coinTypeToSpendFrom;
+ final String? payjoinUri;
}
diff --git a/cw_bitcoin/lib/bitcoin_wallet.dart b/cw_bitcoin/lib/bitcoin_wallet.dart
index 7135d0a7a..a23b72660 100644
--- a/cw_bitcoin/lib/bitcoin_wallet.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet.dart
@@ -3,22 +3,33 @@ import 'dart:convert';
import 'package:bip39/bip39.dart' as bip39;
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/blockchain_utils.dart';
+import 'package:cw_bitcoin/address_from_output.dart';
import 'package:cw_bitcoin/bitcoin_address_record.dart';
import 'package:cw_bitcoin/bitcoin_mnemonic.dart';
-import 'package:cw_bitcoin/psbt_transaction_builder.dart';
-import 'package:cw_core/encryption_file_utils.dart';
-import 'package:cw_bitcoin/electrum_derivations.dart';
+import 'package:cw_bitcoin/bitcoin_transaction_credentials.dart';
import 'package:cw_bitcoin/bitcoin_wallet_addresses.dart';
import 'package:cw_bitcoin/electrum_balance.dart';
+import 'package:cw_bitcoin/electrum_derivations.dart';
import 'package:cw_bitcoin/electrum_wallet.dart';
import 'package:cw_bitcoin/electrum_wallet_snapshot.dart';
+import 'package:cw_bitcoin/payjoin/manager.dart';
+import 'package:cw_bitcoin/payjoin/storage.dart';
+import 'package:cw_bitcoin/pending_bitcoin_transaction.dart';
+import 'package:cw_bitcoin/psbt/signer.dart';
+import 'package:cw_bitcoin/psbt/transaction_builder.dart';
+import 'package:cw_bitcoin/psbt/v0_deserialize.dart';
+import 'package:cw_bitcoin/psbt/v0_finalizer.dart';
import 'package:cw_core/crypto_currency.dart';
+import 'package:cw_core/encryption_file_utils.dart';
+import 'package:cw_core/payjoin_session.dart';
+import 'package:cw_core/pending_transaction.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:cw_core/wallet_keys_file.dart';
import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:ledger_bitcoin/ledger_bitcoin.dart';
+import 'package:ledger_bitcoin/psbt.dart';
import 'package:ledger_flutter_plus/ledger_flutter_plus.dart';
import 'package:mobx/mobx.dart';
@@ -31,6 +42,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
required String password,
required WalletInfo walletInfo,
required Box unspentCoinsInfo,
+ required Box payjoinBox,
required EncryptionFileUtils encryptionFileUtils,
Uint8List? seedBytes,
String? mnemonic,
@@ -71,20 +83,21 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
// String derivationPath = walletInfo.derivationInfo!.derivationPath!;
// String sideDerivationPath = derivationPath.substring(0, derivationPath.length - 1) + "1";
// final hd = bitcoin.HDWallet.fromSeed(seedBytes, network: networkType);
- walletAddresses = BitcoinWalletAddresses(
- walletInfo,
- initialAddresses: initialAddresses,
- initialRegularAddressIndex: initialRegularAddressIndex,
- initialChangeAddressIndex: initialChangeAddressIndex,
- initialSilentAddresses: initialSilentAddresses,
- initialSilentAddressIndex: initialSilentAddressIndex,
- mainHd: hd,
- sideHd: accountHD.childKey(Bip32KeyIndex(1)),
- network: networkParam ?? network,
- masterHd:
- seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
- isHardwareWallet: walletInfo.isHardwareWallet,
- );
+
+ payjoinManager = PayjoinManager(PayjoinStorage(payjoinBox), this);
+ walletAddresses = BitcoinWalletAddresses(walletInfo,
+ initialAddresses: initialAddresses,
+ initialRegularAddressIndex: initialRegularAddressIndex,
+ initialChangeAddressIndex: initialChangeAddressIndex,
+ initialSilentAddresses: initialSilentAddresses,
+ initialSilentAddressIndex: initialSilentAddressIndex,
+ mainHd: hd,
+ sideHd: accountHD.childKey(Bip32KeyIndex(1)),
+ network: networkParam ?? network,
+ masterHd:
+ seedBytes != null ? Bip32Slip10Secp256k1.fromSeed(seedBytes) : null,
+ isHardwareWallet: walletInfo.isHardwareWallet,
+ payjoinManager: payjoinManager);
autorun((_) {
this.walletAddresses.isEnabledAutoGenerateSubaddress =
@@ -100,6 +113,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
required String password,
required WalletInfo walletInfo,
required Box unspentCoinsInfo,
+ required Box payjoinBox,
required EncryptionFileUtils encryptionFileUtils,
String? passphrase,
String? addressPageType,
@@ -122,9 +136,11 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
break;
case DerivationType.electrum:
default:
- seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
+ seedBytes =
+ await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
break;
}
+
return BitcoinWallet(
mnemonic: mnemonic,
passphrase: passphrase ?? "",
@@ -141,6 +157,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
initialChangeAddressIndex: initialChangeAddressIndex,
addressPageType: addressPageType,
networkParam: network,
+ payjoinBox: payjoinBox,
);
}
@@ -148,6 +165,7 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
required String name,
required WalletInfo walletInfo,
required Box unspentCoinsInfo,
+ required Box payjoinBox,
required String password,
required EncryptionFileUtils encryptionFileUtils,
required bool alwaysScan,
@@ -204,7 +222,8 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
if (mnemonic != null) {
switch (walletInfo.derivationInfo!.derivationType) {
case DerivationType.electrum:
- seedBytes = await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
+ seedBytes =
+ await mnemonicToSeedBytes(mnemonic, passphrase: passphrase ?? "");
break;
case DerivationType.bip39:
default:
@@ -217,24 +236,24 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
}
return BitcoinWallet(
- mnemonic: mnemonic,
- xpub: keysData.xPub,
- password: password,
- passphrase: passphrase,
- walletInfo: walletInfo,
- unspentCoinsInfo: unspentCoinsInfo,
- initialAddresses: snp?.addresses,
- initialSilentAddresses: snp?.silentAddresses,
- initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
- initialBalance: snp?.balance,
- encryptionFileUtils: encryptionFileUtils,
- seedBytes: seedBytes,
- initialRegularAddressIndex: snp?.regularAddressIndex,
- initialChangeAddressIndex: snp?.changeAddressIndex,
- addressPageType: snp?.addressPageType,
- networkParam: network,
- alwaysScan: alwaysScan,
- );
+ mnemonic: mnemonic,
+ xpub: keysData.xPub,
+ password: password,
+ passphrase: passphrase,
+ walletInfo: walletInfo,
+ unspentCoinsInfo: unspentCoinsInfo,
+ initialAddresses: snp?.addresses,
+ initialSilentAddresses: snp?.silentAddresses,
+ initialSilentAddressIndex: snp?.silentAddressIndex ?? 0,
+ initialBalance: snp?.balance,
+ encryptionFileUtils: encryptionFileUtils,
+ seedBytes: seedBytes,
+ initialRegularAddressIndex: snp?.regularAddressIndex,
+ initialChangeAddressIndex: snp?.changeAddressIndex,
+ addressPageType: snp?.addressPageType,
+ networkParam: network,
+ alwaysScan: alwaysScan,
+ payjoinBox: payjoinBox);
}
LedgerConnection? _ledgerConnection;
@@ -247,20 +266,25 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
derivationPath: walletInfo.derivationInfo!.derivationPath!);
}
- @override
- Future buildHardwareWalletTransaction({
+ late final PayjoinManager payjoinManager;
+
+ bool get isPayjoinAvailable => unspentCoinsInfo.values
+ .where((element) =>
+ element.walletId == id && element.isSending && !element.isFrozen)
+ .isNotEmpty;
+
+ Future buildPsbt({
required List outputs,
required BigInt fee,
required BasedUtxoNetwork network,
required List utxos,
required Map publicKeys,
+ required Uint8List masterFingerprint,
String? memo,
bool enableRBF = false,
BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
}) async {
- final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint();
-
final psbtReadyInputs = [];
for (final utxo in utxos) {
final rawTx =
@@ -278,13 +302,128 @@ abstract class BitcoinWalletBase extends ElectrumWallet with Store {
));
}
- final psbt = PSBTTransactionBuild(
- inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF);
+ return PSBTTransactionBuild(
+ inputs: psbtReadyInputs, outputs: outputs, enableRBF: enableRBF)
+ .psbt;
+ }
- final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt.psbt);
+ @override
+ Future buildHardwareWalletTransaction({
+ required List outputs,
+ required BigInt fee,
+ required BasedUtxoNetwork network,
+ required List utxos,
+ required Map publicKeys,
+ String? memo,
+ bool enableRBF = false,
+ BitcoinOrdering inputOrdering = BitcoinOrdering.bip69,
+ BitcoinOrdering outputOrdering = BitcoinOrdering.bip69,
+ }) async {
+ final masterFingerprint = await _bitcoinLedgerApp!.getMasterFingerprint();
+
+ final psbt = await buildPsbt(
+ outputs: outputs,
+ fee: fee,
+ network: network,
+ utxos: utxos,
+ publicKeys: publicKeys,
+ masterFingerprint: masterFingerprint,
+ memo: memo,
+ enableRBF: enableRBF,
+ inputOrdering: inputOrdering,
+ outputOrdering: outputOrdering,
+ );
+
+ final rawHex = await _bitcoinLedgerApp!.signPsbt(psbt: psbt);
return BtcTransaction.fromRaw(BytesUtils.toHexString(rawHex));
}
+ @override
+ Future createTransaction(Object credentials) async {
+ credentials = credentials as BitcoinTransactionCredentials;
+
+ final tx = (await super.createTransaction(credentials))
+ as PendingBitcoinTransaction;
+
+ final payjoinUri = credentials.payjoinUri;
+ if (payjoinUri == null) return tx;
+
+ final transaction = await buildPsbt(
+ utxos: tx.utxos,
+ outputs: tx.outputs
+ .map((e) => BitcoinOutput(
+ address: addressFromScript(e.scriptPubKey),
+ value: e.amount,
+ isSilentPayment: e.isSilentPayment,
+ isChange: e.isChange,
+ ))
+ .toList(),
+ fee: BigInt.from(tx.fee),
+ network: network,
+ memo: credentials.outputs.first.memo,
+ outputOrdering: BitcoinOrdering.none,
+ enableRBF: true,
+ publicKeys: tx.publicKeys!,
+ masterFingerprint: Uint8List(0));
+
+ final originalPsbt = await signPsbt(
+ base64.encode(transaction.asPsbtV0()), getUtxoWithPrivateKeys());
+
+ tx.commitOverride = () async {
+ final sender = await payjoinManager.initSender(
+ payjoinUri, originalPsbt, int.parse(tx.feeRate));
+ payjoinManager.spawnNewSender(
+ sender: sender, pjUrl: payjoinUri, amount: BigInt.from(tx.amount));
+ };
+
+ return tx;
+ }
+
+ List getUtxoWithPrivateKeys() => unspentCoins
+ .where((e) => (e.isSending && !e.isFrozen))
+ .map((unspent) => UtxoWithPrivateKey.fromUnspent(unspent, this))
+ .toList();
+
+ Future commitPsbt(String finalizedPsbt) {
+ final psbt = PsbtV2()..deserializeV0(base64.decode(finalizedPsbt));
+
+ final btcTx =
+ BtcTransaction.fromRaw(BytesUtils.toHexString(psbt.extract()));
+
+ return PendingBitcoinTransaction(
+ btcTx,
+ type,
+ electrumClient: electrumClient,
+ amount: 0,
+ fee: 0,
+ feeRate: "",
+ network: network,
+ hasChange: true,
+ ).commit();
+ }
+
+ Future signPsbt(
+ String preProcessedPsbt, List utxos) async {
+ final psbt = PsbtV2()..deserializeV0(base64Decode(preProcessedPsbt));
+
+ await psbt.signWithUTXO(utxos, (txDigest, utxo, key, sighash) {
+ return utxo.utxo.isP2tr()
+ ? key.signTapRoot(
+ txDigest,
+ sighash: sighash,
+ tweak: utxo.utxo.isSilentPayment != true,
+ )
+ : key.signInput(txDigest, sigHash: sighash);
+ }, (txId, vout) async {
+ final txHex = await electrumClient.getTransactionHex(hash: txId);
+ final output = BtcTransaction.fromRaw(txHex).outputs[vout];
+ return TaprootAmountScriptPair(output.amount, output.scriptPubKey);
+ });
+
+ psbt.finalizeV0();
+ return base64Encode(psbt.asPsbtV0());
+ }
+
@override
Future signMessage(String message, {String? address = null}) async {
if (walletInfo.isHardwareWallet) {
diff --git a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
index 1a122ef9e..a92c4770f 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_addresses.dart
@@ -1,10 +1,13 @@
import 'package:bitcoin_base/bitcoin_base.dart';
import 'package:blockchain_utils/bip/bip/bip32/bip32.dart';
import 'package:cw_bitcoin/electrum_wallet_addresses.dart';
+import 'package:cw_bitcoin/payjoin/manager.dart';
import 'package:cw_bitcoin/utils.dart';
import 'package:cw_core/unspent_coin_type.dart';
+import 'package:cw_core/utils/print_verbose.dart';
import 'package:cw_core/wallet_info.dart';
import 'package:mobx/mobx.dart';
+import 'package:payjoin_flutter/receive.dart' as payjoin;
part 'bitcoin_wallet_addresses.g.dart';
@@ -17,6 +20,7 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
required super.sideHd,
required super.network,
required super.isHardwareWallet,
+ required this.payjoinManager,
super.initialAddresses,
super.initialRegularAddressIndex,
super.initialChangeAddressIndex,
@@ -25,6 +29,13 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
super.masterHd,
}) : super(walletInfo);
+ final PayjoinManager payjoinManager;
+
+ payjoin.Receiver? currentPayjoinReceiver;
+
+ @observable
+ String? payjoinEndpoint = null;
+
@override
String getAddress(
{required int index,
@@ -45,4 +56,22 @@ abstract class BitcoinWalletAddressesBase extends ElectrumWalletAddresses with S
return generateP2WPKHAddress(hd: hd, index: index, network: network);
}
+
+ @action
+ Future initPayjoin() async {
+ await payjoinManager.initPayjoin();
+ currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress);
+ payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
+
+ payjoinManager.resumeSessions();
+ }
+
+ @action
+ Future newPayjoinReceiver() async {
+ currentPayjoinReceiver = await payjoinManager.initReceiver(primaryAddress);
+ payjoinEndpoint = (await currentPayjoinReceiver?.pjUri())?.pjEndpoint();
+
+ printV("Initializing new Payjoin Receiver");
+ payjoinManager.spawnNewReceiver(receiver: currentPayjoinReceiver!);
+ }
}
diff --git a/cw_bitcoin/lib/bitcoin_wallet_service.dart b/cw_bitcoin/lib/bitcoin_wallet_service.dart
index 7ee1534bf..317b25bcd 100644
--- a/cw_bitcoin/lib/bitcoin_wallet_service.dart
+++ b/cw_bitcoin/lib/bitcoin_wallet_service.dart
@@ -5,6 +5,7 @@ import 'package:cw_bitcoin/bitcoin_mnemonics_bip39.dart';
import 'package:cw_bitcoin/mnemonic_is_incorrect_exception.dart';
import 'package:cw_bitcoin/bitcoin_wallet_creation_credentials.dart';
import 'package:cw_core/encryption_file_utils.dart';
+import 'package:cw_core/payjoin_session.dart';
import 'package:cw_core/unspent_coins_info.dart';
import 'package:cw_core/wallet_base.dart';
import 'package:cw_core/wallet_service.dart';
@@ -21,10 +22,12 @@ class BitcoinWalletService extends WalletService<
BitcoinRestoreWalletFromSeedCredentials,
BitcoinRestoreWalletFromWIFCredentials,
BitcoinRestoreWalletFromHardware> {
- BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource, this.alwaysScan, this.isDirect);
+ BitcoinWalletService(this.walletInfoSource, this.unspentCoinsInfoSource,
+ this.payjoinSessionSource, this.alwaysScan, this.isDirect);
final Box walletInfoSource;
final Box unspentCoinsInfoSource;
+ final Box payjoinSessionSource;
final bool alwaysScan;
final bool isDirect;
@@ -55,6 +58,7 @@ class BitcoinWalletService extends WalletService<
passphrase: credentials.passphrase,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource,
+ payjoinBox: payjoinSessionSource,
network: network,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@@ -79,6 +83,7 @@ class BitcoinWalletService extends WalletService<
name: name,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
+ payjoinBox: payjoinSessionSource,
alwaysScan: alwaysScan,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@@ -92,6 +97,7 @@ class BitcoinWalletService extends WalletService<
name: name,
walletInfo: walletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
+ payjoinBox: payjoinSessionSource,
alwaysScan: alwaysScan,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@@ -126,6 +132,7 @@ class BitcoinWalletService extends WalletService<
name: currentName,
walletInfo: currentWalletInfo,
unspentCoinsInfo: unspentCoinsInfoSource,
+ payjoinBox: payjoinSessionSource,
alwaysScan: alwaysScan,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
@@ -147,7 +154,6 @@ class BitcoinWalletService extends WalletService<
credentials.walletInfo?.network = network.value;
credentials.walletInfo?.derivationInfo?.derivationPath =
credentials.hwAccountData.derivationPath;
-
final wallet = await BitcoinWallet(
password: credentials.password!,
xpub: credentials.hwAccountData.xpub,
@@ -155,6 +161,7 @@ class BitcoinWalletService extends WalletService<
unspentCoinsInfo: unspentCoinsInfoSource,
networkParam: network,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
+ payjoinBox: payjoinSessionSource,
);
await wallet.save();
await wallet.init();
@@ -182,6 +189,7 @@ class BitcoinWalletService extends WalletService<
mnemonic: credentials.mnemonic,
walletInfo: credentials.walletInfo!,
unspentCoinsInfo: unspentCoinsInfoSource,
+ payjoinBox: payjoinSessionSource,
network: network,
encryptionFileUtils: encryptionFileUtilsFor(isDirect),
);
diff --git a/cw_bitcoin/lib/electrum_wallet.dart b/cw_bitcoin/lib/electrum_wallet.dart
index 14fd1d3a9..35c15682c 100644
--- a/cw_bitcoin/lib/electrum_wallet.dart
+++ b/cw_bitcoin/lib/electrum_wallet.dart
@@ -1188,6 +1188,7 @@ abstract class ElectrumWalletBase
isSendAll: estimatedTx.isSendAll,
hasTaprootInputs: hasTaprootInputs,
utxos: estimatedTx.utxos,
+ publicKeys: estimatedTx.publicKeys
)..addListener((transaction) async {
transactionHistory.addOne(transaction);
if (estimatedTx.spendsSilentPayment) {
@@ -1965,6 +1966,11 @@ abstract class ElectrumWalletBase
}
}
+ bool isMine(Script script) {
+ final derivedAddress = addressFromOutputScript(script, network);
+ return addressesSet.contains(derivedAddress);
+ }
+
@override
Future