From 72362d1b618ac36e8c79a8ddab8c67c23237cb06 Mon Sep 17 00:00:00 2001 From: julian-CStack Date: Tue, 21 Mar 2023 17:15:42 -0600 Subject: [PATCH 1/6] initial purge --- assets/images/wownero_logo.png | Bin 50010 -> 0 bytes assets/images/wownero_menu.png | Bin 50010 -> 0 bytes assets/wownero_node_list.yml | 24 - cw_wownero/.gitignore | 11 - cw_wownero/.metadata | 10 - cw_wownero/CHANGELOG.md | 3 - cw_wownero/android/.classpath | 6 - cw_wownero/android/.gitignore | 8 - cw_wownero/android/.project | 23 - .../org.eclipse.buildship.core.prefs | 13 - cw_wownero/android/CMakeLists.txt | 244 -- cw_wownero/android/build.gradle | 49 - cw_wownero/android/gradle.properties | 4 - .../gradle/wrapper/gradle-wrapper.properties | 5 - cw_wownero/android/jni/wownero_jni.cpp | 74 - cw_wownero/android/settings.gradle | 1 - .../android/src/main/AndroidManifest.xml | 4 - .../cakewallet/cw_wownero/CwWowneroPlugin.kt | 93 - cw_wownero/ios/.gitignore | 37 - cw_wownero/ios/Assets/.gitkeep | 0 cw_wownero/ios/Classes/CwWalletListener.h | 23 - cw_wownero/ios/Classes/CwWowneroPlugin.h | 4 - cw_wownero/ios/Classes/CwWowneroPlugin.m | 8 - .../ios/Classes/SwiftCwWowneroPlugin.swift | 14 - cw_wownero/ios/Classes/wownero_api.cpp | 907 -------- cw_wownero/ios/Classes/wownero_api.h | 42 - cw_wownero/ios/cw_wownero.podspec | 50 - cw_wownero/lib/api/account_list.dart | 85 - .../lib/api/convert_utf8_to_string.dart | 10 - .../connection_to_node_exception.dart | 5 - .../creation_transaction_exception.dart | 8 - .../exceptions/setup_wallet_exception.dart | 5 - .../exceptions/wallet_creation_exception.dart | 8 - .../exceptions/wallet_opening_exception.dart | 8 - .../wallet_restore_from_keys_exception.dart | 5 - .../wallet_restore_from_seed_exception.dart | 5 - cw_wownero/lib/api/signatures.dart | 152 -- cw_wownero/lib/api/structs/account_row.dart | 12 - .../lib/api/structs/pending_transaction.dart | 29 - .../lib/api/structs/subaddress_row.dart | 14 - .../lib/api/structs/transaction_info_row.dart | 42 - cw_wownero/lib/api/structs/ut8_box.dart | 9 - cw_wownero/lib/api/subaddress_list.dart | 99 - cw_wownero/lib/api/transaction_history.dart | 242 -- cw_wownero/lib/api/types.dart | 151 -- cw_wownero/lib/api/wallet.dart | 422 ---- cw_wownero/lib/api/wallet_manager.dart | 291 --- cw_wownero/lib/api/wownero_api.dart | 12 - cw_wownero/lib/api/wownero_output.dart | 8 - cw_wownero/lib/mnemonics/english.dart | 1630 ------------- cw_wownero/lib/mnemonics/english14.dart | 2052 ----------------- cw_wownero/lib/mnemonics/english25.dart | 1630 ------------- .../lib/pending_wownero_transaction.dart | 50 - cw_wownero/lib/wownero_account_list.dart | 78 - cw_wownero/lib/wownero_account_list.g.dart | 34 - cw_wownero/lib/wownero_amount_format.dart | 18 - cw_wownero/lib/wownero_balance.dart | 30 - cw_wownero/lib/wownero_subaddress_list.dart | 90 - cw_wownero/lib/wownero_subaddress_list.g.dart | 34 - ...nero_transaction_creation_credentials.dart | 9 - ...ownero_transaction_creation_exception.dart | 8 - .../lib/wownero_transaction_history.dart | 27 - .../lib/wownero_transaction_history.g.dart | 18 - cw_wownero/lib/wownero_transaction_info.dart | 90 - cw_wownero/lib/wownero_wallet.dart | 451 ---- cw_wownero/lib/wownero_wallet.g.dart | 51 - cw_wownero/lib/wownero_wallet_addresses.dart | 85 - .../lib/wownero_wallet_addresses.g.dart | 68 - cw_wownero/lib/wownero_wallet_service.dart | 248 -- cw_wownero/pubspec.lock | 609 ----- cw_wownero/pubspec.yaml | 79 - example/ios/Podfile.lock | 23 - example/lib/main.dart | 687 +++--- example/pubspec.lock | 228 +- lib/view_model/send/output.dart | 10 - lib/wownero/cw_wownero.dart | 309 --- lib/wownero/wownero.dart | 150 -- pubspec.lock | 231 +- pubspec.yaml | 3 - scripts/android/build_all.sh | 2 - scripts/android/build_wownero.sh | 74 - scripts/android/build_wownero_all.sh | 9 - scripts/android/build_wownero_seed.sh | 66 - scripts/android/copy_monero_deps.sh | 4 - scripts/ios/build_all.sh | 1 - scripts/ios/build_wownero.sh | 71 - scripts/ios/build_wownero_all.sh | 11 - scripts/ios/build_wownero_seed.sh | 46 - scripts/ios/setup.sh | 17 - scripts/linux/build_sharedfile.sh | 7 - scripts/linux/build_wownero.sh | 58 - scripts/linux/build_wownero_seed.sh | 45 - scripts/linux/copy_monero_deps.sh | 4 - 93 files changed, 629 insertions(+), 12095 deletions(-) delete mode 100644 assets/images/wownero_logo.png delete mode 100644 assets/images/wownero_menu.png delete mode 100644 assets/wownero_node_list.yml delete mode 100644 cw_wownero/.gitignore delete mode 100644 cw_wownero/.metadata delete mode 100644 cw_wownero/CHANGELOG.md delete mode 100644 cw_wownero/android/.classpath delete mode 100644 cw_wownero/android/.gitignore delete mode 100644 cw_wownero/android/.project delete mode 100644 cw_wownero/android/.settings/org.eclipse.buildship.core.prefs delete mode 100644 cw_wownero/android/CMakeLists.txt delete mode 100644 cw_wownero/android/build.gradle delete mode 100644 cw_wownero/android/gradle.properties delete mode 100644 cw_wownero/android/gradle/wrapper/gradle-wrapper.properties delete mode 100644 cw_wownero/android/jni/wownero_jni.cpp delete mode 100644 cw_wownero/android/settings.gradle delete mode 100644 cw_wownero/android/src/main/AndroidManifest.xml delete mode 100644 cw_wownero/android/src/main/kotlin/com/cakewallet/cw_wownero/CwWowneroPlugin.kt delete mode 100644 cw_wownero/ios/.gitignore delete mode 100644 cw_wownero/ios/Assets/.gitkeep delete mode 100644 cw_wownero/ios/Classes/CwWalletListener.h delete mode 100644 cw_wownero/ios/Classes/CwWowneroPlugin.h delete mode 100644 cw_wownero/ios/Classes/CwWowneroPlugin.m delete mode 100644 cw_wownero/ios/Classes/SwiftCwWowneroPlugin.swift delete mode 100644 cw_wownero/ios/Classes/wownero_api.cpp delete mode 100644 cw_wownero/ios/Classes/wownero_api.h delete mode 100644 cw_wownero/ios/cw_wownero.podspec delete mode 100644 cw_wownero/lib/api/account_list.dart delete mode 100644 cw_wownero/lib/api/convert_utf8_to_string.dart delete mode 100644 cw_wownero/lib/api/exceptions/connection_to_node_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/creation_transaction_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/setup_wallet_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/wallet_creation_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/wallet_opening_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart delete mode 100644 cw_wownero/lib/api/exceptions/wallet_restore_from_seed_exception.dart delete mode 100644 cw_wownero/lib/api/signatures.dart delete mode 100644 cw_wownero/lib/api/structs/account_row.dart delete mode 100644 cw_wownero/lib/api/structs/pending_transaction.dart delete mode 100644 cw_wownero/lib/api/structs/subaddress_row.dart delete mode 100644 cw_wownero/lib/api/structs/transaction_info_row.dart delete mode 100644 cw_wownero/lib/api/structs/ut8_box.dart delete mode 100644 cw_wownero/lib/api/subaddress_list.dart delete mode 100644 cw_wownero/lib/api/transaction_history.dart delete mode 100644 cw_wownero/lib/api/types.dart delete mode 100644 cw_wownero/lib/api/wallet.dart delete mode 100644 cw_wownero/lib/api/wallet_manager.dart delete mode 100644 cw_wownero/lib/api/wownero_api.dart delete mode 100644 cw_wownero/lib/api/wownero_output.dart delete mode 100644 cw_wownero/lib/mnemonics/english.dart delete mode 100644 cw_wownero/lib/mnemonics/english14.dart delete mode 100644 cw_wownero/lib/mnemonics/english25.dart delete mode 100644 cw_wownero/lib/pending_wownero_transaction.dart delete mode 100644 cw_wownero/lib/wownero_account_list.dart delete mode 100644 cw_wownero/lib/wownero_account_list.g.dart delete mode 100644 cw_wownero/lib/wownero_amount_format.dart delete mode 100644 cw_wownero/lib/wownero_balance.dart delete mode 100644 cw_wownero/lib/wownero_subaddress_list.dart delete mode 100644 cw_wownero/lib/wownero_subaddress_list.g.dart delete mode 100644 cw_wownero/lib/wownero_transaction_creation_credentials.dart delete mode 100644 cw_wownero/lib/wownero_transaction_creation_exception.dart delete mode 100644 cw_wownero/lib/wownero_transaction_history.dart delete mode 100644 cw_wownero/lib/wownero_transaction_history.g.dart delete mode 100644 cw_wownero/lib/wownero_transaction_info.dart delete mode 100644 cw_wownero/lib/wownero_wallet.dart delete mode 100644 cw_wownero/lib/wownero_wallet.g.dart delete mode 100644 cw_wownero/lib/wownero_wallet_addresses.dart delete mode 100644 cw_wownero/lib/wownero_wallet_addresses.g.dart delete mode 100644 cw_wownero/lib/wownero_wallet_service.dart delete mode 100644 cw_wownero/pubspec.lock delete mode 100644 cw_wownero/pubspec.yaml delete mode 100644 lib/wownero/cw_wownero.dart delete mode 100644 lib/wownero/wownero.dart delete mode 100755 scripts/android/build_wownero.sh delete mode 100755 scripts/android/build_wownero_all.sh delete mode 100755 scripts/android/build_wownero_seed.sh delete mode 100755 scripts/ios/build_wownero.sh delete mode 100755 scripts/ios/build_wownero_all.sh delete mode 100755 scripts/ios/build_wownero_seed.sh delete mode 100755 scripts/linux/build_wownero.sh delete mode 100755 scripts/linux/build_wownero_seed.sh diff --git a/assets/images/wownero_logo.png b/assets/images/wownero_logo.png deleted file mode 100644 index a3da77b9e08a57f71bf63ca5863667232c96c0c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50010 zcmV)eK&HQmP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw00006 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 z

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 z

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 qz*5`5z{ - - - - - diff --git a/cw_wownero/android/.gitignore b/cw_wownero/android/.gitignore deleted file mode 100644 index c6cbe562a4..0000000000 --- a/cw_wownero/android/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -*.iml -.gradle -/local.properties -/.idea/workspace.xml -/.idea/libraries -.DS_Store -/build -/captures diff --git a/cw_wownero/android/.project b/cw_wownero/android/.project deleted file mode 100644 index e1b61ff1b9..0000000000 --- a/cw_wownero/android/.project +++ /dev/null @@ -1,23 +0,0 @@ - - - cw_wownero - Project android created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - diff --git a/cw_wownero/android/.settings/org.eclipse.buildship.core.prefs b/cw_wownero/android/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index a88c4d4840..0000000000 --- a/cw_wownero/android/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(VERSION(6.0-20191016123526+0000)) -connection.project.dir=../../android -eclipse.preferences.version=1 -gradle.user.home= -java.home= -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/cw_wownero/android/CMakeLists.txt b/cw_wownero/android/CMakeLists.txt deleted file mode 100644 index fb5a8b74b7..0000000000 --- a/cw_wownero/android/CMakeLists.txt +++ /dev/null @@ -1,244 +0,0 @@ -cmake_minimum_required(VERSION 3.4.1) - -add_library( cw_wownero - SHARED - ./jni/wownero_jni.cpp - ../ios/Classes/wownero_api.cpp) - - find_library( log-lib log ) - -set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../../cw_shared_external/ios/External/android) - -############ -# libsodium -############ - -add_library(sodium STATIC IMPORTED) -set_target_properties(sodium PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libsodium.a) - -############ -# OpenSSL -############ - -add_library(crypto STATIC IMPORTED) -set_target_properties(crypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libcrypto.a) - -add_library(ssl STATIC IMPORTED) -set_target_properties(ssl PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libssl.a) - -############ -# wownero-seed -############ - -add_library(wownero-seed STATIC IMPORTED) -set_target_properties(wownero-seed PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libwownero-seed.a) - -############ -# Boost -############ - -add_library(boost_chrono STATIC IMPORTED) -set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_chrono.a) - -add_library(boost_date_time STATIC IMPORTED) -set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_date_time.a) - -add_library(boost_filesystem STATIC IMPORTED) -set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_filesystem.a) - -add_library(boost_program_options STATIC IMPORTED) -set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_program_options.a) - -add_library(boost_regex STATIC IMPORTED) -set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_regex.a) - -add_library(boost_serialization STATIC IMPORTED) -set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_serialization.a) - -add_library(boost_system STATIC IMPORTED) -set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_system.a) - -add_library(boost_thread STATIC IMPORTED) -set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_thread.a) - -add_library(boost_wserialization STATIC IMPORTED) -set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/libboost_wserialization.a) - -############# -# Wownero -############# - -add_library(wallet_api STATIC IMPORTED) -set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet_api.a) - -add_library(wallet STATIC IMPORTED) -set_target_properties(wallet PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet.a) - -add_library(cryptonote_core STATIC IMPORTED) -set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_core.a) - -add_library(cryptonote_basic STATIC IMPORTED) -set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_basic.a) - -add_library(cryptonote_format_utils_basic STATIC IMPORTED) -set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcryptonote_format_utils_basic.a) - -add_library(mnemonics STATIC IMPORTED) -set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libmnemonics.a) - -add_library(common STATIC IMPORTED) -set_target_properties(common PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcommon.a) - -add_library(cncrypto STATIC IMPORTED) -set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcncrypto.a) - -add_library(ringct STATIC IMPORTED) -set_target_properties(ringct PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libringct.a) - -add_library(ringct_basic STATIC IMPORTED) -set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libringct_basic.a) - -add_library(blockchain_db STATIC IMPORTED) -set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libblockchain_db.a) - -add_library(lmdb STATIC IMPORTED) -set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/liblmdb.a) - -add_library(easylogging STATIC IMPORTED) -set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libeasylogging.a) - -add_library(unbound STATIC IMPORTED) -set_target_properties(unbound PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libunbound.a) - -add_library(epee STATIC IMPORTED) -set_target_properties(epee PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libepee.a) - -add_library(blocks STATIC IMPORTED) -set_target_properties(blocks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libblocks.a) - -add_library(checkpoints STATIC IMPORTED) -set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libcheckpoints.a) - -add_library(device STATIC IMPORTED) -set_target_properties(device PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libdevice.a) - -add_library(device_trezor STATIC IMPORTED) -set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libdevice_trezor.a) - -add_library(multisig STATIC IMPORTED) -set_target_properties(multisig PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libmultisig.a) - -add_library(version STATIC IMPORTED) -set_target_properties(version PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libversion.a) - -add_library(net STATIC IMPORTED) -set_target_properties(net PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libnet.a) - -add_library(hardforks STATIC IMPORTED) -set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libhardforks.a) - -add_library(randomx STATIC IMPORTED) -set_target_properties(randomx PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/librandomx.a) - -add_library(rpc_base STATIC IMPORTED) -set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/librpc_base.a) - -add_library(wallet-crypto STATIC IMPORTED) -set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/lib/wownero/libwallet-crypto.a) - -set(WALLET_CRYPTO "") - -if(${ANDROID_ABI} STREQUAL "x86_64") - set(WALLET_CRYPTO "wallet-crypto") -endif() - -include_directories( ${EXTERNAL_LIBS_DIR}/${ANDROID_ABI}/include ) - -target_link_libraries( cw_wownero - - wallet_api - wallet - cryptonote_core - cryptonote_basic - cryptonote_format_utils_basic - mnemonics - ringct - ringct_basic - net - common - cncrypto - blockchain_db - lmdb - easylogging - unbound - epee - blocks - checkpoints - device - device_trezor - multisig - version - randomx - hardforks - rpc_base - ${WALLET_CRYPTO} - - boost_chrono - boost_date_time - boost_filesystem - boost_program_options - boost_regex - boost_serialization - boost_system - boost_thread - boost_wserialization - - ssl - crypto - - sodium - - -Wl,--whole-archive - wownero-seed - -Wl,--no-whole-archive - - ${log-lib} ) \ No newline at end of file diff --git a/cw_wownero/android/build.gradle b/cw_wownero/android/build.gradle deleted file mode 100644 index afb23e7975..0000000000 --- a/cw_wownero/android/build.gradle +++ /dev/null @@ -1,49 +0,0 @@ -group 'com.cakewallet.wownero' -version '1.0-SNAPSHOT' - -buildscript { - ext.kotlin_version = '1.6.10' - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.4' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -rootProject.allprojects { - repositories { - google() - jcenter() - } -} - -apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' - -android { - compileSdkVersion 31 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - defaultConfig { - minSdkVersion 21 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - } - lintOptions { - disable 'InvalidPackage' - } - externalNativeBuild { - cmake { - path "CMakeLists.txt" - } - } -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/cw_wownero/android/gradle.properties b/cw_wownero/android/gradle.properties deleted file mode 100644 index 38c8d4544f..0000000000 --- a/cw_wownero/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.enableR8=true -android.useAndroidX=true -android.enableJetifier=true diff --git a/cw_wownero/android/gradle/wrapper/gradle-wrapper.properties b/cw_wownero/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 3c46198fce..0000000000 --- a/cw_wownero/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,5 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip diff --git a/cw_wownero/android/jni/wownero_jni.cpp b/cw_wownero/android/jni/wownero_jni.cpp deleted file mode 100644 index 4e2deb6a8f..0000000000 --- a/cw_wownero/android/jni/wownero_jni.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include -#include "../../ios/Classes/wownero_api.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -JNIEXPORT void JNICALL -Java_com_cakewallet_wownero_WowneroApi_setNodeAddressJNI( - JNIEnv *env, - jobject inst, - jstring uri, - jstring login, - jstring password, - jboolean use_ssl, - jboolean is_light_wallet) { - const char *_uri = env->GetStringUTFChars(uri, 0); - const char *_login = ""; - const char *_password = ""; - char *error; - - if (login != NULL) { - _login = env->GetStringUTFChars(login, 0); - } - - if (password != NULL) { - _password = env->GetStringUTFChars(password, 0); - } - char *__uri = (char*) _uri; - char *__login = (char*) _login; - char *__password = (char*) _password; - bool inited = setup_node(__uri, __login, __password, false, false, error); - - if (!inited) { - env->ThrowNew(env->FindClass("java/lang/Exception"), error); - } -} - -JNIEXPORT void JNICALL -Java_com_cakewallet_wownero_WowneroApi_connectToNodeJNI( - JNIEnv *env, - jobject inst) { - char *error; - bool is_connected = connect_to_node(error); - - if (!is_connected) { - env->ThrowNew(env->FindClass("java/lang/Exception"), error); - } -} - -JNIEXPORT void JNICALL -Java_com_cakewallet_wownero_WowneroApi_startSyncJNI( - JNIEnv *env, - jobject inst) { - start_refresh(); -} - -JNIEXPORT void JNICALL -Java_com_cakewallet_wownero_WowneroApi_loadWalletJNI( - JNIEnv *env, - jobject inst, - jstring path, - jstring password) { - char *_path = (char *) env->GetStringUTFChars(path, 0); - char *_password = (char *) env->GetStringUTFChars(password, 0); - - load_wallet(_path, _password, 0); -} - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/cw_wownero/android/settings.gradle b/cw_wownero/android/settings.gradle deleted file mode 100644 index f6786df21d..0000000000 --- a/cw_wownero/android/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'cw_wownero' diff --git a/cw_wownero/android/src/main/AndroidManifest.xml b/cw_wownero/android/src/main/AndroidManifest.xml deleted file mode 100644 index a1e6eef79b..0000000000 --- a/cw_wownero/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - diff --git a/cw_wownero/android/src/main/kotlin/com/cakewallet/cw_wownero/CwWowneroPlugin.kt b/cw_wownero/android/src/main/kotlin/com/cakewallet/cw_wownero/CwWowneroPlugin.kt deleted file mode 100644 index 41ac9a9181..0000000000 --- a/cw_wownero/android/src/main/kotlin/com/cakewallet/cw_wownero/CwWowneroPlugin.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.cakewallet.cw_wownero - -import androidx.annotation.NonNull -import android.app.Activity -import android.os.AsyncTask -import android.os.Looper -import android.os.Handler -import android.os.Process - -import io.flutter.embedding.engine.plugins.FlutterPlugin -import io.flutter.plugin.common.MethodCall -import io.flutter.plugin.common.MethodChannel -import io.flutter.plugin.common.MethodChannel.MethodCallHandler -import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry.Registrar - -class doAsync(val handler: () -> Unit) : AsyncTask() { - override fun doInBackground(vararg params: Void?): Void? { - Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO); - handler() - return null - } -} - -class CwWowneroPlugin: FlutterPlugin, MethodCallHandler { - companion object { - // val wowneroApi = WowneroApi() - val main = Handler(Looper.getMainLooper()); - - init { - System.loadLibrary("cw_wownero") - } - - @JvmStatic - fun registerWith(registrar: Registrar) { - val channel = MethodChannel(registrar.messenger(), "cw_wownero") - channel.setMethodCallHandler(CwWowneroPlugin()) - } - } - /// The MethodChannel that will the communication between Flutter and native Android - /// - /// 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 - - override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) { - channel = MethodChannel(flutterPluginBinding.binaryMessenger, "cw_wownero") - channel.setMethodCallHandler(this) - } - - override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) { - if (call.method == "getPlatformVersion") { - result.success("Android ${android.os.Build.VERSION.RELEASE}") - } else if (call.method == "setupNode") { - val uri = call.argument("address") ?: "" - val login = call.argument("login") ?: "" - val password = call.argument("password") ?: "" - val useSSL = false - val isLightWallet = false -// doAsync { -// try { -// wowneroApi.setNodeAddressJNI(uri, login, password, useSSL, isLightWallet) -// main.post({ -// result.success(true) -// }); -// } catch(e: Throwable) { -// main.post({ -// result.error("CONNECTION_ERROR", e.message, null) -// }); -// } -// }.execute() - } else if (call.method == "startSync") { -// doAsync { -// wowneroApi.startSyncJNI() -// main.post({ -// result.success(true) -// }); -// }.execute() - } else if (call.method == "loadWallet") { - val path = call.argument("path") ?: "" - val password = call.argument("password") ?: "" -// wowneroApi.loadWalletJNI(path, password) - result.success(true) - } else { - - result.notImplemented() - } - } - - override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { - channel.setMethodCallHandler(null) - } -} diff --git a/cw_wownero/ios/.gitignore b/cw_wownero/ios/.gitignore deleted file mode 100644 index aa479fd3ce..0000000000 --- a/cw_wownero/ios/.gitignore +++ /dev/null @@ -1,37 +0,0 @@ -.idea/ -.vagrant/ -.sconsign.dblite -.svn/ - -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser -*.mode1v3 -*.mode2v3 -*.perspectivev3 - -!default.pbxuser -!default.mode1v3 -!default.mode2v3 -!default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig -/Flutter/flutter_export_environment.sh \ No newline at end of file diff --git a/cw_wownero/ios/Assets/.gitkeep b/cw_wownero/ios/Assets/.gitkeep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/cw_wownero/ios/Classes/CwWalletListener.h b/cw_wownero/ios/Classes/CwWalletListener.h deleted file mode 100644 index fecc2320b3..0000000000 --- a/cw_wownero/ios/Classes/CwWalletListener.h +++ /dev/null @@ -1,23 +0,0 @@ -#include - -struct CWWowneroWalletListener; - -typedef int8_t (*on_new_block_callback)(uint64_t height); -typedef int8_t (*on_need_to_refresh_callback)(); - -typedef struct CWWowneroWalletListener -{ - // on_money_spent_callback *on_money_spent; - // on_money_received_callback *on_money_received; - // on_unconfirmed_money_received_callback *on_unconfirmed_money_received; - // on_new_block_callback *on_new_block; - // on_updated_callback *on_updated; - // on_refreshed_callback *on_refreshed; - - on_new_block_callback on_new_block; -} CWWowneroWalletListener; - -struct TestListener { - // int8_t x; - on_new_block_callback on_new_block; -}; \ No newline at end of file diff --git a/cw_wownero/ios/Classes/CwWowneroPlugin.h b/cw_wownero/ios/Classes/CwWowneroPlugin.h deleted file mode 100644 index 4b3002c888..0000000000 --- a/cw_wownero/ios/Classes/CwWowneroPlugin.h +++ /dev/null @@ -1,4 +0,0 @@ -#import - -@interface CwWowneroPlugin : NSObject -@end diff --git a/cw_wownero/ios/Classes/CwWowneroPlugin.m b/cw_wownero/ios/Classes/CwWowneroPlugin.m deleted file mode 100644 index 67d39529f2..0000000000 --- a/cw_wownero/ios/Classes/CwWowneroPlugin.m +++ /dev/null @@ -1,8 +0,0 @@ -#import "CwWowneroPlugin.h" -#import - -@implementation CwWowneroPlugin -+ (void)registerWithRegistrar:(NSObject*)registrar { - [SwiftCwWowneroPlugin registerWithRegistrar:registrar]; -} -@end diff --git a/cw_wownero/ios/Classes/SwiftCwWowneroPlugin.swift b/cw_wownero/ios/Classes/SwiftCwWowneroPlugin.swift deleted file mode 100644 index 975181dcb4..0000000000 --- a/cw_wownero/ios/Classes/SwiftCwWowneroPlugin.swift +++ /dev/null @@ -1,14 +0,0 @@ -import Flutter -import UIKit - -public class SwiftCwWowneroPlugin: NSObject, FlutterPlugin { - public static func register(with registrar: FlutterPluginRegistrar) { - let channel = FlutterMethodChannel(name: "cw_wownero", binaryMessenger: registrar.messenger()) - let instance = SwiftCwWowneroPlugin() - registrar.addMethodCallDelegate(instance, channel: channel) - } - - public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { - result("iOS " + UIDevice.current.systemVersion) - } -} diff --git a/cw_wownero/ios/Classes/wownero_api.cpp b/cw_wownero/ios/Classes/wownero_api.cpp deleted file mode 100644 index d66316cd3b..0000000000 --- a/cw_wownero/ios/Classes/wownero_api.cpp +++ /dev/null @@ -1,907 +0,0 @@ -#include -#include "cstdlib" -#include -#include -#include -#include -#include -#include "thread" -#include "CwWalletListener.h" - -#include - -#if __APPLE__ -// Fix for randomx on ios -void __clear_cache(void* start, void* end) { } -#include "../../../cw_shared_external/ios/External/ios/include/wownero/wallet2_api.h" -#include "../../../cw_shared_external/ios/External/ios/include/wownero_seed/wownero_seed.hpp" -#else -#include -#include "../External/android/include/wallet2_api.h" -#endif - -#ifdef linux -#include -#endif - -// void nice(int niceness); // Prototype definition - -using namespace std::chrono_literals; -#ifdef __cplusplus -extern "C" -{ -#endif - const uint64_t MONERO_BLOCK_SIZE = 1000; - - struct Utf8Box - { - char *value; - - Utf8Box(char *_value) - { - value = _value; - } - }; - - struct SubaddressRow - { - uint64_t id; - char *address; - char *label; - - SubaddressRow(std::size_t _id, char *_address, char *_label) - { - id = static_cast(_id); - address = _address; - label = _label; - } - }; - - struct AccountRow - { - uint64_t id; - char *label; - - AccountRow(std::size_t _id, char *_label) - { - id = static_cast(_id); - label = _label; - } - }; - - struct MoneroWalletListener : Monero::WalletListener - { - uint64_t m_height; - bool m_need_to_refresh; - bool m_new_transaction; - - MoneroWalletListener() - { - m_height = 0; - m_need_to_refresh = false; - m_new_transaction = false; - } - - void moneySpent(const std::string &txId, uint64_t amount) - { - m_new_transaction = true; - } - - void moneyReceived(const std::string &txId, uint64_t amount) - { - m_new_transaction = true; - } - - void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) - { - m_new_transaction = true; - } - - void newBlock(uint64_t height) - { - m_height = height; - } - - void updated() - { - m_new_transaction = true; - } - - void refreshed(bool success) - { - m_need_to_refresh = true; - } - - void resetNeedToRefresh() - { - m_need_to_refresh = false; - } - - bool isNeedToRefresh() - { - return m_need_to_refresh; - } - - bool isNewTransactionExist() - { - return m_new_transaction; - } - - void resetIsNewTransactionExist() - { - m_new_transaction = false; - } - - uint64_t height() - { - return m_height; - } - }; - - struct TransactionInfoRow - { - uint64_t amount; - uint64_t fee; - uint64_t blockHeight; - uint64_t confirmations; - uint32_t subaddrAccount; - int8_t direction; - int8_t isPending; - uint32_t subaddrIndex; - - char *hash; - char *paymentId; - - int64_t datetime; - - TransactionInfoRow(Monero::TransactionInfo *transaction) - { - amount = transaction->amount(); - fee = transaction->fee(); - blockHeight = transaction->blockHeight(); - subaddrAccount = transaction->subaddrAccount(); - std::set::iterator it = transaction->subaddrIndex().begin(); - subaddrIndex = *it; - confirmations = transaction->confirmations(); - datetime = static_cast(transaction->timestamp()); - direction = transaction->direction(); - isPending = static_cast(transaction->isPending()); - std::string *hash_str = new std::string(transaction->hash()); - hash = strdup(hash_str->c_str()); - paymentId = strdup(transaction->paymentId().c_str()); - } - }; - - struct PendingTransactionRaw - { - uint64_t amount; - uint64_t fee; - char *hash; - Monero::PendingTransaction *transaction; - - PendingTransactionRaw(Monero::PendingTransaction *_transaction) - { - transaction = _transaction; - amount = _transaction->amount(); - fee = _transaction->fee(); - hash = strdup(_transaction->txid()[0].c_str()); - } - }; - - Monero::Wallet *m_wallet; - Monero::TransactionHistory *m_transaction_history; - MoneroWalletListener *m_listener; - Monero::Subaddress *m_subaddress; - Monero::SubaddressAccount *m_account; - uint64_t m_last_known_wallet_height; - uint64_t m_cached_syncing_blockchain_height = 0; - std::mutex store_lock; - bool is_storing = false; - - void change_current_wallet(Monero::Wallet *wallet) - { - m_wallet = wallet; - m_listener = nullptr; - - - if (wallet != nullptr) - { - m_transaction_history = wallet->history(); - } - else - { - m_transaction_history = nullptr; - } - - if (wallet != nullptr) - { - m_account = wallet->subaddressAccount(); - } - else - { - m_account = nullptr; - } - - if (wallet != nullptr) - { - m_subaddress = wallet->subaddress(); - } - else - { - m_subaddress = nullptr; - } - } - - Monero::Wallet *get_current_wallet() - { - return m_wallet; - } - - bool create_14_word_wallet(char *path, char *password, char *language, int32_t networkType, char *error) - { - Monero::NetworkType _networkType = static_cast(networkType); - Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager(); - - // 14 word seeds /* - time_t time = std::time(nullptr); - wownero_seed wow_seed(time, "wownero"); - - std::stringstream seed_stream; - seed_stream << wow_seed; - std::string seed = seed_stream.str(); - - std::stringstream key_stream; - key_stream << wow_seed.key(); - std::string spendKey = key_stream.str(); - - uint64_t restoreHeight = wow_seed.blockheight(); - - Monero::Wallet *wallet = walletManager->createDeterministicWalletFromSpendKey( - std::string(path), - std::string(password), - std::string(language), - static_cast(_networkType), - (uint64_t)restoreHeight, - spendKey, - 1); - wallet->setCacheAttribute("cake.seed", seed); - // */ - - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - - if (wallet->status() != Monero::Wallet::Status_Ok) - { - error = strdup(wallet->errorString().c_str()); - return false; - } - - change_current_wallet(wallet); - return true; - } - - bool create_25_word_wallet(char *path, char *password, char *language, int32_t networkType, char *error) - { - Monero::NetworkType _networkType = static_cast(networkType); - Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager(); - - // 25 word seeds /* - Monero::Wallet *wallet = walletManager->createWallet(path, password, language, _networkType); - // */ - - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - - if (wallet->status() != Monero::Wallet::Status_Ok) - { - error = strdup(wallet->errorString().c_str()); - return false; - } - - change_current_wallet(wallet); - return true; - } - - bool restore_wallet_from_14_word_seed(char *path, char *password, char *seed, int32_t networkType, char *error) - { - Monero::NetworkType _networkType = static_cast(networkType); - Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager(); - - // 14 word seeds /* - wownero_seed wow_seed(seed, "wownero"); - - std::stringstream seed_stream; - seed_stream << wow_seed; - std::string seed_str = seed_stream.str(); - - std::stringstream key_stream; - key_stream << wow_seed.key(); - std::string spendKey = key_stream.str(); - - uint64_t restoreHeight = wow_seed.blockheight(); - - Monero::Wallet *wallet = walletManager->createDeterministicWalletFromSpendKey( - std::string(path), - std::string(password), - "English", - static_cast(_networkType), - (uint64_t)restoreHeight, - spendKey, - 1); - wallet->setCacheAttribute("cake.seed", seed_str); - // */ - - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - - if (status != Monero::Wallet::Status_Ok || !errorString.empty()) - { - error = strdup(errorString.c_str()); - return false; - } - - change_current_wallet(wallet); - return true; - } - - bool restore_wallet_from_25_word_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error) - { - Monero::NetworkType _networkType = static_cast(networkType); - Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager(); - - // 25 word seeds /* - Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->recoveryWallet( - std::string(path), - std::string(password), - std::string(seed), - _networkType, - (uint64_t)restoreHeight); - // */ - - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - - if (status != Monero::Wallet::Status_Ok || !errorString.empty()) - { - error = strdup(errorString.c_str()); - return false; - } - - change_current_wallet(wallet); - return true; - } - - bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error) - { - // this function is not used, restoring from keys is disabled for Wownero - Monero::NetworkType _networkType = static_cast(networkType); - Monero::Wallet *wallet = Monero::WalletManagerFactory::getWalletManager()->createWalletFromKeys( - std::string(path), - std::string(password), - std::string(language), - _networkType, - (uint64_t)restoreHeight, - std::string(address), - std::string(viewKey), - std::string(spendKey)); - - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - - if (status != Monero::Wallet::Status_Ok || !errorString.empty()) - { - error = strdup(errorString.c_str()); - return false; - } - - change_current_wallet(wallet); - return true; - } - - bool load_wallet(char *path, char *password, int32_t nettype) - { - nice(19); - Monero::NetworkType networkType = static_cast(nettype); - Monero::WalletManager *walletManager = Monero::WalletManagerFactory::getWalletManager(); - Monero::Wallet *wallet = walletManager->openWallet(std::string(path), std::string(password), networkType); - int status; - std::string errorString; - - wallet->statusWithErrorString(status, errorString); - change_current_wallet(wallet); - - return !(status != Monero::Wallet::Status_Ok || !errorString.empty()); - } - - char *error_string() { - return strdup(get_current_wallet()->errorString().c_str()); - } - - - bool is_wallet_exist(char *path) - { - return Monero::WalletManagerFactory::getWalletManager()->walletExists(std::string(path)); - } - - void close_current_wallet() - { - Monero::WalletManagerFactory::getWalletManager()->closeWallet(get_current_wallet()); - change_current_wallet(nullptr); - } - - char *get_filename() - { - return strdup(get_current_wallet()->filename().c_str()); - } - - char *secret_view_key() - { - return strdup(get_current_wallet()->secretViewKey().c_str()); - } - - char *public_view_key() - { - return strdup(get_current_wallet()->publicViewKey().c_str()); - } - - char *secret_spend_key() - { - return strdup(get_current_wallet()->secretSpendKey().c_str()); - } - - char *public_spend_key() - { - return strdup(get_current_wallet()->publicSpendKey().c_str()); - } - - char *get_address(uint32_t account_index, uint32_t address_index) - { - return strdup(get_current_wallet()->address(account_index, address_index).c_str()); - } - - const char *seed() - { - return strdup(get_current_wallet()->getCacheAttribute("cake.seed").c_str()); - } - - uint64_t get_full_balance(uint32_t account_index) - { - return get_current_wallet()->balance(account_index); - } - - uint64_t get_unlocked_balance(uint32_t account_index) - { - return get_current_wallet()->unlockedBalance(account_index); - } - - uint64_t get_current_height() - { - return get_current_wallet()->blockChainHeight(); - } - - uint64_t get_node_height() - { - return get_current_wallet()->daemonBlockChainHeight(); - } - - uint64_t get_seed_height(char *seed) - { - wownero_seed wow_seed(seed, "wownero"); - return wow_seed.blockheight(); - } - - bool connect_to_node(char *error) - { - nice(19); - bool is_connected = get_current_wallet()->connectToDaemon(); - - if (!is_connected) - { - error = strdup(get_current_wallet()->errorString().c_str()); - } - - return is_connected; - } - - bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error) - { - nice(19); - Monero::Wallet *wallet = get_current_wallet(); - - std::string _login = ""; - std::string _password = ""; - - if (login != nullptr) - { - _login = std::string(login); - } - - if (password != nullptr) - { - _password = std::string(password); - } - - bool inited = wallet->init(std::string(address), 0, _login, _password, true, is_light_wallet); - - if (!inited) - { - error = strdup(wallet->errorString().c_str()); - } else if (!wallet->connectToDaemon()) { - error = strdup(wallet->errorString().c_str()); - } - - wallet->setTrustedDaemon(true); - return inited; - } - - bool is_connected() - { - try { - return get_current_wallet()->connected(); - } catch (...) { - return false; - } - } - - void start_refresh() - { - get_current_wallet()->refreshAsync(); - get_current_wallet()->startRefresh(); - } - - void set_refresh_from_block_height(uint64_t height) - { - get_current_wallet()->setRefreshFromBlockHeight(height); - } - - void set_recovering_from_seed(bool is_recovery) - { - get_current_wallet()->setRecoveringFromSeed(is_recovery); - } - - void store(char *path) - { - store_lock.lock(); - if (is_storing) { - return; - } - - is_storing = true; - get_current_wallet()->store(std::string(path)); - is_storing = false; - store_lock.unlock(); - } - - bool transaction_create(char *address, char *payment_id, char *amount, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) - { - nice(19); - - auto priority = static_cast(priority_raw); - std::string _payment_id; - Monero::PendingTransaction *transaction; - - if (payment_id != nullptr) - { - _payment_id = std::string(payment_id); - } - - if (amount != nullptr) - { - uint64_t _amount = Monero::Wallet::amountFromString(std::string(amount)); - transaction = m_wallet->createTransaction(std::string(address), _payment_id, _amount, m_wallet->defaultMixin(), priority, subaddr_account); - } - else - { - transaction = m_wallet->createTransaction(std::string(address), _payment_id, Monero::optional(), m_wallet->defaultMixin(), priority, subaddr_account); - } - - int status = transaction->status(); - - if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) - { - error = Utf8Box(strdup(transaction->errorString().c_str())); - return false; - } - - if (m_listener != nullptr) { - m_listener->m_new_transaction = true; - } - - pendingTransaction = PendingTransactionRaw(transaction); - return true; - } - - bool transaction_create_mult_dest(char **addresses, char *payment_id, char **amounts, uint32_t size, - uint8_t priority_raw, uint32_t subaddr_account, Utf8Box &error, PendingTransactionRaw &pendingTransaction) - { - nice(19); - - std::vector _addresses; - std::vector _amounts; - - for (int i = 0; i < size; i++) { - _addresses.push_back(std::string(*addresses)); - _amounts.push_back(Monero::Wallet::amountFromString(std::string(*amounts))); - addresses++; - amounts++; - } - - auto priority = static_cast(priority_raw); - std::string _payment_id; - Monero::PendingTransaction *transaction; - - if (payment_id != nullptr) - { - _payment_id = std::string(payment_id); - } - - transaction = m_wallet->createTransactionMultDest(_addresses, _payment_id, _amounts, m_wallet->defaultMixin(), priority, subaddr_account); - - int status = transaction->status(); - - if (status == Monero::PendingTransaction::Status::Status_Error || status == Monero::PendingTransaction::Status::Status_Critical) - { - error = Utf8Box(strdup(transaction->errorString().c_str())); - return false; - } - - if (m_listener != nullptr) { - m_listener->m_new_transaction = true; - } - - pendingTransaction = PendingTransactionRaw(transaction); - return true; - } - - bool transaction_commit(PendingTransactionRaw *transaction, Utf8Box &error) - { - bool committed = transaction->transaction->commit(); - - if (!committed) - { - error = Utf8Box(strdup(transaction->transaction->errorString().c_str())); - } else if (m_listener != nullptr) { - m_listener->m_new_transaction = true; - } - - return committed; - } - - uint64_t get_node_height_or_update(uint64_t base_eight) - { - if (m_cached_syncing_blockchain_height < base_eight) { - m_cached_syncing_blockchain_height = base_eight; - } - - return m_cached_syncing_blockchain_height; - } - - uint64_t get_syncing_height() - { - if (m_listener == nullptr) { - return 0; - } - - uint64_t height = m_listener->height(); - - if (height <= 1) { - return 0; - } - - if (height != m_last_known_wallet_height) - { - m_last_known_wallet_height = height; - } - - return height; - } - - uint64_t is_needed_to_refresh() - { - if (m_listener == nullptr) { - return false; - } - - bool should_refresh = m_listener->isNeedToRefresh(); - - if (should_refresh) { - m_listener->resetNeedToRefresh(); - } - - return should_refresh; - } - - uint8_t is_new_transaction_exist() - { - if (m_listener == nullptr) { - return false; - } - - bool is_new_transaction_exist = m_listener->isNewTransactionExist(); - - if (is_new_transaction_exist) - { - m_listener->resetIsNewTransactionExist(); - } - - return is_new_transaction_exist; - } - - void set_listener() - { - m_last_known_wallet_height = 0; - - if (m_listener != nullptr) - { - free(m_listener); - } - - m_listener = new MoneroWalletListener(); - get_current_wallet()->setListener(m_listener); - } - - int64_t *subaddrress_get_all() - { - std::vector _subaddresses = m_subaddress->getAll(); - size_t size = _subaddresses.size(); - int64_t *subaddresses = (int64_t *)malloc(size * sizeof(int64_t)); - - for (int i = 0; i < size; i++) - { - Monero::SubaddressRow *row = _subaddresses[i]; - SubaddressRow *_row = new SubaddressRow(row->getRowId(), strdup(row->getAddress().c_str()), strdup(row->getLabel().c_str())); - subaddresses[i] = reinterpret_cast(_row); - } - - return subaddresses; - } - - int32_t subaddrress_size() - { - std::vector _subaddresses = m_subaddress->getAll(); - return _subaddresses.size(); - } - - void subaddress_add_row(uint32_t accountIndex, char *label) - { - m_subaddress->addRow(accountIndex, std::string(label)); - } - - void subaddress_set_label(uint32_t accountIndex, uint32_t addressIndex, char *label) - { - m_subaddress->setLabel(accountIndex, addressIndex, std::string(label)); - } - - void subaddress_refresh(uint32_t accountIndex) - { - m_subaddress->refresh(accountIndex); - } - - int32_t account_size() - { - std::vector _accocunts = m_account->getAll(); - return _accocunts.size(); - } - - int64_t *account_get_all() - { - std::vector _accocunts = m_account->getAll(); - size_t size = _accocunts.size(); - int64_t *accocunts = (int64_t *)malloc(size * sizeof(int64_t)); - - for (int i = 0; i < size; i++) - { - Monero::SubaddressAccountRow *row = _accocunts[i]; - AccountRow *_row = new AccountRow(row->getRowId(), strdup(row->getLabel().c_str())); - accocunts[i] = reinterpret_cast(_row); - } - - return accocunts; - } - - void account_add_row(char *label) - { - m_account->addRow(std::string(label)); - } - - void account_set_label_row(uint32_t account_index, char *label) - { - m_account->setLabel(account_index, label); - } - - void account_refresh() - { - m_account->refresh(); - } - - int64_t *transactions_get_all() - { - std::vector transactions = m_transaction_history->getAll(); - size_t size = transactions.size(); - int64_t *transactionAddresses = (int64_t *)malloc(size * sizeof(int64_t)); - - for (int i = 0; i < size; i++) - { - Monero::TransactionInfo *row = transactions[i]; - TransactionInfoRow *tx = new TransactionInfoRow(row); - transactionAddresses[i] = reinterpret_cast(tx); - } - - return transactionAddresses; - } - - void transactions_refresh() - { - m_transaction_history->refresh(); - } - - int64_t transactions_count() - { - return m_transaction_history->count(); - } - - int LedgerExchange( - unsigned char *command, - unsigned int cmd_len, - unsigned char *response, - unsigned int max_resp_len) - { - return -1; - } - - int LedgerFind(char *buffer, size_t len) - { - return -1; - } - - void on_startup() - { - Monero::Utils::onStartup(); - Monero::WalletManagerFactory::setLogLevel(4); - } - - void rescan_blockchain() - { - m_wallet->rescanBlockchainAsync(); - } - - char * get_tx_key(char * txId) - { - return strdup(m_wallet->getTxKey(std::string(txId)).c_str()); - } - - char *get_subaddress_label(uint32_t accountIndex, uint32_t addressIndex) - { - return strdup(get_current_wallet()->getSubaddressLabel(accountIndex, addressIndex).c_str()); - } - - void set_trusted_daemon(bool arg) - { - m_wallet->setTrustedDaemon(arg); - } - - bool trusted_daemon() - { - return m_wallet->trustedDaemon(); - } - - bool validate_address(char *address) - { - return get_current_wallet()->addressValid(std::string(address), 0); // TODO fix like by making the command below work or by otherwise detecting nettype - //return get_current_wallet()->validateAddress(std::string(address)); - } - -#ifdef __cplusplus -} -#endif diff --git a/cw_wownero/ios/Classes/wownero_api.h b/cw_wownero/ios/Classes/wownero_api.h deleted file mode 100644 index 02215161e2..0000000000 --- a/cw_wownero/ios/Classes/wownero_api.h +++ /dev/null @@ -1,42 +0,0 @@ -#include -#include -#include -#include "CwWalletListener.h" - -#ifdef __cplusplus -extern "C" { -#endif - -bool create_wallet(char *path, char *password, char *language, int32_t networkType, char *error); -bool restore_wallet_from_14_word_seed(char *path, char *password, char *seed, int32_t networkType, char *error); -bool restore_wallet_from_25_word_seed(char *path, char *password, char *seed, int32_t networkType, uint64_t restoreHeight, char *error); -bool restore_wallet_from_keys(char *path, char *password, char *language, char *address, char *viewKey, char *spendKey, int32_t networkType, uint64_t restoreHeight, char *error); -void load_wallet(char *path, char *password, int32_t nettype); -bool is_wallet_exist(char *path); - -char *get_filename(); -const char *seed(); -char *get_address(uint32_t account_index, uint32_t address_index); -uint64_t get_full_balance(uint32_t account_index); -uint64_t get_unlocked_balance(uint32_t account_index); -uint64_t get_current_height(); -uint64_t get_node_height(); -uint64_t get_seed_height(char *seed); - -bool is_connected(); - -bool setup_node(char *address, char *login, char *password, bool use_ssl, bool is_light_wallet, char *error); -bool connect_to_node(char *error); -void start_refresh(); -void set_refresh_from_block_height(uint64_t height); -void set_recovering_from_seed(bool is_recovery); -void store(char *path); - -void set_trusted_daemon(bool arg); -bool trusted_daemon(); - -bool validate_address(char *address); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/cw_wownero/ios/cw_wownero.podspec b/cw_wownero/ios/cw_wownero.podspec deleted file mode 100644 index 7b89f0406a..0000000000 --- a/cw_wownero/ios/cw_wownero.podspec +++ /dev/null @@ -1,50 +0,0 @@ -# -# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html. -# Run `pod lib lint cw_wownero.podspec' to validate before publishing. -# -Pod::Spec.new do |s| - s.name = 'cw_wownero' - s.version = '0.0.2' - s.summary = 'Cake Wallet Wownero' - s.description = 'Cake Wallet wrapper over Wownero project' - s.homepage = 'http://cakewallet.com' - s.license = { :file => '../LICENSE' } - s.author = { 'CakeWallet' => 'support@cakewallet.com' } - s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.public_header_files = 'Classes/**/*.h, Classes/*.h, Classes/**/*.hpp, Classes/*.hpp, ../shared_external/ios/libs/wownero/include/src/**/*.h, ../shared_external/ios/libs/wownero/include/contrib/**/*.h, ../shared_external/ios/libs/wownero/include/../shared_external/ios/**/*.h' - s.dependency 'Flutter' - s.dependency 'cw_shared_external' - s.platform = :ios, '10.0' - s.swift_version = '5.0' - s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS' => 'arm64', 'ENABLE_BITCODE' => 'NO' } - s.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/Classes/*.h" } - - s.subspec 'OpenSSL' do |openssl| - openssl.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h' - openssl.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libcrypto.a', '../../../../../cw_shared_external/ios/External/ios/lib/libssl.a' - openssl.libraries = 'ssl', 'crypto' - openssl.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" } - end - - s.subspec 'Sodium' do |sodium| - sodium.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h' - sodium.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libsodium.a' - sodium.libraries = 'sodium' - sodium.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" } - end - - s.subspec 'Boost' do |boost| - boost.preserve_paths = '../../../../../cw_shared_external/ios/External/ios/include/**/*.h', - boost.vendored_libraries = '../../../../../cw_shared_external/ios/External/ios/lib/libboost.a', - boost.libraries = 'boost' - boost.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include/**" } - end - - s.subspec 'Wownero' do |wownero| - wownero.preserve_paths = 'External/ios/include/**/*.h' - wownero.vendored_libraries = 'External/ios/lib/libwownero.a' - wownero.libraries = 'wownero' - wownero.xcconfig = { 'HEADER_SEARCH_PATHS' => "${PODS_ROOT}/#{s.name}/External/ios/include" } - end -end diff --git a/cw_wownero/lib/api/account_list.dart b/cw_wownero/lib/api/account_list.dart deleted file mode 100644 index 8d38051bb9..0000000000 --- a/cw_wownero/lib/api/account_list.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/signatures.dart'; -import 'package:cw_wownero/api/structs/account_row.dart'; -import 'package:cw_wownero/api/types.dart'; -import 'package:cw_wownero/api/wallet.dart'; -import 'package:cw_wownero/api/wownero_api.dart'; -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; -import 'package:flutter/foundation.dart'; - -final accountSizeNative = wowneroApi - .lookup>('account_size') - .asFunction(); - -final accountRefreshNative = wowneroApi - .lookup>('account_refresh') - .asFunction(); - -final accountGetAllNative = wowneroApi - .lookup>('account_get_all') - .asFunction(); - -final accountAddNewNative = wowneroApi - .lookup>('account_add_row') - .asFunction(); - -final accountSetLabelNative = wowneroApi - .lookup>('account_set_label_row') - .asFunction(); - -bool isUpdating = false; - -void refreshAccounts() { - try { - isUpdating = true; - accountRefreshNative(); - isUpdating = false; - } catch (e) { - isUpdating = false; - rethrow; - } -} - -List getAllAccount() { - final size = accountSizeNative(); - final accountAddressesPointer = accountGetAllNative(); - final accountAddresses = accountAddressesPointer.asTypedList(size); - - return accountAddresses - .map((addr) => Pointer.fromAddress(addr).ref) - .toList(); -} - -void addAccountSync({required String label}) { - final labelPointer = label.toNativeUtf8(); - accountAddNewNative(labelPointer); - pkgffi.calloc.free(labelPointer); -} - -void setLabelForAccountSync({int? accountIndex, required String label}) { - final labelPointer = label.toNativeUtf8(); - accountSetLabelNative(accountIndex, labelPointer); - pkgffi.calloc.free(labelPointer); -} - -void _addAccount(String? label) => addAccountSync(label: label!); - -void _setLabelForAccount(Map args) { - final label = args['label'] as String; - final accountIndex = args['accountIndex'] as int?; - - setLabelForAccountSync(label: label, accountIndex: accountIndex); -} - -Future addAccount({String? label}) async { - await compute(_addAccount, label); - await store(); -} - -Future setLabelForAccount({int? accountIndex, String? label}) async { - await compute( - _setLabelForAccount, {'accountIndex': accountIndex, 'label': label}); - await store(); -} diff --git a/cw_wownero/lib/api/convert_utf8_to_string.dart b/cw_wownero/lib/api/convert_utf8_to_string.dart deleted file mode 100644 index 28b1ecdd74..0000000000 --- a/cw_wownero/lib/api/convert_utf8_to_string.dart +++ /dev/null @@ -1,10 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; - -String convertUTF8ToString({required Pointer pointer}) { - final str = pointer.toDartString(); - pkgffi.calloc.free(pointer); - return str; -} diff --git a/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart b/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart deleted file mode 100644 index d2ddc62837..0000000000 --- a/cw_wownero/lib/api/exceptions/connection_to_node_exception.dart +++ /dev/null @@ -1,5 +0,0 @@ -class ConnectionToNodeException implements Exception { - ConnectionToNodeException({this.message}); - - final String? message; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/creation_transaction_exception.dart b/cw_wownero/lib/api/exceptions/creation_transaction_exception.dart deleted file mode 100644 index 5af419b4e5..0000000000 --- a/cw_wownero/lib/api/exceptions/creation_transaction_exception.dart +++ /dev/null @@ -1,8 +0,0 @@ -class CreationTransactionException implements Exception { - CreationTransactionException({this.message}); - - final String? message; - - @override - String toString() => message!; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart b/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart deleted file mode 100644 index 102620562c..0000000000 --- a/cw_wownero/lib/api/exceptions/setup_wallet_exception.dart +++ /dev/null @@ -1,5 +0,0 @@ -class SetupWalletException implements Exception { - SetupWalletException({this.message}); - - final String? message; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/wallet_creation_exception.dart b/cw_wownero/lib/api/exceptions/wallet_creation_exception.dart deleted file mode 100644 index 443981b1d5..0000000000 --- a/cw_wownero/lib/api/exceptions/wallet_creation_exception.dart +++ /dev/null @@ -1,8 +0,0 @@ -class WalletCreationException implements Exception { - WalletCreationException({this.message}); - - final String? message; - - @override - String toString() => message!; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/wallet_opening_exception.dart b/cw_wownero/lib/api/exceptions/wallet_opening_exception.dart deleted file mode 100644 index ce4c6fc39d..0000000000 --- a/cw_wownero/lib/api/exceptions/wallet_opening_exception.dart +++ /dev/null @@ -1,8 +0,0 @@ -class WalletOpeningException implements Exception { - WalletOpeningException({this.message}); - - final String? message; - - @override - String toString() => message!; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart b/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart deleted file mode 100644 index d5dd8de56f..0000000000 --- a/cw_wownero/lib/api/exceptions/wallet_restore_from_keys_exception.dart +++ /dev/null @@ -1,5 +0,0 @@ -class WalletRestoreFromKeysException implements Exception { - WalletRestoreFromKeysException({this.message}); - - final String? message; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/exceptions/wallet_restore_from_seed_exception.dart b/cw_wownero/lib/api/exceptions/wallet_restore_from_seed_exception.dart deleted file mode 100644 index ed8a4819cc..0000000000 --- a/cw_wownero/lib/api/exceptions/wallet_restore_from_seed_exception.dart +++ /dev/null @@ -1,5 +0,0 @@ -class WalletRestoreFromSeedException implements Exception { - WalletRestoreFromSeedException({this.message}); - - final String? message; -} \ No newline at end of file diff --git a/cw_wownero/lib/api/signatures.dart b/cw_wownero/lib/api/signatures.dart deleted file mode 100644 index 9a48289609..0000000000 --- a/cw_wownero/lib/api/signatures.dart +++ /dev/null @@ -1,152 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/structs/pending_transaction.dart'; -import 'package:cw_wownero/api/structs/ut8_box.dart'; -import 'package:ffi/ffi.dart'; - -typedef create_14_word_wallet = Int8 Function( - Pointer, Pointer, Pointer, Int32, Pointer); - -typedef create_25_word_wallet = Int8 Function( - Pointer, Pointer, Pointer, Int32, Pointer); - -typedef restore_wallet_from_14_word_seed = Int8 Function( - Pointer, Pointer, Pointer, Int32, Pointer); - -typedef restore_wallet_from_25_word_seed = Int8 Function( - Pointer, Pointer, Pointer, Int32, Pointer); - -typedef restore_wallet_from_keys = Int8 Function( - Pointer, - Pointer, - Pointer, - Pointer, - Pointer, - Pointer, - Int32, - Int64, - Pointer); - -typedef is_wallet_exist = Int8 Function(Pointer); - -typedef load_wallet = Int8 Function(Pointer, Pointer, Int8); - -typedef error_string = Pointer Function(); - -typedef get_filename = Pointer Function(); - -typedef get_seed = Pointer Function(); - -typedef get_address = Pointer Function(Int32, Int32); - -typedef get_full_balanace = Int64 Function(Int32); - -typedef get_unlocked_balanace = Int64 Function(Int32); - -typedef get_current_height = Int64 Function(); - -typedef get_node_height = Int64 Function(); - -typedef get_seed_height = Int64 Function(Pointer); - -typedef is_connected = Int8 Function(); - -typedef setup_node = Int8 Function( - Pointer, Pointer, Pointer, Int8, Int8, Pointer); - -typedef start_refresh = Void Function(); - -typedef connect_to_node = Int8 Function(); - -typedef set_refresh_from_block_height = Void Function(Int64); - -typedef set_recovering_from_seed = Void Function(Int8); - -typedef store_c = Void Function(Pointer); - -typedef set_password = Int8 Function( - Pointer password, Pointer error); - -typedef set_listener = Void Function(); - -typedef get_syncing_height = Int64 Function(); - -typedef is_needed_to_refresh = Int8 Function(); - -typedef is_new_transaction_exist = Int8 Function(); - -typedef subaddrress_size = Int32 Function(); - -typedef subaddrress_refresh = Void Function(Int32); - -typedef subaddress_get_all = Pointer Function(); - -typedef subaddress_add_new = Void Function( - Int32 accountIndex, Pointer label); - -typedef subaddress_set_label = Void Function( - Int32 accountIndex, Int32 addressIndex, Pointer label); - -typedef account_size = Int32 Function(); - -typedef account_refresh = Void Function(); - -typedef account_get_all = Pointer Function(); - -typedef account_add_new = Void Function(Pointer label); - -typedef account_set_label = Void Function( - Int32 accountIndex, Pointer label); - -typedef transactions_refresh = Void Function(); - -typedef get_tx_key = Pointer Function(Pointer txId); - -typedef transactions_count = Int64 Function(); - -typedef transactions_get_all = Pointer Function(); - -typedef transaction_create = Int8 Function( - Pointer address, - Pointer paymentId, - Pointer amount, - Int8 priorityRaw, - Int32 subaddrAccount, - Pointer error, - Pointer pendingTransaction); - -typedef transaction_create_mult_dest = Int8 Function( - Pointer> addresses, - Pointer paymentId, - Pointer> amounts, - Int32 size, - Int8 priorityRaw, - Int32 subaddrAccount, - Pointer error, - Pointer pendingTransaction); - -typedef transaction_commit = Int8 Function( - Pointer, Pointer); - -typedef secret_view_key = Pointer Function(); - -typedef public_view_key = Pointer Function(); - -typedef secret_spend_key = Pointer Function(); - -typedef public_spend_key = Pointer Function(); - -typedef close_current_wallet = Void Function(); - -typedef on_startup = Void Function(); - -typedef rescan_blockchain = Void Function(); - -typedef get_subaddress_label = Pointer Function( - Int32 accountIndex, Int32 addressIndex); - -typedef set_trusted_daemon = Void Function(Int8 trusted); - -typedef trusted_daemon = Int8 Function(); - -typedef validate_address = Int8 Function(Pointer address); diff --git a/cw_wownero/lib/api/structs/account_row.dart b/cw_wownero/lib/api/structs/account_row.dart deleted file mode 100644 index d41c96e3ec..0000000000 --- a/cw_wownero/lib/api/structs/account_row.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; - -class AccountRow extends Struct { - @Int64() - external int id; - external Pointer label; - - String getLabel() => label.toDartString(); - int getId() => id; -} diff --git a/cw_wownero/lib/api/structs/pending_transaction.dart b/cw_wownero/lib/api/structs/pending_transaction.dart deleted file mode 100644 index c8123c9ebf..0000000000 --- a/cw_wownero/lib/api/structs/pending_transaction.dart +++ /dev/null @@ -1,29 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; - -class PendingTransactionRaw extends Struct { - @Int64() - external int amount; - - @Int64() - external int fee; - - external Pointer hash; - - String getHash() => hash.toDartString(); -} - -class PendingTransactionDescription { - PendingTransactionDescription({ - this.amount, - this.fee, - this.hash, - this.pointerAddress, - }); - - final int? amount; - final int? fee; - final String? hash; - final int? pointerAddress; -} diff --git a/cw_wownero/lib/api/structs/subaddress_row.dart b/cw_wownero/lib/api/structs/subaddress_row.dart deleted file mode 100644 index 09493a3cd0..0000000000 --- a/cw_wownero/lib/api/structs/subaddress_row.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; - -class SubaddressRow extends Struct { - @Int64() - external int id; - external Pointer address; - external Pointer label; - - String getLabel() => label.toDartString(); - String getAddress() => address.toDartString(); - int getId() => id; -} diff --git a/cw_wownero/lib/api/structs/transaction_info_row.dart b/cw_wownero/lib/api/structs/transaction_info_row.dart deleted file mode 100644 index ad3c32e9fd..0000000000 --- a/cw_wownero/lib/api/structs/transaction_info_row.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; - -class TransactionInfoRow extends Struct { - @Uint64() - external int amount; - - @Uint64() - external int fee; - - @Uint64() - external int blockHeight; - - @Uint64() - external int confirmations; - - @Uint32() - external int subaddrAccount; - - @Int8() - external int direction; - - @Int8() - external int isPending; - - @Uint32() - external int subaddrIndex; - - external Pointer hash; - - external Pointer paymentId; - - @Int64() - external int datetime; - - int getDatetime() => datetime; - int getAmount() => amount >= 0 ? amount : amount * -1; - bool getIsPending() => isPending != 0; - String getHash() => hash.toDartString(); - String getPaymentId() => paymentId.toDartString(); -} diff --git a/cw_wownero/lib/api/structs/ut8_box.dart b/cw_wownero/lib/api/structs/ut8_box.dart deleted file mode 100644 index d3b4de5577..0000000000 --- a/cw_wownero/lib/api/structs/ut8_box.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'dart:ffi'; - -import 'package:ffi/ffi.dart'; - -class Utf8Box extends Struct { - external Pointer value; - - String getValue() => value.toDartString(); -} diff --git a/cw_wownero/lib/api/subaddress_list.dart b/cw_wownero/lib/api/subaddress_list.dart deleted file mode 100644 index 05921fd1ea..0000000000 --- a/cw_wownero/lib/api/subaddress_list.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/signatures.dart'; -import 'package:cw_wownero/api/structs/subaddress_row.dart'; -import 'package:cw_wownero/api/types.dart'; -import 'package:cw_wownero/api/wallet.dart'; -import 'package:cw_wownero/api/wownero_api.dart'; -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; -import 'package:flutter/foundation.dart'; - -final subaddressSizeNative = wowneroApi - .lookup>('subaddrress_size') - .asFunction(); - -final subaddressRefreshNative = wowneroApi - .lookup>('subaddress_refresh') - .asFunction(); - -final subaddrressGetAllNative = wowneroApi - .lookup>('subaddrress_get_all') - .asFunction(); - -final subaddrressAddNewNative = wowneroApi - .lookup>('subaddress_add_row') - .asFunction(); - -final subaddrressSetLabelNative = wowneroApi - .lookup>('subaddress_set_label') - .asFunction(); - -bool isUpdating = false; - -void refreshSubaddresses({required int? accountIndex}) { - try { - isUpdating = true; - subaddressRefreshNative(accountIndex); - isUpdating = false; - } catch (e) { - isUpdating = false; - rethrow; - } -} - -List getAllSubaddresses() { - final size = subaddressSizeNative(); - final subaddressAddressesPointer = subaddrressGetAllNative(); - final subaddressAddresses = subaddressAddressesPointer.asTypedList(size); - - return subaddressAddresses - .map((addr) => Pointer.fromAddress(addr).ref) - .toList(); -} - -void addSubaddressSync({int? accountIndex, required String label}) { - final labelPointer = label.toNativeUtf8(); - subaddrressAddNewNative(accountIndex, labelPointer); - pkgffi.calloc.free(labelPointer); -} - -void setLabelForSubaddressSync( - {int? accountIndex, int? addressIndex, required String label}) { - final labelPointer = label.toNativeUtf8(); - - subaddrressSetLabelNative(accountIndex, addressIndex, labelPointer); - pkgffi.calloc.free(labelPointer); -} - -void _addSubaddress(Map args) { - final label = args['label'] as String; - final accountIndex = args['accountIndex'] as int?; - - addSubaddressSync(accountIndex: accountIndex, label: label); -} - -void _setLabelForSubaddress(Map args) { - final label = args['label'] as String; - final accountIndex = args['accountIndex'] as int?; - final addressIndex = args['addressIndex'] as int?; - - setLabelForSubaddressSync( - accountIndex: accountIndex, addressIndex: addressIndex, label: label); -} - -Future addSubaddress({int? accountIndex, String? label}) async { - await compute, void>( - _addSubaddress, {'accountIndex': accountIndex, 'label': label}); - await store(); -} - -Future setLabelForSubaddress( - {int? accountIndex, int? addressIndex, String? label}) async { - await compute, void>(_setLabelForSubaddress, { - 'accountIndex': accountIndex, - 'addressIndex': addressIndex, - 'label': label - }); - await store(); -} diff --git a/cw_wownero/lib/api/transaction_history.dart b/cw_wownero/lib/api/transaction_history.dart deleted file mode 100644 index 5eb022e89d..0000000000 --- a/cw_wownero/lib/api/transaction_history.dart +++ /dev/null @@ -1,242 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/convert_utf8_to_string.dart'; -import 'package:cw_wownero/api/exceptions/creation_transaction_exception.dart'; -import 'package:cw_wownero/api/signatures.dart'; -import 'package:cw_wownero/api/structs/pending_transaction.dart'; -import 'package:cw_wownero/api/structs/transaction_info_row.dart'; -import 'package:cw_wownero/api/structs/ut8_box.dart'; -import 'package:cw_wownero/api/types.dart'; -import 'package:cw_wownero/api/wownero_api.dart'; -import 'package:cw_wownero/api/wownero_output.dart'; -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; -import 'package:flutter/foundation.dart'; - -final transactionsRefreshNative = wowneroApi - .lookup>('transactions_refresh') - .asFunction(); - -final transactionsCountNative = wowneroApi - .lookup>('transactions_count') - .asFunction(); - -final transactionsGetAllNative = wowneroApi - .lookup>('transactions_get_all') - .asFunction(); - -final transactionCreateNative = wowneroApi - .lookup>('transaction_create') - .asFunction(); - -final transactionCreateMultDestNative = wowneroApi - .lookup>( - 'transaction_create_mult_dest') - .asFunction(); - -final transactionCommitNative = wowneroApi - .lookup>('transaction_commit') - .asFunction(); - -final getTxKeyNative = wowneroApi - .lookup>('get_tx_key') - .asFunction(); - -String? getTxKey(String txId) { - final txIdPointer = txId.toNativeUtf8(); - final keyPointer = getTxKeyNative(txIdPointer); - - pkgffi.calloc.free(txIdPointer); - - if (keyPointer != null) { - return convertUTF8ToString(pointer: keyPointer); - } - - return null; -} - -void refreshTransactions() => transactionsRefreshNative(); - -int countOfTransactions() => transactionsCountNative(); - -List getAllTransations() { - final size = transactionsCountNative(); - final transactionsPointer = transactionsGetAllNative(); - final transactionsAddresses = transactionsPointer.asTypedList(size); - - return transactionsAddresses - .map((addr) => Pointer.fromAddress(addr).ref) - .toList(); -} - -PendingTransactionDescription createTransactionSync( - {required String address, - required String paymentId, - String? amount, - int? priorityRaw, - int? accountIndex = 0}) { - final addressPointer = address.toNativeUtf8(); - final paymentIdPointer = paymentId.toNativeUtf8(); - final amountPointer = amount != null ? amount.toNativeUtf8() : nullptr; - - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf()); - final pendingTransactionRawPointer = pkgffi.calloc - .allocate(sizeOf()); - final created = transactionCreateNative( - addressPointer, - paymentIdPointer, - amountPointer, - priorityRaw, - accountIndex, - errorMessagePointer, - pendingTransactionRawPointer) != - 0; - - pkgffi.calloc.free(addressPointer); - pkgffi.calloc.free(paymentIdPointer); - - if (amountPointer != nullptr) { - pkgffi.calloc.free(amountPointer); - } - - if (!created) { - final message = errorMessagePointer.ref.getValue(); - pkgffi.calloc.free(errorMessagePointer); - throw CreationTransactionException(message: message); - } - - return PendingTransactionDescription( - amount: pendingTransactionRawPointer.ref.amount, - fee: pendingTransactionRawPointer.ref.fee, - hash: pendingTransactionRawPointer.ref.getHash(), - pointerAddress: pendingTransactionRawPointer.address); -} - -PendingTransactionDescription createTransactionMultDestSync( - {required List outputs, - required String paymentId, - int? priorityRaw, - int? accountIndex = 0}) { - final int size = outputs.length; - final List> addressesPointers = - outputs.map((output) => output.address!.toNativeUtf8()).toList(); - final Pointer> addressesPointerPointer = - pkgffi.calloc.allocate(size * sizeOf>()); - final List> amountsPointers = - outputs.map((output) => output.amount.toNativeUtf8()).toList(); - final Pointer> amountsPointerPointer = - pkgffi.calloc.allocate(size * sizeOf>()); - - for (int i = 0; i < size; i++) { - addressesPointerPointer[i] = addressesPointers[i]; - amountsPointerPointer[i] = amountsPointers[i]; - } - - final paymentIdPointer = paymentId.toNativeUtf8(); - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf()); - final pendingTransactionRawPointer = pkgffi.calloc - .allocate(sizeOf()); - final created = transactionCreateMultDestNative( - addressesPointerPointer, - paymentIdPointer, - amountsPointerPointer, - size, - priorityRaw, - accountIndex, - errorMessagePointer, - pendingTransactionRawPointer) != - 0; - pkgffi.calloc.free(addressesPointerPointer); - pkgffi.calloc.free(amountsPointerPointer); - - addressesPointers.forEach((element) => pkgffi.calloc.free(element)); - amountsPointers.forEach((element) => pkgffi.calloc.free(element)); - - pkgffi.calloc.free(paymentIdPointer); - - if (!created) { - final message = errorMessagePointer.ref.getValue(); - pkgffi.calloc.free(errorMessagePointer); - throw CreationTransactionException(message: message); - } - - return PendingTransactionDescription( - amount: pendingTransactionRawPointer.ref.amount, - fee: pendingTransactionRawPointer.ref.fee, - hash: pendingTransactionRawPointer.ref.getHash(), - pointerAddress: pendingTransactionRawPointer.address); -} - -void commitTransactionFromPointerAddress({required int address}) => - commitTransaction( - transactionPointer: - Pointer.fromAddress(address)); - -void commitTransaction({Pointer? transactionPointer}) { - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf()); - final isCommited = - transactionCommitNative(transactionPointer!, errorMessagePointer) != 0; - - if (!isCommited) { - final message = errorMessagePointer.ref.getValue(); - pkgffi.calloc.free(errorMessagePointer); - throw CreationTransactionException(message: message); - } -} - -PendingTransactionDescription _createTransactionSync(Map args) { - final address = args['address'] as String; - final paymentId = args['paymentId'] as String; - final amount = args['amount'] as String?; - final priorityRaw = args['priorityRaw'] as int?; - final accountIndex = args['accountIndex'] as int?; - - return createTransactionSync( - address: address, - paymentId: paymentId, - amount: amount, - priorityRaw: priorityRaw, - accountIndex: accountIndex); -} - -PendingTransactionDescription _createTransactionMultDestSync(Map args) { - final outputs = args['outputs'] as List; - final paymentId = args['paymentId'] as String; - final priorityRaw = args['priorityRaw'] as int?; - final accountIndex = args['accountIndex'] as int?; - - return createTransactionMultDestSync( - outputs: outputs, - paymentId: paymentId, - priorityRaw: priorityRaw, - accountIndex: accountIndex); -} - -Future createTransaction( - {String? address, - String paymentId = '', - String? amount, - int? priorityRaw, - int? accountIndex = 0}) => - compute(_createTransactionSync, { - 'address': address, - 'paymentId': paymentId, - 'amount': amount, - 'priorityRaw': priorityRaw, - 'accountIndex': accountIndex - }); - -Future createTransactionMultDest( - {List? outputs, - String paymentId = '', - int? priorityRaw, - int? accountIndex = 0}) => - compute(_createTransactionMultDestSync, { - 'outputs': outputs, - 'paymentId': paymentId, - 'priorityRaw': priorityRaw, - 'accountIndex': accountIndex - }); diff --git a/cw_wownero/lib/api/types.dart b/cw_wownero/lib/api/types.dart deleted file mode 100644 index f28e5eb0ee..0000000000 --- a/cw_wownero/lib/api/types.dart +++ /dev/null @@ -1,151 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/structs/pending_transaction.dart'; -import 'package:cw_wownero/api/structs/ut8_box.dart'; -import 'package:ffi/ffi.dart'; - -typedef Create14WordWallet = int Function( - Pointer, Pointer, Pointer, int, Pointer); - -typedef Create25WordWallet = int Function( - Pointer, Pointer, Pointer, int, Pointer); - -typedef RestoreWalletFrom14WordSeed = int Function( - Pointer, Pointer, Pointer, int, Pointer); - -typedef RestoreWalletFrom25WordSeed = int Function( - Pointer, Pointer, Pointer, int, Pointer); - -typedef RestoreWalletFromKeys = int Function( - Pointer, - Pointer, - Pointer, - Pointer, - Pointer, - Pointer, - int, - int?, - Pointer); - -typedef IsWalletExist = int Function(Pointer); - -typedef LoadWallet = int Function(Pointer, Pointer, int); - -typedef ErrorString = Pointer Function(); - -typedef GetFilename = Pointer Function(); - -typedef GetSeed = Pointer Function(); - -typedef GetAddress = Pointer Function(int, int); - -typedef GetFullBalance = int Function(int?); - -typedef GetUnlockedBalance = int Function(int?); - -typedef GetCurrentHeight = int Function(); - -typedef GetNodeHeight = int Function(); - -typedef GetSeedHeight = int Function(Pointer); - -typedef IsConnected = int Function(); - -typedef SetupNode = int Function( - Pointer, Pointer, Pointer, int, int, Pointer); - -typedef StartRefresh = void Function(); - -typedef ConnectToNode = int Function(); - -typedef SetRefreshFromBlockHeight = void Function(int?); - -typedef SetRecoveringFromSeed = void Function(int); - -typedef Store = void Function(Pointer); - -typedef SetPassword = int Function( - Pointer password, Pointer error); - -typedef SetListener = void Function(); - -typedef GetSyncingHeight = int Function(); - -typedef IsNeededToRefresh = int Function(); - -typedef IsNewTransactionExist = int Function(); - -typedef SubaddressSize = int Function(); - -typedef SubaddressRefresh = void Function(int?); - -typedef SubaddressGetAll = Pointer Function(); - -typedef SubaddressAddNew = void Function( - int? accountIndex, Pointer label); - -typedef SubaddressSetLabel = void Function( - int? accountIndex, int? addressIndex, Pointer label); - -typedef AccountSize = int Function(); - -typedef AccountRefresh = void Function(); - -typedef AccountGetAll = Pointer Function(); - -typedef AccountAddNew = void Function(Pointer label); - -typedef AccountSetLabel = void Function(int? accountIndex, Pointer label); - -typedef TransactionsRefresh = void Function(); - -typedef GetTxKey = Pointer Function(Pointer txId); - -typedef TransactionsCount = int Function(); - -typedef TransactionsGetAll = Pointer Function(); - -typedef TransactionCreate = int Function( - Pointer address, - Pointer paymentId, - Pointer amount, - int? priorityRaw, - int? subaddrAccount, - Pointer error, - Pointer pendingTransaction); - -typedef TransactionCreateMultDest = int Function( - Pointer> addresses, - Pointer paymentId, - Pointer> amounts, - int size, - int? priorityRaw, - int? subaddrAccount, - Pointer error, - Pointer pendingTransaction); - -typedef TransactionCommit = int Function( - Pointer, Pointer); - -typedef SecretViewKey = Pointer Function(); - -typedef PublicViewKey = Pointer Function(); - -typedef SecretSpendKey = Pointer Function(); - -typedef PublicSpendKey = Pointer Function(); - -typedef CloseCurrentWallet = void Function(); - -typedef OnStartup = void Function(); - -typedef RescanBlockchainAsync = void Function(); - -typedef GetSubaddressLabel = Pointer Function( - int accountIndex, int addressIndex); - -typedef SetTrustedDaemon = void Function(int); - -typedef TrustedDaemon = int Function(); - -typedef ValidateAddress = int Function(Pointer address); diff --git a/cw_wownero/lib/api/wallet.dart b/cw_wownero/lib/api/wallet.dart deleted file mode 100644 index 9cb941e84f..0000000000 --- a/cw_wownero/lib/api/wallet.dart +++ /dev/null @@ -1,422 +0,0 @@ -import 'dart:async'; -import 'dart:ffi'; - -import 'package:cw_wownero/api/convert_utf8_to_string.dart'; -import 'package:cw_wownero/api/exceptions/setup_wallet_exception.dart'; -import 'package:cw_wownero/api/signatures.dart'; -import 'package:cw_wownero/api/structs/ut8_box.dart'; -import 'package:cw_wownero/api/types.dart'; -import 'package:cw_wownero/api/wownero_api.dart'; -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; -import 'package:flutter/foundation.dart'; - -int _boolToInt(bool value) => value ? 1 : 0; - -final getFileNameNative = wowneroApi - .lookup>('get_filename') - .asFunction(); - -final getSeedNative = - wowneroApi.lookup>('seed').asFunction(); - -final getAddressNative = wowneroApi - .lookup>('get_address') - .asFunction(); - -final getFullBalanceNative = wowneroApi - .lookup>('get_full_balance') - .asFunction(); - -final getUnlockedBalanceNative = wowneroApi - .lookup>('get_unlocked_balance') - .asFunction(); - -final getCurrentHeightNative = wowneroApi - .lookup>('get_current_height') - .asFunction(); - -final getNodeHeightNative = wowneroApi - .lookup>('get_node_height') - .asFunction(); - -final getSeedHeightNative = wowneroApi - .lookup>('get_seed_height') - .asFunction(); - -final isConnectedNative = wowneroApi - .lookup>('is_connected') - .asFunction(); - -final setupNodeNative = wowneroApi - .lookup>('setup_node') - .asFunction(); - -final startRefreshNative = wowneroApi - .lookup>('start_refresh') - .asFunction(); - -final connecToNodeNative = wowneroApi - .lookup>('connect_to_node') - .asFunction(); - -final setRefreshFromBlockHeightNative = wowneroApi - .lookup>( - 'set_refresh_from_block_height') - .asFunction(); - -final setRecoveringFromSeedNative = wowneroApi - .lookup>( - 'set_recovering_from_seed') - .asFunction(); - -final storeNative = - wowneroApi.lookup>('store').asFunction(); - -final setPasswordNative = wowneroApi - .lookup>('set_password') - .asFunction(); - -final setListenerNative = wowneroApi - .lookup>('set_listener') - .asFunction(); - -final getSyncingHeightNative = wowneroApi - .lookup>('get_syncing_height') - .asFunction(); - -final isNeededToRefreshNative = wowneroApi - .lookup>('is_needed_to_refresh') - .asFunction(); - -final isNewTransactionExistNative = wowneroApi - .lookup>( - 'is_new_transaction_exist') - .asFunction(); - -final getSecretViewKeyNative = wowneroApi - .lookup>('secret_view_key') - .asFunction(); - -final getPublicViewKeyNative = wowneroApi - .lookup>('public_view_key') - .asFunction(); - -final getSecretSpendKeyNative = wowneroApi - .lookup>('secret_spend_key') - .asFunction(); - -final getPublicSpendKeyNative = wowneroApi - .lookup>('public_spend_key') - .asFunction(); - -final closeCurrentWalletNative = wowneroApi - .lookup>('close_current_wallet') - .asFunction(); - -final onStartupNative = wowneroApi - .lookup>('on_startup') - .asFunction(); - -final rescanBlockchainAsyncNative = wowneroApi - .lookup>('rescan_blockchain') - .asFunction(); - -final getSubaddressLabelNative = wowneroApi - .lookup>('get_subaddress_label') - .asFunction(); - -final setTrustedDaemonNative = wowneroApi - .lookup>('set_trusted_daemon') - .asFunction(); - -final trustedDaemonNative = wowneroApi - .lookup>('trusted_daemon') - .asFunction(); - -final validateAddressNative = wowneroApi - .lookup>('validate_address') - .asFunction(); - -int getSyncingHeight() => getSyncingHeightNative(); - -bool isNeededToRefresh() => isNeededToRefreshNative() != 0; - -bool isNewTransactionExist() => isNewTransactionExistNative() != 0; - -String getFilename() => convertUTF8ToString(pointer: getFileNameNative()); - -String getSeed() => convertUTF8ToString(pointer: getSeedNative()); - -String getAddress({int accountIndex = 0, int addressIndex = 0}) => - convertUTF8ToString(pointer: getAddressNative(accountIndex, addressIndex)); - -int getFullBalance({int? accountIndex = 0}) => - getFullBalanceNative(accountIndex); - -int getUnlockedBalance({int? accountIndex = 0}) => - getUnlockedBalanceNative(accountIndex); - -int getCurrentHeight() => getCurrentHeightNative(); - -int getNodeHeightSync() => getNodeHeightNative(); - -int getSeedHeightSync(String seed) { - final seedPointer = seed.toNativeUtf8(); - final ret = getSeedHeightNative(seedPointer); - pkgffi.calloc.free(seedPointer); - return ret; -} - -bool isConnectedSync() => isConnectedNative() != 0; - -bool setupNodeSync( - {required String address, - String? login, - String? password, - bool useSSL = false, - bool isLightWallet = false}) { - print("SetupNodeSync begin"); - final addressPointer = address.toNativeUtf8(); - Pointer? loginPointer; - Pointer? passwordPointer; - - if (login != null) { - loginPointer = login.toNativeUtf8(); - } - - if (password != null) { - passwordPointer = password.toNativeUtf8(); - } - - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf>()); - final isSetupNode = setupNodeNative( - addressPointer, - loginPointer!, - passwordPointer!, - _boolToInt(useSSL), - _boolToInt(isLightWallet), - errorMessagePointer) != - 0; - - pkgffi.calloc.free(addressPointer); - pkgffi.calloc.free(loginPointer); - pkgffi.calloc.free(passwordPointer); - - if (!isSetupNode) { - throw SetupWalletException( - message: convertUTF8ToString(pointer: errorMessagePointer)); - } - print("setup nodesync end"); - - return isSetupNode; -} - -void startRefreshSync() => startRefreshNative(); - -Future connectToNode() async => connecToNodeNative() != 0; - -void setRefreshFromBlockHeight({int? height = 0}) => - setRefreshFromBlockHeightNative(height ?? 0); - -void setRecoveringFromSeed({required bool isRecovery}) => - setRecoveringFromSeedNative(_boolToInt(isRecovery)); - -void storeSync() { - final pathPointer = ''.toNativeUtf8(); - storeNative(pathPointer); - pkgffi.calloc.free(pathPointer); -} - -void setPasswordSync(String password) { - final passwordPointer = password.toNativeUtf8(); - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf()); - // final errorMessagePointer = allocate(); - final changed = setPasswordNative(passwordPointer, errorMessagePointer) != 0; - pkgffi.calloc.free(passwordPointer); - - if (!changed) { - final message = errorMessagePointer.ref.getValue(); - pkgffi.calloc.free(errorMessagePointer); - throw Exception(message); - } - - pkgffi.calloc.free(errorMessagePointer); -} - -void closeCurrentWallet() => closeCurrentWalletNative(); - -String getSecretViewKey() => - convertUTF8ToString(pointer: getSecretViewKeyNative()); - -String getPublicViewKey() => - convertUTF8ToString(pointer: getPublicViewKeyNative()); - -String getSecretSpendKey() => - convertUTF8ToString(pointer: getSecretSpendKeyNative()); - -String getPublicSpendKey() => - convertUTF8ToString(pointer: getPublicSpendKeyNative()); - -class SyncListener { - SyncListener(this.onNewBlock, this.onNewTransaction) { - _cachedBlockchainHeight = 0; - _lastKnownBlockHeight = 0; - _initialSyncHeight = 0; - } - - void Function(int, int, double) onNewBlock; - void Function() onNewTransaction; - - Timer? _updateSyncInfoTimer; - int? _cachedBlockchainHeight; - int? _lastKnownBlockHeight; - late int _initialSyncHeight; - - Future getNodeHeightOrUpdate(int baseHeight) async { - if (_cachedBlockchainHeight! < baseHeight || _cachedBlockchainHeight == 0) { - _cachedBlockchainHeight = await getNodeHeight(); - } - - return _cachedBlockchainHeight; - } - - void start() { - _cachedBlockchainHeight = 0; - _lastKnownBlockHeight = 0; - _initialSyncHeight = 0; - _updateSyncInfoTimer ??= - Timer.periodic(Duration(milliseconds: 1200), (_) async { - if (isNewTransactionExist()) { - onNewTransaction.call(); - } - - var syncHeight = getSyncingHeight(); - - if (syncHeight <= 0) { - syncHeight = getCurrentHeight(); - } - - if (_initialSyncHeight <= 0) { - _initialSyncHeight = syncHeight; - } - - final bchHeight = await getNodeHeightOrUpdate(syncHeight); - - if (_lastKnownBlockHeight == syncHeight || syncHeight == null) { - return; - } - - _lastKnownBlockHeight = syncHeight; - final track = bchHeight! - _initialSyncHeight; - final diff = track - (bchHeight - syncHeight); - final ptc = diff <= 0 ? 0.0 : diff / track; - final left = bchHeight - syncHeight; - - if (syncHeight < 0 || left < 0) { - return; - } - - // 1. Actual new height; 2. Blocks left to finish; 3. Progress in percents; - onNewBlock.call(syncHeight, left, ptc); - }); - } - - void stop() => _updateSyncInfoTimer?.cancel(); -} - -SyncListener setListeners(void Function(int, int, double) onNewBlock, - void Function() onNewTransaction) { - final listener = SyncListener(onNewBlock, onNewTransaction); - setListenerNative(); - return listener; -} - -void onStartup() => onStartupNative(); - -void _storeSync(Object _) => storeSync(); - -bool _setupNodeSync(Map args) { - final address = args['address'] as String; - final login = (args['login'] ?? '') as String; - final password = (args['password'] ?? '') as String; - final useSSL = args['useSSL'] as bool; - final isLightWallet = args['isLightWallet'] as bool; - - return setupNodeSync( - address: address, - login: login, - password: password, - useSSL: useSSL, - isLightWallet: isLightWallet); -} - -bool _isConnected(Object _) => isConnectedSync(); - -int _getNodeHeight(Object _) => getNodeHeightSync(); - -void startRefresh() => startRefreshSync(); - -Future setupNode( - {String? address, - String? login, - String? password, - bool useSSL = false, - bool isLightWallet = false}) => - compute, void>(_setupNodeSync, { - 'address': address, - 'login': login, - 'password': password, - 'useSSL': useSSL, - 'isLightWallet': isLightWallet - }); - -int storeTime = 0; -bool priorityInQueue = false; - -Future store({bool prioritySave = false}) async { - if (priorityInQueue) { - return false; - } - print( - "${DateTime.now().millisecondsSinceEpoch} $prioritySave $priorityInQueue"); - if (DateTime.now().millisecondsSinceEpoch < storeTime + 90000 && - prioritySave) { - priorityInQueue = true; - await Future.delayed(Duration(seconds: 1)); - priorityInQueue = false; - return store(prioritySave: prioritySave); - } else if (DateTime.now().millisecondsSinceEpoch < storeTime + 90000 && - !prioritySave) { - return false; - } - print("released $storeTime"); - storeTime = DateTime.now().millisecondsSinceEpoch; - await compute(_storeSync, 0); - return true; -} - -Future isConnected() => compute(_isConnected, 0); - -Future getNodeHeight() => compute(_getNodeHeight, 0); - -void rescanBlockchainAsync() => rescanBlockchainAsyncNative(); - -String getSubaddressLabel(int accountIndex, int addressIndex) { - return convertUTF8ToString( - pointer: getSubaddressLabelNative(accountIndex, addressIndex)); -} - -Future setTrustedDaemon(bool trusted) async => - setTrustedDaemonNative(_boolToInt(trusted)); - -Future trustedDaemon() async => trustedDaemonNative() != 0; - -bool validateAddress(String address) { - final addressPointer = address.toNativeUtf8(); - final valid = validateAddressNative(addressPointer) != 0; - pkgffi.calloc.free(addressPointer); - return valid; -} diff --git a/cw_wownero/lib/api/wallet_manager.dart b/cw_wownero/lib/api/wallet_manager.dart deleted file mode 100644 index 3a24a925b9..0000000000 --- a/cw_wownero/lib/api/wallet_manager.dart +++ /dev/null @@ -1,291 +0,0 @@ -import 'dart:ffi'; - -import 'package:cw_wownero/api/convert_utf8_to_string.dart'; -import 'package:cw_wownero/api/exceptions/wallet_creation_exception.dart'; -import 'package:cw_wownero/api/exceptions/wallet_opening_exception.dart'; -import 'package:cw_wownero/api/exceptions/wallet_restore_from_keys_exception.dart'; -import 'package:cw_wownero/api/exceptions/wallet_restore_from_seed_exception.dart'; -import 'package:cw_wownero/api/signatures.dart'; -import 'package:cw_wownero/api/types.dart'; -import 'package:cw_wownero/api/wownero_api.dart'; -import 'package:ffi/ffi.dart'; -import 'package:ffi/ffi.dart' as pkgffi; -import 'package:flutter/foundation.dart'; - -final create14WordWalletNative = wowneroApi - .lookup>('create_14_word_wallet') - .asFunction(); - -final create25WordWalletNative = wowneroApi - .lookup>('create_25_word_wallet') - .asFunction(); - -final restoreWalletFrom14WordSeedNative = wowneroApi - .lookup>( - 'restore_wallet_from_14_word_seed') - .asFunction(); - -final restoreWalletFrom25WordSeedNative = wowneroApi - .lookup>( - 'restore_wallet_from_25_word_seed') - .asFunction(); - -final restoreWalletFromKeysNative = wowneroApi - .lookup>( - 'restore_wallet_from_keys') - .asFunction(); - -final isWalletExistNative = wowneroApi - .lookup>('is_wallet_exist') - .asFunction(); - -final loadWalletNative = wowneroApi - .lookup>('load_wallet') - .asFunction(); - -final errorStringNative = wowneroApi - .lookup>('error_string') - .asFunction(); - -void createWalletSync( - {required String path, - required String password, - required String language, - int nettype = 0, - int seedWordsLength = 14}) { - final pathPointer = path.toNativeUtf8(); - final passwordPointer = password.toNativeUtf8(); - final languagePointer = language.toNativeUtf8(); - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf>()); - - bool - isWalletCreated; // TODO refactor to return to use of final isWalletCreated - if (seedWordsLength == 14) { - isWalletCreated = create14WordWalletNative(pathPointer, passwordPointer, - languagePointer, nettype, errorMessagePointer) != - 0; - } else /*if (seedWordsLength == 25)*/ { - isWalletCreated = create25WordWalletNative(pathPointer, passwordPointer, - languagePointer, nettype, errorMessagePointer) != - 0; - // TODO handle other cases / validation - } - - pkgffi.calloc.free(pathPointer); - pkgffi.calloc.free(passwordPointer); - pkgffi.calloc.free(languagePointer); - - if (!isWalletCreated) { - throw WalletCreationException( - message: convertUTF8ToString(pointer: errorMessagePointer)); - } - - // setupNodeSync(address: "node.moneroworld.com:18089"); -} - -bool isWalletExistSync({required String path}) { - final pathPointer = path.toNativeUtf8(); - final isExist = isWalletExistNative(pathPointer) != 0; - - pkgffi.calloc.free(pathPointer); - - return isExist; -} - -void restoreWalletFromSeedSync( - {required String path, - required String password, - required String seed, - int nettype = 0, - int? restoreHeight = 0}) { - final pathPointer = path.toNativeUtf8(); - final passwordPointer = password.toNativeUtf8(); - final seedPointer = seed.toNativeUtf8(); - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf>()); - - int seedWordsLength = seed.split(' ').length; - bool isWalletRestored; // TODO refactor to return to use of final isRestored - if (seedWordsLength == 14) { - isWalletRestored = restoreWalletFrom14WordSeedNative(pathPointer, - passwordPointer, seedPointer, nettype, errorMessagePointer) != - 0; - } else /*if(seedWordsLength == 25)*/ { - isWalletRestored = restoreWalletFrom25WordSeedNative(pathPointer, - passwordPointer, seedPointer, nettype, errorMessagePointer) != - 0; - // TODO handle other cases / validation - } - - pkgffi.calloc.free(pathPointer); - pkgffi.calloc.free(passwordPointer); - pkgffi.calloc.free(seedPointer); - - if (!isWalletRestored) { - throw WalletRestoreFromSeedException( - message: convertUTF8ToString(pointer: errorMessagePointer)); - } -} - -void restoreWalletFromKeysSync( - {required String path, - required String password, - required String language, - required String address, - required String viewKey, - required String spendKey, - int nettype = 0, - int? restoreHeight = 0}) { - final pathPointer = path.toNativeUtf8(); - final passwordPointer = password.toNativeUtf8(); - final languagePointer = language.toNativeUtf8(); - final addressPointer = address.toNativeUtf8(); - final viewKeyPointer = viewKey.toNativeUtf8(); - final spendKeyPointer = spendKey.toNativeUtf8(); - final errorMessagePointer = - pkgffi.calloc.allocate(sizeOf>()); - final isWalletRestored = restoreWalletFromKeysNative( - pathPointer, - passwordPointer, - languagePointer, - addressPointer, - viewKeyPointer, - spendKeyPointer, - nettype, - restoreHeight, - errorMessagePointer) != - 0; - - pkgffi.calloc.free(pathPointer); - pkgffi.calloc.free(passwordPointer); - pkgffi.calloc.free(languagePointer); - pkgffi.calloc.free(addressPointer); - pkgffi.calloc.free(viewKeyPointer); - pkgffi.calloc.free(spendKeyPointer); - - if (!isWalletRestored) { - throw WalletRestoreFromKeysException( - message: convertUTF8ToString(pointer: errorMessagePointer)); - } -} - -void loadWallet( - {required String path, required String password, int nettype = 0}) { - final pathPointer = path.toNativeUtf8(); - final passwordPointer = password.toNativeUtf8(); - final loaded = loadWalletNative(pathPointer, passwordPointer, nettype) != 0; - pkgffi.calloc.free(pathPointer); - pkgffi.calloc.free(passwordPointer); - - if (!loaded) { - throw WalletOpeningException( - message: convertUTF8ToString(pointer: errorStringNative())); - } -} - -void _createWallet(Map args) { - final path = args['path'] as String; - final password = args['password'] as String; - final language = args['language'] as String; - final seedWordsLength = args['seedWordsLength'] as int?; - - createWalletSync( - path: path, - password: password, - language: language, - seedWordsLength: seedWordsLength ?? 14); -} - -void _restoreFromSeed(Map args) { - final path = args['path'] as String; - final password = args['password'] as String; - final seed = args['seed'] as String; - final restoreHeight = args['restoreHeight'] as int?; - - restoreWalletFromSeedSync( - path: path, password: password, seed: seed, restoreHeight: restoreHeight); -} - -void _restoreFromKeys(Map args) { - final path = args['path'] as String; - final password = args['password'] as String; - final language = args['language'] as String; - final restoreHeight = args['restoreHeight'] as int?; - final address = args['address'] as String; - final viewKey = args['viewKey'] as String; - final spendKey = args['spendKey'] as String; - - restoreWalletFromKeysSync( - path: path, - password: password, - language: language, - restoreHeight: restoreHeight, - address: address, - viewKey: viewKey, - spendKey: spendKey); -} - -Future _openWallet(Map args) async => - loadWallet(path: args['path']!, password: args['password']!); - -bool _isWalletExist(String? path) => isWalletExistSync(path: path!); - -void openWallet( - {required String path, - required String password, - int nettype = 0}) async => - loadWallet(path: path, password: password, nettype: nettype); - -Future openWalletAsync(Map args) async => - compute(_openWallet, args); - -Future createWallet( - {String? path, - String? password, - String? language, - int nettype = 0, - int seedWordsLength = 14}) async => - compute(_createWallet, { - 'path': path, - 'password': password, - 'language': language, - 'nettype': nettype, - 'seedWordsLength': seedWordsLength - }); - -Future restoreFromSeed( - {String? path, - String? password, - String? seed, - int nettype = 0, - int? restoreHeight = 0}) async => - compute, void>(_restoreFromSeed, { - 'path': path, - 'password': password, - 'seed': seed, - 'nettype': nettype, - 'restoreHeight': restoreHeight - }); - -Future restoreFromKeys( - {String? path, - String? password, - String? language, - String? address, - String? viewKey, - String? spendKey, - int nettype = 0, - int? restoreHeight = 0}) async => - compute, void>(_restoreFromKeys, { - 'path': path, - 'password': password, - 'language': language, - 'address': address, - 'viewKey': viewKey, - 'spendKey': spendKey, - 'nettype': nettype, - 'restoreHeight': restoreHeight - }); - -Future isWalletExist({String? path}) => compute(_isWalletExist, path); diff --git a/cw_wownero/lib/api/wownero_api.dart b/cw_wownero/lib/api/wownero_api.dart deleted file mode 100644 index 0828a27a83..0000000000 --- a/cw_wownero/lib/api/wownero_api.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:ffi'; -import 'dart:io'; - -DynamicLibrary get wowneroApi { - if (Platform.environment.containsKey('FLUTTER_TEST')) { - return DynamicLibrary.open( - 'crypto_plugins/flutter_libmonero/scripts/linux/build/libcw_wownero.so'); - } - return Platform.isAndroid || Platform.isLinux - ? DynamicLibrary.open("libcw_wownero.so") - : DynamicLibrary.open("cw_wownero.framework/cw_wownero"); -} diff --git a/cw_wownero/lib/api/wownero_output.dart b/cw_wownero/lib/api/wownero_output.dart deleted file mode 100644 index 58610b974f..0000000000 --- a/cw_wownero/lib/api/wownero_output.dart +++ /dev/null @@ -1,8 +0,0 @@ -import 'package:flutter/foundation.dart'; - -class WowneroOutput { - WowneroOutput({required this.address, required this.amount}); - - final String? address; - final String amount; -} diff --git a/cw_wownero/lib/mnemonics/english.dart b/cw_wownero/lib/mnemonics/english.dart deleted file mode 100644 index fb464d04e8..0000000000 --- a/cw_wownero/lib/mnemonics/english.dart +++ /dev/null @@ -1,1630 +0,0 @@ -class EnglishMnemonics { - static const words = [ - "abbey", - "abducts", - "ability", - "ablaze", - "abnormal", - "abort", - "abrasive", - "absorb", - "abyss", - "academy", - "aces", - "aching", - "acidic", - "acoustic", - "acquire", - "across", - "actress", - "acumen", - "adapt", - "addicted", - "adept", - "adhesive", - "adjust", - "adopt", - "adrenalin", - "adult", - "adventure", - "aerial", - "afar", - "affair", - "afield", - "afloat", - "afoot", - "afraid", - "after", - "against", - "agenda", - "aggravate", - "agile", - "aglow", - "agnostic", - "agony", - "agreed", - "ahead", - "aided", - "ailments", - "aimless", - "airport", - "aisle", - "ajar", - "akin", - "alarms", - "album", - "alchemy", - "alerts", - "algebra", - "alkaline", - "alley", - "almost", - "aloof", - "alpine", - "already", - "also", - "altitude", - "alumni", - "always", - "amaze", - "ambush", - "amended", - "amidst", - "ammo", - "amnesty", - "among", - "amply", - "amused", - "anchor", - "android", - "anecdote", - "angled", - "ankle", - "annoyed", - "answers", - "antics", - "anvil", - "anxiety", - "anybody", - "apart", - "apex", - "aphid", - "aplomb", - "apology", - "apply", - "apricot", - "aptitude", - "aquarium", - "arbitrary", - "archer", - "ardent", - "arena", - "argue", - "arises", - "army", - "around", - "arrow", - "arsenic", - "artistic", - "ascend", - "ashtray", - "aside", - "asked", - "asleep", - "aspire", - "assorted", - "asylum", - "athlete", - "atlas", - "atom", - "atrium", - "attire", - "auburn", - "auctions", - "audio", - "august", - "aunt", - "austere", - "autumn", - "avatar", - "avidly", - "avoid", - "awakened", - "awesome", - "awful", - "awkward", - "awning", - "awoken", - "axes", - "axis", - "axle", - "aztec", - "azure", - "baby", - "bacon", - "badge", - "baffles", - "bagpipe", - "bailed", - "bakery", - "balding", - "bamboo", - "banjo", - "baptism", - "basin", - "batch", - "bawled", - "bays", - "because", - "beer", - "befit", - "begun", - "behind", - "being", - "below", - "bemused", - "benches", - "berries", - "bested", - "betting", - "bevel", - "beware", - "beyond", - "bias", - "bicycle", - "bids", - "bifocals", - "biggest", - "bikini", - "bimonthly", - "binocular", - "biology", - "biplane", - "birth", - "biscuit", - "bite", - "biweekly", - "blender", - "blip", - "bluntly", - "boat", - "bobsled", - "bodies", - "bogeys", - "boil", - "boldly", - "bomb", - "border", - "boss", - "both", - "bounced", - "bovine", - "bowling", - "boxes", - "boyfriend", - "broken", - "brunt", - "bubble", - "buckets", - "budget", - "buffet", - "bugs", - "building", - "bulb", - "bumper", - "bunch", - "business", - "butter", - "buying", - "buzzer", - "bygones", - "byline", - "bypass", - "cabin", - "cactus", - "cadets", - "cafe", - "cage", - "cajun", - "cake", - "calamity", - "camp", - "candy", - "casket", - "catch", - "cause", - "cavernous", - "cease", - "cedar", - "ceiling", - "cell", - "cement", - "cent", - "certain", - "chlorine", - "chrome", - "cider", - "cigar", - "cinema", - "circle", - "cistern", - "citadel", - "civilian", - "claim", - "click", - "clue", - "coal", - "cobra", - "cocoa", - "code", - "coexist", - "coffee", - "cogs", - "cohesive", - "coils", - "colony", - "comb", - "cool", - "copy", - "corrode", - "costume", - "cottage", - "cousin", - "cowl", - "criminal", - "cube", - "cucumber", - "cuddled", - "cuffs", - "cuisine", - "cunning", - "cupcake", - "custom", - "cycling", - "cylinder", - "cynical", - "dabbing", - "dads", - "daft", - "dagger", - "daily", - "damp", - "dangerous", - "dapper", - "darted", - "dash", - "dating", - "dauntless", - "dawn", - "daytime", - "dazed", - "debut", - "decay", - "dedicated", - "deepest", - "deftly", - "degrees", - "dehydrate", - "deity", - "dejected", - "delayed", - "demonstrate", - "dented", - "deodorant", - "depth", - "desk", - "devoid", - "dewdrop", - "dexterity", - "dialect", - "dice", - "diet", - "different", - "digit", - "dilute", - "dime", - "dinner", - "diode", - "diplomat", - "directed", - "distance", - "ditch", - "divers", - "dizzy", - "doctor", - "dodge", - "does", - "dogs", - "doing", - "dolphin", - "domestic", - "donuts", - "doorway", - "dormant", - "dosage", - "dotted", - "double", - "dove", - "down", - "dozen", - "dreams", - "drinks", - "drowning", - "drunk", - "drying", - "dual", - "dubbed", - "duckling", - "dude", - "duets", - "duke", - "dullness", - "dummy", - "dunes", - "duplex", - "duration", - "dusted", - "duties", - "dwarf", - "dwelt", - "dwindling", - "dying", - "dynamite", - "dyslexic", - "each", - "eagle", - "earth", - "easy", - "eating", - "eavesdrop", - "eccentric", - "echo", - "eclipse", - "economics", - "ecstatic", - "eden", - "edgy", - "edited", - "educated", - "eels", - "efficient", - "eggs", - "egotistic", - "eight", - "either", - "eject", - "elapse", - "elbow", - "eldest", - "eleven", - "elite", - "elope", - "else", - "eluded", - "emails", - "ember", - "emerge", - "emit", - "emotion", - "empty", - "emulate", - "energy", - "enforce", - "enhanced", - "enigma", - "enjoy", - "enlist", - "enmity", - "enough", - "enraged", - "ensign", - "entrance", - "envy", - "epoxy", - "equip", - "erase", - "erected", - "erosion", - "error", - "eskimos", - "espionage", - "essential", - "estate", - "etched", - "eternal", - "ethics", - "etiquette", - "evaluate", - "evenings", - "evicted", - "evolved", - "examine", - "excess", - "exhale", - "exit", - "exotic", - "exquisite", - "extra", - "exult", - "fabrics", - "factual", - "fading", - "fainted", - "faked", - "fall", - "family", - "fancy", - "farming", - "fatal", - "faulty", - "fawns", - "faxed", - "fazed", - "feast", - "february", - "federal", - "feel", - "feline", - "females", - "fences", - "ferry", - "festival", - "fetches", - "fever", - "fewest", - "fiat", - "fibula", - "fictional", - "fidget", - "fierce", - "fifteen", - "fight", - "films", - "firm", - "fishing", - "fitting", - "five", - "fixate", - "fizzle", - "fleet", - "flippant", - "flying", - "foamy", - "focus", - "foes", - "foggy", - "foiled", - "folding", - "fonts", - "foolish", - "fossil", - "fountain", - "fowls", - "foxes", - "foyer", - "framed", - "friendly", - "frown", - "fruit", - "frying", - "fudge", - "fuel", - "fugitive", - "fully", - "fuming", - "fungal", - "furnished", - "fuselage", - "future", - "fuzzy", - "gables", - "gadget", - "gags", - "gained", - "galaxy", - "gambit", - "gang", - "gasp", - "gather", - "gauze", - "gave", - "gawk", - "gaze", - "gearbox", - "gecko", - "geek", - "gels", - "gemstone", - "general", - "geometry", - "germs", - "gesture", - "getting", - "geyser", - "ghetto", - "ghost", - "giant", - "giddy", - "gifts", - "gigantic", - "gills", - "gimmick", - "ginger", - "girth", - "giving", - "glass", - "gleeful", - "glide", - "gnaw", - "gnome", - "goat", - "goblet", - "godfather", - "goes", - "goggles", - "going", - "goldfish", - "gone", - "goodbye", - "gopher", - "gorilla", - "gossip", - "gotten", - "gourmet", - "governing", - "gown", - "greater", - "grunt", - "guarded", - "guest", - "guide", - "gulp", - "gumball", - "guru", - "gusts", - "gutter", - "guys", - "gymnast", - "gypsy", - "gyrate", - "habitat", - "hacksaw", - "haggled", - "hairy", - "hamburger", - "happens", - "hashing", - "hatchet", - "haunted", - "having", - "hawk", - "haystack", - "hazard", - "hectare", - "hedgehog", - "heels", - "hefty", - "height", - "hemlock", - "hence", - "heron", - "hesitate", - "hexagon", - "hickory", - "hiding", - "highway", - "hijack", - "hiker", - "hills", - "himself", - "hinder", - "hippo", - "hire", - "history", - "hitched", - "hive", - "hoax", - "hobby", - "hockey", - "hoisting", - "hold", - "honked", - "hookup", - "hope", - "hornet", - "hospital", - "hotel", - "hounded", - "hover", - "howls", - "hubcaps", - "huddle", - "huge", - "hull", - "humid", - "hunter", - "hurried", - "husband", - "huts", - "hybrid", - "hydrogen", - "hyper", - "iceberg", - "icing", - "icon", - "identity", - "idiom", - "idled", - "idols", - "igloo", - "ignore", - "iguana", - "illness", - "imagine", - "imbalance", - "imitate", - "impel", - "inactive", - "inbound", - "incur", - "industrial", - "inexact", - "inflamed", - "ingested", - "initiate", - "injury", - "inkling", - "inline", - "inmate", - "innocent", - "inorganic", - "input", - "inquest", - "inroads", - "insult", - "intended", - "inundate", - "invoke", - "inwardly", - "ionic", - "irate", - "iris", - "irony", - "irritate", - "island", - "isolated", - "issued", - "italics", - "itches", - "items", - "itinerary", - "itself", - "ivory", - "jabbed", - "jackets", - "jaded", - "jagged", - "jailed", - "jamming", - "january", - "jargon", - "jaunt", - "javelin", - "jaws", - "jazz", - "jeans", - "jeers", - "jellyfish", - "jeopardy", - "jerseys", - "jester", - "jetting", - "jewels", - "jigsaw", - "jingle", - "jittery", - "jive", - "jobs", - "jockey", - "jogger", - "joining", - "joking", - "jolted", - "jostle", - "journal", - "joyous", - "jubilee", - "judge", - "juggled", - "juicy", - "jukebox", - "july", - "jump", - "junk", - "jury", - "justice", - "juvenile", - "kangaroo", - "karate", - "keep", - "kennel", - "kept", - "kernels", - "kettle", - "keyboard", - "kickoff", - "kidneys", - "king", - "kiosk", - "kisses", - "kitchens", - "kiwi", - "knapsack", - "knee", - "knife", - "knowledge", - "knuckle", - "koala", - "laboratory", - "ladder", - "lagoon", - "lair", - "lakes", - "lamb", - "language", - "laptop", - "large", - "last", - "later", - "launching", - "lava", - "lawsuit", - "layout", - "lazy", - "lectures", - "ledge", - "leech", - "left", - "legion", - "leisure", - "lemon", - "lending", - "leopard", - "lesson", - "lettuce", - "lexicon", - "liar", - "library", - "licks", - "lids", - "lied", - "lifestyle", - "light", - "likewise", - "lilac", - "limits", - "linen", - "lion", - "lipstick", - "liquid", - "listen", - "lively", - "loaded", - "lobster", - "locker", - "lodge", - "lofty", - "logic", - "loincloth", - "long", - "looking", - "lopped", - "lordship", - "losing", - "lottery", - "loudly", - "love", - "lower", - "loyal", - "lucky", - "luggage", - "lukewarm", - "lullaby", - "lumber", - "lunar", - "lurk", - "lush", - "luxury", - "lymph", - "lynx", - "lyrics", - "macro", - "madness", - "magically", - "mailed", - "major", - "makeup", - "malady", - "mammal", - "maps", - "masterful", - "match", - "maul", - "maverick", - "maximum", - "mayor", - "maze", - "meant", - "mechanic", - "medicate", - "meeting", - "megabyte", - "melting", - "memoir", - "menu", - "merger", - "mesh", - "metro", - "mews", - "mice", - "midst", - "mighty", - "mime", - "mirror", - "misery", - "mittens", - "mixture", - "moat", - "mobile", - "mocked", - "mohawk", - "moisture", - "molten", - "moment", - "money", - "moon", - "mops", - "morsel", - "mostly", - "motherly", - "mouth", - "movement", - "mowing", - "much", - "muddy", - "muffin", - "mugged", - "mullet", - "mumble", - "mundane", - "muppet", - "mural", - "musical", - "muzzle", - "myriad", - "mystery", - "myth", - "nabbing", - "nagged", - "nail", - "names", - "nanny", - "napkin", - "narrate", - "nasty", - "natural", - "nautical", - "navy", - "nearby", - "necklace", - "needed", - "negative", - "neither", - "neon", - "nephew", - "nerves", - "nestle", - "network", - "neutral", - "never", - "newt", - "nexus", - "nibs", - "niche", - "niece", - "nifty", - "nightly", - "nimbly", - "nineteen", - "nirvana", - "nitrogen", - "nobody", - "nocturnal", - "nodes", - "noises", - "nomad", - "noodles", - "northern", - "nostril", - "noted", - "nouns", - "novelty", - "nowhere", - "nozzle", - "nuance", - "nucleus", - "nudged", - "nugget", - "nuisance", - "null", - "number", - "nuns", - "nurse", - "nutshell", - "nylon", - "oaks", - "oars", - "oasis", - "oatmeal", - "obedient", - "object", - "obliged", - "obnoxious", - "observant", - "obtains", - "obvious", - "occur", - "ocean", - "october", - "odds", - "odometer", - "offend", - "often", - "oilfield", - "ointment", - "okay", - "older", - "olive", - "olympics", - "omega", - "omission", - "omnibus", - "onboard", - "oncoming", - "oneself", - "ongoing", - "onion", - "online", - "onslaught", - "onto", - "onward", - "oozed", - "opacity", - "opened", - "opposite", - "optical", - "opus", - "orange", - "orbit", - "orchid", - "orders", - "organs", - "origin", - "ornament", - "orphans", - "oscar", - "ostrich", - "otherwise", - "otter", - "ouch", - "ought", - "ounce", - "ourselves", - "oust", - "outbreak", - "oval", - "oven", - "owed", - "owls", - "owner", - "oxidant", - "oxygen", - "oyster", - "ozone", - "pact", - "paddles", - "pager", - "pairing", - "palace", - "pamphlet", - "pancakes", - "paper", - "paradise", - "pastry", - "patio", - "pause", - "pavements", - "pawnshop", - "payment", - "peaches", - "pebbles", - "peculiar", - "pedantic", - "peeled", - "pegs", - "pelican", - "pencil", - "people", - "pepper", - "perfect", - "pests", - "petals", - "phase", - "pheasants", - "phone", - "phrases", - "physics", - "piano", - "picked", - "pierce", - "pigment", - "piloted", - "pimple", - "pinched", - "pioneer", - "pipeline", - "pirate", - "pistons", - "pitched", - "pivot", - "pixels", - "pizza", - "playful", - "pledge", - "pliers", - "plotting", - "plus", - "plywood", - "poaching", - "pockets", - "podcast", - "poetry", - "point", - "poker", - "polar", - "ponies", - "pool", - "popular", - "portents", - "possible", - "potato", - "pouch", - "poverty", - "powder", - "pram", - "present", - "pride", - "problems", - "pruned", - "prying", - "psychic", - "public", - "puck", - "puddle", - "puffin", - "pulp", - "pumpkins", - "punch", - "puppy", - "purged", - "push", - "putty", - "puzzled", - "pylons", - "pyramid", - "python", - "queen", - "quick", - "quote", - "rabbits", - "racetrack", - "radar", - "rafts", - "rage", - "railway", - "raking", - "rally", - "ramped", - "randomly", - "rapid", - "rarest", - "rash", - "rated", - "ravine", - "rays", - "razor", - "react", - "rebel", - "recipe", - "reduce", - "reef", - "refer", - "regular", - "reheat", - "reinvest", - "rejoices", - "rekindle", - "relic", - "remedy", - "renting", - "reorder", - "repent", - "request", - "reruns", - "rest", - "return", - "reunion", - "revamp", - "rewind", - "rhino", - "rhythm", - "ribbon", - "richly", - "ridges", - "rift", - "rigid", - "rims", - "ringing", - "riots", - "ripped", - "rising", - "ritual", - "river", - "roared", - "robot", - "rockets", - "rodent", - "rogue", - "roles", - "romance", - "roomy", - "roped", - "roster", - "rotate", - "rounded", - "rover", - "rowboat", - "royal", - "ruby", - "rudely", - "ruffled", - "rugged", - "ruined", - "ruling", - "rumble", - "runway", - "rural", - "rustled", - "ruthless", - "sabotage", - "sack", - "sadness", - "safety", - "saga", - "sailor", - "sake", - "salads", - "sample", - "sanity", - "sapling", - "sarcasm", - "sash", - "satin", - "saucepan", - "saved", - "sawmill", - "saxophone", - "sayings", - "scamper", - "scenic", - "school", - "science", - "scoop", - "scrub", - "scuba", - "seasons", - "second", - "sedan", - "seeded", - "segments", - "seismic", - "selfish", - "semifinal", - "sensible", - "september", - "sequence", - "serving", - "session", - "setup", - "seventh", - "sewage", - "shackles", - "shelter", - "shipped", - "shocking", - "shrugged", - "shuffled", - "shyness", - "siblings", - "sickness", - "sidekick", - "sieve", - "sifting", - "sighting", - "silk", - "simplest", - "sincerely", - "sipped", - "siren", - "situated", - "sixteen", - "sizes", - "skater", - "skew", - "skirting", - "skulls", - "skydive", - "slackens", - "sleepless", - "slid", - "slower", - "slug", - "smash", - "smelting", - "smidgen", - "smog", - "smuggled", - "snake", - "sneeze", - "sniff", - "snout", - "snug", - "soapy", - "sober", - "soccer", - "soda", - "software", - "soggy", - "soil", - "solved", - "somewhere", - "sonic", - "soothe", - "soprano", - "sorry", - "southern", - "sovereign", - "sowed", - "soya", - "space", - "speedy", - "sphere", - "spiders", - "splendid", - "spout", - "sprig", - "spud", - "spying", - "square", - "stacking", - "stellar", - "stick", - "stockpile", - "strained", - "stunning", - "stylishly", - "subtly", - "succeed", - "suddenly", - "suede", - "suffice", - "sugar", - "suitcase", - "sulking", - "summon", - "sunken", - "superior", - "surfer", - "sushi", - "suture", - "swagger", - "swept", - "swiftly", - "sword", - "swung", - "syllabus", - "symptoms", - "syndrome", - "syringe", - "system", - "taboo", - "tacit", - "tadpoles", - "tagged", - "tail", - "taken", - "talent", - "tamper", - "tanks", - "tapestry", - "tarnished", - "tasked", - "tattoo", - "taunts", - "tavern", - "tawny", - "taxi", - "teardrop", - "technical", - "tedious", - "teeming", - "tell", - "template", - "tender", - "tepid", - "tequila", - "terminal", - "testing", - "tether", - "textbook", - "thaw", - "theatrics", - "thirsty", - "thorn", - "threaten", - "thumbs", - "thwart", - "ticket", - "tidy", - "tiers", - "tiger", - "tilt", - "timber", - "tinted", - "tipsy", - "tirade", - "tissue", - "titans", - "toaster", - "tobacco", - "today", - "toenail", - "toffee", - "together", - "toilet", - "token", - "tolerant", - "tomorrow", - "tonic", - "toolbox", - "topic", - "torch", - "tossed", - "total", - "touchy", - "towel", - "toxic", - "toyed", - "trash", - "trendy", - "tribal", - "trolling", - "truth", - "trying", - "tsunami", - "tubes", - "tucks", - "tudor", - "tuesday", - "tufts", - "tugs", - "tuition", - "tulips", - "tumbling", - "tunnel", - "turnip", - "tusks", - "tutor", - "tuxedo", - "twang", - "tweezers", - "twice", - "twofold", - "tycoon", - "typist", - "tyrant", - "ugly", - "ulcers", - "ultimate", - "umbrella", - "umpire", - "unafraid", - "unbending", - "uncle", - "under", - "uneven", - "unfit", - "ungainly", - "unhappy", - "union", - "unjustly", - "unknown", - "unlikely", - "unmask", - "unnoticed", - "unopened", - "unplugs", - "unquoted", - "unrest", - "unsafe", - "until", - "unusual", - "unveil", - "unwind", - "unzip", - "upbeat", - "upcoming", - "update", - "upgrade", - "uphill", - "upkeep", - "upload", - "upon", - "upper", - "upright", - "upstairs", - "uptight", - "upwards", - "urban", - "urchins", - "urgent", - "usage", - "useful", - "usher", - "using", - "usual", - "utensils", - "utility", - "utmost", - "utopia", - "uttered", - "vacation", - "vague", - "vain", - "value", - "vampire", - "vane", - "vapidly", - "vary", - "vastness", - "vats", - "vaults", - "vector", - "veered", - "vegan", - "vehicle", - "vein", - "velvet", - "venomous", - "verification", - "vessel", - "veteran", - "vexed", - "vials", - "vibrate", - "victim", - "video", - "viewpoint", - "vigilant", - "viking", - "village", - "vinegar", - "violin", - "vipers", - "virtual", - "visited", - "vitals", - "vivid", - "vixen", - "vocal", - "vogue", - "voice", - "volcano", - "vortex", - "voted", - "voucher", - "vowels", - "voyage", - "vulture", - "wade", - "waffle", - "wagtail", - "waist", - "waking", - "wallets", - "wanted", - "warped", - "washing", - "water", - "waveform", - "waxing", - "wayside", - "weavers", - "website", - "wedge", - "weekday", - "weird", - "welders", - "went", - "wept", - "were", - "western", - "wetsuit", - "whale", - "when", - "whipped", - "whole", - "wickets", - "width", - "wield", - "wife", - "wiggle", - "wildly", - "winter", - "wipeout", - "wiring", - "wise", - "withdrawn", - "wives", - "wizard", - "wobbly", - "woes", - "woken", - "wolf", - "womanly", - "wonders", - "woozy", - "worry", - "wounded", - "woven", - "wrap", - "wrist", - "wrong", - "yacht", - "yahoo", - "yanks", - "yard", - "yawning", - "yearbook", - "yellow", - "yesterday", - "yeti", - "yields", - "yodel", - "yoga", - "younger", - "yoyo", - "zapped", - "zeal", - "zebra", - "zero", - "zesty", - "zigzags", - "zinger", - "zippers", - "zodiac", - "zombie", - "zones", - "zoom" - ]; -} diff --git a/cw_wownero/lib/mnemonics/english14.dart b/cw_wownero/lib/mnemonics/english14.dart deleted file mode 100644 index 8f0c89e8f1..0000000000 --- a/cw_wownero/lib/mnemonics/english14.dart +++ /dev/null @@ -1,2052 +0,0 @@ -class EnglishMnemonics14 { - static const words = [ - "abandon", - "ability", - "able", - "about", - "above", - "absent", - "absorb", - "abstract", - "absurd", - "abuse", - "access", - "accident", - "account", - "accuse", - "achieve", - "acid", - "acoustic", - "acquire", - "across", - "act", - "action", - "actor", - "actress", - "actual", - "adapt", - "add", - "addict", - "address", - "adjust", - "admit", - "adult", - "advance", - "advice", - "aerobic", - "affair", - "afford", - "afraid", - "again", - "age", - "agent", - "agree", - "ahead", - "aim", - "air", - "airport", - "aisle", - "alarm", - "album", - "alcohol", - "alert", - "alien", - "all", - "alley", - "allow", - "almost", - "alone", - "alpha", - "already", - "also", - "alter", - "always", - "amateur", - "amazing", - "among", - "amount", - "amused", - "analyst", - "anchor", - "ancient", - "anger", - "angle", - "angry", - "animal", - "ankle", - "announce", - "annual", - "another", - "answer", - "antenna", - "antique", - "anxiety", - "any", - "apart", - "apology", - "appear", - "apple", - "approve", - "april", - "arch", - "arctic", - "area", - "arena", - "argue", - "arm", - "armed", - "armor", - "army", - "around", - "arrange", - "arrest", - "arrive", - "arrow", - "art", - "artefact", - "artist", - "artwork", - "ask", - "aspect", - "assault", - "asset", - "assist", - "assume", - "asthma", - "athlete", - "atom", - "attack", - "attend", - "attitude", - "attract", - "auction", - "audit", - "august", - "aunt", - "author", - "auto", - "autumn", - "average", - "avocado", - "avoid", - "awake", - "aware", - "away", - "awesome", - "awful", - "awkward", - "axis", - "baby", - "bachelor", - "bacon", - "badge", - "bag", - "balance", - "balcony", - "ball", - "bamboo", - "banana", - "banner", - "bar", - "barely", - "bargain", - "barrel", - "base", - "basic", - "basket", - "battle", - "beach", - "bean", - "beauty", - "because", - "become", - "beef", - "before", - "begin", - "behave", - "behind", - "believe", - "below", - "belt", - "bench", - "benefit", - "best", - "betray", - "better", - "between", - "beyond", - "bicycle", - "bid", - "bike", - "bind", - "biology", - "bird", - "birth", - "bitter", - "black", - "blade", - "blame", - "blanket", - "blast", - "bleak", - "bless", - "blind", - "blood", - "blossom", - "blouse", - "blue", - "blur", - "blush", - "board", - "boat", - "body", - "boil", - "bomb", - "bone", - "bonus", - "book", - "boost", - "border", - "boring", - "borrow", - "boss", - "bottom", - "bounce", - "box", - "boy", - "bracket", - "brain", - "brand", - "brass", - "brave", - "bread", - "breeze", - "brick", - "bridge", - "brief", - "bright", - "bring", - "brisk", - "broccoli", - "broken", - "bronze", - "broom", - "brother", - "brown", - "brush", - "bubble", - "buddy", - "budget", - "buffalo", - "build", - "bulb", - "bulk", - "bullet", - "bundle", - "bunker", - "burden", - "burger", - "burst", - "bus", - "business", - "busy", - "butter", - "buyer", - "buzz", - "cabbage", - "cabin", - "cable", - "cactus", - "cage", - "cake", - "call", - "calm", - "camera", - "camp", - "can", - "canal", - "cancel", - "candy", - "cannon", - "canoe", - "canvas", - "canyon", - "capable", - "capital", - "captain", - "car", - "carbon", - "card", - "cargo", - "carpet", - "carry", - "cart", - "case", - "cash", - "casino", - "castle", - "casual", - "cat", - "catalog", - "catch", - "category", - "cattle", - "caught", - "cause", - "caution", - "cave", - "ceiling", - "celery", - "cement", - "census", - "century", - "cereal", - "certain", - "chair", - "chalk", - "champion", - "change", - "chaos", - "chapter", - "charge", - "chase", - "chat", - "cheap", - "check", - "cheese", - "chef", - "cherry", - "chest", - "chicken", - "chief", - "child", - "chimney", - "choice", - "choose", - "chronic", - "chuckle", - "chunk", - "churn", - "cigar", - "cinnamon", - "circle", - "citizen", - "city", - "civil", - "claim", - "clap", - "clarify", - "claw", - "clay", - "clean", - "clerk", - "clever", - "click", - "client", - "cliff", - "climb", - "clinic", - "clip", - "clock", - "clog", - "close", - "cloth", - "cloud", - "clown", - "club", - "clump", - "cluster", - "clutch", - "coach", - "coast", - "coconut", - "code", - "coffee", - "coil", - "coin", - "collect", - "color", - "column", - "combine", - "come", - "comfort", - "comic", - "common", - "company", - "concert", - "conduct", - "confirm", - "congress", - "connect", - "consider", - "control", - "convince", - "cook", - "cool", - "copper", - "copy", - "coral", - "core", - "corn", - "correct", - "cost", - "cotton", - "couch", - "country", - "couple", - "course", - "cousin", - "cover", - "coyote", - "crack", - "cradle", - "craft", - "cram", - "crane", - "crash", - "crater", - "crawl", - "crazy", - "cream", - "credit", - "creek", - "crew", - "cricket", - "crime", - "crisp", - "critic", - "crop", - "cross", - "crouch", - "crowd", - "crucial", - "cruel", - "cruise", - "crumble", - "crunch", - "crush", - "cry", - "crystal", - "cube", - "culture", - "cup", - "cupboard", - "curious", - "current", - "curtain", - "curve", - "cushion", - "custom", - "cute", - "cycle", - "dad", - "damage", - "damp", - "dance", - "danger", - "daring", - "dash", - "daughter", - "dawn", - "day", - "deal", - "debate", - "debris", - "decade", - "december", - "decide", - "decline", - "decorate", - "decrease", - "deer", - "defense", - "define", - "defy", - "degree", - "delay", - "deliver", - "demand", - "demise", - "denial", - "dentist", - "deny", - "depart", - "depend", - "deposit", - "depth", - "deputy", - "derive", - "describe", - "desert", - "design", - "desk", - "despair", - "destroy", - "detail", - "detect", - "develop", - "device", - "devote", - "diagram", - "dial", - "diamond", - "diary", - "dice", - "diesel", - "diet", - "differ", - "digital", - "dignity", - "dilemma", - "dinner", - "dinosaur", - "direct", - "dirt", - "disagree", - "discover", - "disease", - "dish", - "dismiss", - "disorder", - "display", - "distance", - "divert", - "divide", - "divorce", - "dizzy", - "doctor", - "document", - "dog", - "doll", - "dolphin", - "domain", - "donate", - "donkey", - "donor", - "door", - "dose", - "double", - "dove", - "draft", - "dragon", - "drama", - "drastic", - "draw", - "dream", - "dress", - "drift", - "drill", - "drink", - "drip", - "drive", - "drop", - "drum", - "dry", - "duck", - "dumb", - "dune", - "during", - "dust", - "dutch", - "duty", - "dwarf", - "dynamic", - "eager", - "eagle", - "early", - "earn", - "earth", - "easily", - "east", - "easy", - "echo", - "ecology", - "economy", - "edge", - "edit", - "educate", - "effort", - "egg", - "eight", - "either", - "elbow", - "elder", - "electric", - "elegant", - "element", - "elephant", - "elevator", - "elite", - "else", - "embark", - "embody", - "embrace", - "emerge", - "emotion", - "employ", - "empower", - "empty", - "enable", - "enact", - "end", - "endless", - "endorse", - "enemy", - "energy", - "enforce", - "engage", - "engine", - "enhance", - "enjoy", - "enlist", - "enough", - "enrich", - "enroll", - "ensure", - "enter", - "entire", - "entry", - "envelope", - "episode", - "equal", - "equip", - "era", - "erase", - "erode", - "erosion", - "error", - "erupt", - "escape", - "essay", - "essence", - "estate", - "eternal", - "ethics", - "evidence", - "evil", - "evoke", - "evolve", - "exact", - "example", - "excess", - "exchange", - "excite", - "exclude", - "excuse", - "execute", - "exercise", - "exhaust", - "exhibit", - "exile", - "exist", - "exit", - "exotic", - "expand", - "expect", - "expire", - "explain", - "expose", - "express", - "extend", - "extra", - "eye", - "eyebrow", - "fabric", - "face", - "faculty", - "fade", - "faint", - "faith", - "fall", - "false", - "fame", - "family", - "famous", - "fan", - "fancy", - "fantasy", - "farm", - "fashion", - "fat", - "fatal", - "father", - "fatigue", - "fault", - "favorite", - "feature", - "february", - "federal", - "fee", - "feed", - "feel", - "female", - "fence", - "festival", - "fetch", - "fever", - "few", - "fiber", - "fiction", - "field", - "figure", - "file", - "film", - "filter", - "final", - "find", - "fine", - "finger", - "finish", - "fire", - "firm", - "first", - "fiscal", - "fish", - "fit", - "fitness", - "fix", - "flag", - "flame", - "flash", - "flat", - "flavor", - "flee", - "flight", - "flip", - "float", - "flock", - "floor", - "flower", - "fluid", - "flush", - "fly", - "foam", - "focus", - "fog", - "foil", - "fold", - "follow", - "food", - "foot", - "force", - "forest", - "forget", - "fork", - "fortune", - "forum", - "forward", - "fossil", - "foster", - "found", - "fox", - "fragile", - "frame", - "frequent", - "fresh", - "friend", - "fringe", - "frog", - "front", - "frost", - "frown", - "frozen", - "fruit", - "fuel", - "fun", - "funny", - "furnace", - "fury", - "future", - "gadget", - "gain", - "galaxy", - "gallery", - "game", - "gap", - "garage", - "garbage", - "garden", - "garlic", - "garment", - "gas", - "gasp", - "gate", - "gather", - "gauge", - "gaze", - "general", - "genius", - "genre", - "gentle", - "genuine", - "gesture", - "ghost", - "giant", - "gift", - "giggle", - "ginger", - "giraffe", - "girl", - "give", - "glad", - "glance", - "glare", - "glass", - "glide", - "glimpse", - "globe", - "gloom", - "glory", - "glove", - "glow", - "glue", - "goat", - "goddess", - "gold", - "good", - "goose", - "gorilla", - "gospel", - "gossip", - "govern", - "gown", - "grab", - "grace", - "grain", - "grant", - "grape", - "grass", - "gravity", - "great", - "green", - "grid", - "grief", - "grit", - "grocery", - "group", - "grow", - "grunt", - "guard", - "guess", - "guide", - "guilt", - "guitar", - "gun", - "gym", - "habit", - "hair", - "half", - "hammer", - "hamster", - "hand", - "happy", - "harbor", - "hard", - "harsh", - "harvest", - "hat", - "have", - "hawk", - "hazard", - "head", - "health", - "heart", - "heavy", - "hedgehog", - "height", - "hello", - "helmet", - "help", - "hen", - "hero", - "hidden", - "high", - "hill", - "hint", - "hip", - "hire", - "history", - "hobby", - "hockey", - "hold", - "hole", - "holiday", - "hollow", - "home", - "honey", - "hood", - "hope", - "horn", - "horror", - "horse", - "hospital", - "host", - "hotel", - "hour", - "hover", - "hub", - "huge", - "human", - "humble", - "humor", - "hundred", - "hungry", - "hunt", - "hurdle", - "hurry", - "hurt", - "husband", - "hybrid", - "ice", - "icon", - "idea", - "identify", - "idle", - "ignore", - "ill", - "illegal", - "illness", - "image", - "imitate", - "immense", - "immune", - "impact", - "impose", - "improve", - "impulse", - "inch", - "include", - "income", - "increase", - "index", - "indicate", - "indoor", - "industry", - "infant", - "inflict", - "inform", - "inhale", - "inherit", - "initial", - "inject", - "injury", - "inmate", - "inner", - "innocent", - "input", - "inquiry", - "insane", - "insect", - "inside", - "inspire", - "install", - "intact", - "interest", - "into", - "invest", - "invite", - "involve", - "iron", - "island", - "isolate", - "issue", - "item", - "ivory", - "jacket", - "jaguar", - "jar", - "jazz", - "jealous", - "jeans", - "jelly", - "jewel", - "job", - "join", - "joke", - "journey", - "joy", - "judge", - "juice", - "jump", - "jungle", - "junior", - "junk", - "just", - "kangaroo", - "keen", - "keep", - "ketchup", - "key", - "kick", - "kid", - "kidney", - "kind", - "kingdom", - "kiss", - "kit", - "kitchen", - "kite", - "kitten", - "kiwi", - "knee", - "knife", - "knock", - "know", - "lab", - "label", - "labor", - "ladder", - "lady", - "lake", - "lamp", - "language", - "laptop", - "large", - "later", - "latin", - "laugh", - "laundry", - "lava", - "law", - "lawn", - "lawsuit", - "layer", - "lazy", - "leader", - "leaf", - "learn", - "leave", - "lecture", - "left", - "leg", - "legal", - "legend", - "leisure", - "lemon", - "lend", - "length", - "lens", - "leopard", - "lesson", - "letter", - "level", - "liar", - "liberty", - "library", - "license", - "life", - "lift", - "light", - "like", - "limb", - "limit", - "link", - "lion", - "liquid", - "list", - "little", - "live", - "lizard", - "load", - "loan", - "lobster", - "local", - "lock", - "logic", - "lonely", - "long", - "loop", - "lottery", - "loud", - "lounge", - "love", - "loyal", - "lucky", - "luggage", - "lumber", - "lunar", - "lunch", - "luxury", - "lyrics", - "machine", - "mad", - "magic", - "magnet", - "maid", - "mail", - "main", - "major", - "make", - "mammal", - "man", - "manage", - "mandate", - "mango", - "mansion", - "manual", - "maple", - "marble", - "march", - "margin", - "marine", - "market", - "marriage", - "mask", - "mass", - "master", - "match", - "material", - "math", - "matrix", - "matter", - "maximum", - "maze", - "meadow", - "mean", - "measure", - "meat", - "mechanic", - "medal", - "media", - "melody", - "melt", - "member", - "memory", - "mention", - "menu", - "mercy", - "merge", - "merit", - "merry", - "mesh", - "message", - "metal", - "method", - "middle", - "midnight", - "milk", - "million", - "mimic", - "mind", - "minimum", - "minor", - "minute", - "miracle", - "mirror", - "misery", - "miss", - "mistake", - "mix", - "mixed", - "mixture", - "mobile", - "model", - "modify", - "mom", - "moment", - "monitor", - "monkey", - "monster", - "month", - "moon", - "moral", - "more", - "morning", - "mosquito", - "mother", - "motion", - "motor", - "mountain", - "mouse", - "move", - "movie", - "much", - "muffin", - "mule", - "multiply", - "muscle", - "museum", - "mushroom", - "music", - "must", - "mutual", - "myself", - "mystery", - "myth", - "naive", - "name", - "napkin", - "narrow", - "nasty", - "nation", - "nature", - "near", - "neck", - "need", - "negative", - "neglect", - "neither", - "nephew", - "nerve", - "nest", - "net", - "network", - "neutral", - "never", - "news", - "next", - "nice", - "night", - "noble", - "noise", - "nominee", - "noodle", - "normal", - "north", - "nose", - "notable", - "note", - "nothing", - "notice", - "novel", - "now", - "nuclear", - "number", - "nurse", - "nut", - "oak", - "obey", - "object", - "oblige", - "obscure", - "observe", - "obtain", - "obvious", - "occur", - "ocean", - "october", - "odor", - "off", - "offer", - "office", - "often", - "oil", - "okay", - "old", - "olive", - "olympic", - "omit", - "once", - "one", - "onion", - "online", - "only", - "open", - "opera", - "opinion", - "oppose", - "option", - "orange", - "orbit", - "orchard", - "order", - "ordinary", - "organ", - "orient", - "original", - "orphan", - "ostrich", - "other", - "outdoor", - "outer", - "output", - "outside", - "oval", - "oven", - "over", - "own", - "owner", - "oxygen", - "oyster", - "ozone", - "pact", - "paddle", - "page", - "pair", - "palace", - "palm", - "panda", - "panel", - "panic", - "panther", - "paper", - "parade", - "parent", - "park", - "parrot", - "party", - "pass", - "patch", - "path", - "patient", - "patrol", - "pattern", - "pause", - "pave", - "payment", - "peace", - "peanut", - "pear", - "peasant", - "pelican", - "pen", - "penalty", - "pencil", - "people", - "pepper", - "perfect", - "permit", - "person", - "pet", - "phone", - "photo", - "phrase", - "physical", - "piano", - "picnic", - "picture", - "piece", - "pig", - "pigeon", - "pill", - "pilot", - "pink", - "pioneer", - "pipe", - "pistol", - "pitch", - "pizza", - "place", - "planet", - "plastic", - "plate", - "play", - "please", - "pledge", - "pluck", - "plug", - "plunge", - "poem", - "poet", - "point", - "polar", - "pole", - "police", - "pond", - "pony", - "pool", - "popular", - "portion", - "position", - "possible", - "post", - "potato", - "pottery", - "poverty", - "powder", - "power", - "practice", - "praise", - "predict", - "prefer", - "prepare", - "present", - "pretty", - "prevent", - "price", - "pride", - "primary", - "print", - "priority", - "prison", - "private", - "prize", - "problem", - "process", - "produce", - "profit", - "program", - "project", - "promote", - "proof", - "property", - "prosper", - "protect", - "proud", - "provide", - "public", - "pudding", - "pull", - "pulp", - "pulse", - "pumpkin", - "punch", - "pupil", - "puppy", - "purchase", - "purity", - "purpose", - "purse", - "push", - "put", - "puzzle", - "pyramid", - "quality", - "quantum", - "quarter", - "question", - "quick", - "quit", - "quiz", - "quote", - "rabbit", - "raccoon", - "race", - "rack", - "radar", - "radio", - "rail", - "rain", - "raise", - "rally", - "ramp", - "ranch", - "random", - "range", - "rapid", - "rare", - "rate", - "rather", - "raven", - "raw", - "razor", - "ready", - "real", - "reason", - "rebel", - "rebuild", - "recall", - "receive", - "recipe", - "record", - "recycle", - "reduce", - "reflect", - "reform", - "refuse", - "region", - "regret", - "regular", - "reject", - "relax", - "release", - "relief", - "rely", - "remain", - "remember", - "remind", - "remove", - "render", - "renew", - "rent", - "reopen", - "repair", - "repeat", - "replace", - "report", - "require", - "rescue", - "resemble", - "resist", - "resource", - "response", - "result", - "retire", - "retreat", - "return", - "reunion", - "reveal", - "review", - "reward", - "rhythm", - "rib", - "ribbon", - "rice", - "rich", - "ride", - "ridge", - "rifle", - "right", - "rigid", - "ring", - "riot", - "ripple", - "risk", - "ritual", - "rival", - "river", - "road", - "roast", - "robot", - "robust", - "rocket", - "romance", - "roof", - "rookie", - "room", - "rose", - "rotate", - "rough", - "round", - "route", - "royal", - "rubber", - "rude", - "rug", - "rule", - "run", - "runway", - "rural", - "sad", - "saddle", - "sadness", - "safe", - "sail", - "salad", - "salmon", - "salon", - "salt", - "salute", - "same", - "sample", - "sand", - "satisfy", - "satoshi", - "sauce", - "sausage", - "save", - "say", - "scale", - "scan", - "scare", - "scatter", - "scene", - "scheme", - "school", - "science", - "scissors", - "scorpion", - "scout", - "scrap", - "screen", - "script", - "scrub", - "sea", - "search", - "season", - "seat", - "second", - "secret", - "section", - "security", - "seed", - "seek", - "segment", - "select", - "sell", - "seminar", - "senior", - "sense", - "sentence", - "series", - "service", - "session", - "settle", - "setup", - "seven", - "shadow", - "shaft", - "shallow", - "share", - "shed", - "shell", - "sheriff", - "shield", - "shift", - "shine", - "ship", - "shiver", - "shock", - "shoe", - "shoot", - "shop", - "short", - "shoulder", - "shove", - "shrimp", - "shrug", - "shuffle", - "shy", - "sibling", - "sick", - "side", - "siege", - "sight", - "sign", - "silent", - "silk", - "silly", - "silver", - "similar", - "simple", - "since", - "sing", - "siren", - "sister", - "situate", - "six", - "size", - "skate", - "sketch", - "ski", - "skill", - "skin", - "skirt", - "skull", - "slab", - "slam", - "sleep", - "slender", - "slice", - "slide", - "slight", - "slim", - "slogan", - "slot", - "slow", - "slush", - "small", - "smart", - "smile", - "smoke", - "smooth", - "snack", - "snake", - "snap", - "sniff", - "snow", - "soap", - "soccer", - "social", - "sock", - "soda", - "soft", - "solar", - "soldier", - "solid", - "solution", - "solve", - "someone", - "song", - "soon", - "sorry", - "sort", - "soul", - "sound", - "soup", - "source", - "south", - "space", - "spare", - "spatial", - "spawn", - "speak", - "special", - "speed", - "spell", - "spend", - "sphere", - "spice", - "spider", - "spike", - "spin", - "spirit", - "split", - "spoil", - "sponsor", - "spoon", - "sport", - "spot", - "spray", - "spread", - "spring", - "spy", - "square", - "squeeze", - "squirrel", - "stable", - "stadium", - "staff", - "stage", - "stairs", - "stamp", - "stand", - "start", - "state", - "stay", - "steak", - "steel", - "stem", - "step", - "stereo", - "stick", - "still", - "sting", - "stock", - "stomach", - "stone", - "stool", - "story", - "stove", - "strategy", - "street", - "strike", - "strong", - "struggle", - "student", - "stuff", - "stumble", - "style", - "subject", - "submit", - "subway", - "success", - "such", - "sudden", - "suffer", - "sugar", - "suggest", - "suit", - "summer", - "sun", - "sunny", - "sunset", - "super", - "supply", - "supreme", - "sure", - "surface", - "surge", - "surprise", - "surround", - "survey", - "suspect", - "sustain", - "swallow", - "swamp", - "swap", - "swarm", - "swear", - "sweet", - "swift", - "swim", - "swing", - "switch", - "sword", - "symbol", - "symptom", - "syrup", - "system", - "table", - "tackle", - "tag", - "tail", - "talent", - "talk", - "tank", - "tape", - "target", - "task", - "taste", - "tattoo", - "taxi", - "teach", - "team", - "tell", - "ten", - "tenant", - "tennis", - "tent", - "term", - "test", - "text", - "thank", - "that", - "theme", - "then", - "theory", - "there", - "they", - "thing", - "this", - "thought", - "three", - "thrive", - "throw", - "thumb", - "thunder", - "ticket", - "tide", - "tiger", - "tilt", - "timber", - "time", - "tiny", - "tip", - "tired", - "tissue", - "title", - "toast", - "tobacco", - "today", - "toddler", - "toe", - "together", - "toilet", - "token", - "tomato", - "tomorrow", - "tone", - "tongue", - "tonight", - "tool", - "tooth", - "top", - "topic", - "topple", - "torch", - "tornado", - "tortoise", - "toss", - "total", - "tourist", - "toward", - "tower", - "town", - "toy", - "track", - "trade", - "traffic", - "tragic", - "train", - "transfer", - "trap", - "trash", - "travel", - "tray", - "treat", - "tree", - "trend", - "trial", - "tribe", - "trick", - "trigger", - "trim", - "trip", - "trophy", - "trouble", - "truck", - "true", - "truly", - "trumpet", - "trust", - "truth", - "try", - "tube", - "tuition", - "tumble", - "tuna", - "tunnel", - "turkey", - "turn", - "turtle", - "twelve", - "twenty", - "twice", - "twin", - "twist", - "two", - "type", - "typical", - "ugly", - "umbrella", - "unable", - "unaware", - "uncle", - "uncover", - "under", - "undo", - "unfair", - "unfold", - "unhappy", - "uniform", - "unique", - "unit", - "universe", - "unknown", - "unlock", - "until", - "unusual", - "unveil", - "update", - "upgrade", - "uphold", - "upon", - "upper", - "upset", - "urban", - "urge", - "usage", - "use", - "used", - "useful", - "useless", - "usual", - "utility", - "vacant", - "vacuum", - "vague", - "valid", - "valley", - "valve", - "van", - "vanish", - "vapor", - "various", - "vast", - "vault", - "vehicle", - "velvet", - "vendor", - "venture", - "venue", - "verb", - "verify", - "version", - "very", - "vessel", - "veteran", - "viable", - "vibrant", - "vicious", - "victory", - "video", - "view", - "village", - "vintage", - "violin", - "virtual", - "virus", - "visa", - "visit", - "visual", - "vital", - "vivid", - "vocal", - "voice", - "void", - "volcano", - "volume", - "vote", - "voyage", - "wage", - "wagon", - "wait", - "walk", - "wall", - "walnut", - "want", - "warfare", - "warm", - "warrior", - "wash", - "wasp", - "waste", - "water", - "wave", - "way", - "wealth", - "weapon", - "wear", - "weasel", - "weather", - "web", - "wedding", - "weekend", - "weird", - "welcome", - "west", - "wet", - "whale", - "what", - "wheat", - "wheel", - "when", - "where", - "whip", - "whisper", - "wide", - "width", - "wife", - "wild", - "will", - "win", - "window", - "wine", - "wing", - "wink", - "winner", - "winter", - "wire", - "wisdom", - "wise", - "wish", - "witness", - "wolf", - "woman", - "wonder", - "wood", - "wool", - "word", - "work", - "world", - "worry", - "worth", - "wrap", - "wreck", - "wrestle", - "wrist", - "write", - "wrong", - "yard", - "year", - "yellow", - "you", - "young", - "youth", - "zebra", - "zero", - "zone", - "zoo" - ]; -} diff --git a/cw_wownero/lib/mnemonics/english25.dart b/cw_wownero/lib/mnemonics/english25.dart deleted file mode 100644 index f20ead1477..0000000000 --- a/cw_wownero/lib/mnemonics/english25.dart +++ /dev/null @@ -1,1630 +0,0 @@ -class EnglishMnemonics25 { - static const words = [ - "abbey", - "abducts", - "ability", - "ablaze", - "abnormal", - "abort", - "abrasive", - "absorb", - "abyss", - "academy", - "aces", - "aching", - "acidic", - "acoustic", - "acquire", - "across", - "actress", - "acumen", - "adapt", - "addicted", - "adept", - "adhesive", - "adjust", - "adopt", - "adrenalin", - "adult", - "adventure", - "aerial", - "afar", - "affair", - "afield", - "afloat", - "afoot", - "afraid", - "after", - "against", - "agenda", - "aggravate", - "agile", - "aglow", - "agnostic", - "agony", - "agreed", - "ahead", - "aided", - "ailments", - "aimless", - "airport", - "aisle", - "ajar", - "akin", - "alarms", - "album", - "alchemy", - "alerts", - "algebra", - "alkaline", - "alley", - "almost", - "aloof", - "alpine", - "already", - "also", - "altitude", - "alumni", - "always", - "amaze", - "ambush", - "amended", - "amidst", - "ammo", - "amnesty", - "among", - "amply", - "amused", - "anchor", - "android", - "anecdote", - "angled", - "ankle", - "annoyed", - "answers", - "antics", - "anvil", - "anxiety", - "anybody", - "apart", - "apex", - "aphid", - "aplomb", - "apology", - "apply", - "apricot", - "aptitude", - "aquarium", - "arbitrary", - "archer", - "ardent", - "arena", - "argue", - "arises", - "army", - "around", - "arrow", - "arsenic", - "artistic", - "ascend", - "ashtray", - "aside", - "asked", - "asleep", - "aspire", - "assorted", - "asylum", - "athlete", - "atlas", - "atom", - "atrium", - "attire", - "auburn", - "auctions", - "audio", - "august", - "aunt", - "austere", - "autumn", - "avatar", - "avidly", - "avoid", - "awakened", - "awesome", - "awful", - "awkward", - "awning", - "awoken", - "axes", - "axis", - "axle", - "aztec", - "azure", - "baby", - "bacon", - "badge", - "baffles", - "bagpipe", - "bailed", - "bakery", - "balding", - "bamboo", - "banjo", - "baptism", - "basin", - "batch", - "bawled", - "bays", - "because", - "beer", - "befit", - "begun", - "behind", - "being", - "below", - "bemused", - "benches", - "berries", - "bested", - "betting", - "bevel", - "beware", - "beyond", - "bias", - "bicycle", - "bids", - "bifocals", - "biggest", - "bikini", - "bimonthly", - "binocular", - "biology", - "biplane", - "birth", - "biscuit", - "bite", - "biweekly", - "blender", - "blip", - "bluntly", - "boat", - "bobsled", - "bodies", - "bogeys", - "boil", - "boldly", - "bomb", - "border", - "boss", - "both", - "bounced", - "bovine", - "bowling", - "boxes", - "boyfriend", - "broken", - "brunt", - "bubble", - "buckets", - "budget", - "buffet", - "bugs", - "building", - "bulb", - "bumper", - "bunch", - "business", - "butter", - "buying", - "buzzer", - "bygones", - "byline", - "bypass", - "cabin", - "cactus", - "cadets", - "cafe", - "cage", - "cajun", - "cake", - "calamity", - "camp", - "candy", - "casket", - "catch", - "cause", - "cavernous", - "cease", - "cedar", - "ceiling", - "cell", - "cement", - "cent", - "certain", - "chlorine", - "chrome", - "cider", - "cigar", - "cinema", - "circle", - "cistern", - "citadel", - "civilian", - "claim", - "click", - "clue", - "coal", - "cobra", - "cocoa", - "code", - "coexist", - "coffee", - "cogs", - "cohesive", - "coils", - "colony", - "comb", - "cool", - "copy", - "corrode", - "costume", - "cottage", - "cousin", - "cowl", - "criminal", - "cube", - "cucumber", - "cuddled", - "cuffs", - "cuisine", - "cunning", - "cupcake", - "custom", - "cycling", - "cylinder", - "cynical", - "dabbing", - "dads", - "daft", - "dagger", - "daily", - "damp", - "dangerous", - "dapper", - "darted", - "dash", - "dating", - "dauntless", - "dawn", - "daytime", - "dazed", - "debut", - "decay", - "dedicated", - "deepest", - "deftly", - "degrees", - "dehydrate", - "deity", - "dejected", - "delayed", - "demonstrate", - "dented", - "deodorant", - "depth", - "desk", - "devoid", - "dewdrop", - "dexterity", - "dialect", - "dice", - "diet", - "different", - "digit", - "dilute", - "dime", - "dinner", - "diode", - "diplomat", - "directed", - "distance", - "ditch", - "divers", - "dizzy", - "doctor", - "dodge", - "does", - "dogs", - "doing", - "dolphin", - "domestic", - "donuts", - "doorway", - "dormant", - "dosage", - "dotted", - "double", - "dove", - "down", - "dozen", - "dreams", - "drinks", - "drowning", - "drunk", - "drying", - "dual", - "dubbed", - "duckling", - "dude", - "duets", - "duke", - "dullness", - "dummy", - "dunes", - "duplex", - "duration", - "dusted", - "duties", - "dwarf", - "dwelt", - "dwindling", - "dying", - "dynamite", - "dyslexic", - "each", - "eagle", - "earth", - "easy", - "eating", - "eavesdrop", - "eccentric", - "echo", - "eclipse", - "economics", - "ecstatic", - "eden", - "edgy", - "edited", - "educated", - "eels", - "efficient", - "eggs", - "egotistic", - "eight", - "either", - "eject", - "elapse", - "elbow", - "eldest", - "eleven", - "elite", - "elope", - "else", - "eluded", - "emails", - "ember", - "emerge", - "emit", - "emotion", - "empty", - "emulate", - "energy", - "enforce", - "enhanced", - "enigma", - "enjoy", - "enlist", - "enmity", - "enough", - "enraged", - "ensign", - "entrance", - "envy", - "epoxy", - "equip", - "erase", - "erected", - "erosion", - "error", - "eskimos", - "espionage", - "essential", - "estate", - "etched", - "eternal", - "ethics", - "etiquette", - "evaluate", - "evenings", - "evicted", - "evolved", - "examine", - "excess", - "exhale", - "exit", - "exotic", - "exquisite", - "extra", - "exult", - "fabrics", - "factual", - "fading", - "fainted", - "faked", - "fall", - "family", - "fancy", - "farming", - "fatal", - "faulty", - "fawns", - "faxed", - "fazed", - "feast", - "february", - "federal", - "feel", - "feline", - "females", - "fences", - "ferry", - "festival", - "fetches", - "fever", - "fewest", - "fiat", - "fibula", - "fictional", - "fidget", - "fierce", - "fifteen", - "fight", - "films", - "firm", - "fishing", - "fitting", - "five", - "fixate", - "fizzle", - "fleet", - "flippant", - "flying", - "foamy", - "focus", - "foes", - "foggy", - "foiled", - "folding", - "fonts", - "foolish", - "fossil", - "fountain", - "fowls", - "foxes", - "foyer", - "framed", - "friendly", - "frown", - "fruit", - "frying", - "fudge", - "fuel", - "fugitive", - "fully", - "fuming", - "fungal", - "furnished", - "fuselage", - "future", - "fuzzy", - "gables", - "gadget", - "gags", - "gained", - "galaxy", - "gambit", - "gang", - "gasp", - "gather", - "gauze", - "gave", - "gawk", - "gaze", - "gearbox", - "gecko", - "geek", - "gels", - "gemstone", - "general", - "geometry", - "germs", - "gesture", - "getting", - "geyser", - "ghetto", - "ghost", - "giant", - "giddy", - "gifts", - "gigantic", - "gills", - "gimmick", - "ginger", - "girth", - "giving", - "glass", - "gleeful", - "glide", - "gnaw", - "gnome", - "goat", - "goblet", - "godfather", - "goes", - "goggles", - "going", - "goldfish", - "gone", - "goodbye", - "gopher", - "gorilla", - "gossip", - "gotten", - "gourmet", - "governing", - "gown", - "greater", - "grunt", - "guarded", - "guest", - "guide", - "gulp", - "gumball", - "guru", - "gusts", - "gutter", - "guys", - "gymnast", - "gypsy", - "gyrate", - "habitat", - "hacksaw", - "haggled", - "hairy", - "hamburger", - "happens", - "hashing", - "hatchet", - "haunted", - "having", - "hawk", - "haystack", - "hazard", - "hectare", - "hedgehog", - "heels", - "hefty", - "height", - "hemlock", - "hence", - "heron", - "hesitate", - "hexagon", - "hickory", - "hiding", - "highway", - "hijack", - "hiker", - "hills", - "himself", - "hinder", - "hippo", - "hire", - "history", - "hitched", - "hive", - "hoax", - "hobby", - "hockey", - "hoisting", - "hold", - "honked", - "hookup", - "hope", - "hornet", - "hospital", - "hotel", - "hounded", - "hover", - "howls", - "hubcaps", - "huddle", - "huge", - "hull", - "humid", - "hunter", - "hurried", - "husband", - "huts", - "hybrid", - "hydrogen", - "hyper", - "iceberg", - "icing", - "icon", - "identity", - "idiom", - "idled", - "idols", - "igloo", - "ignore", - "iguana", - "illness", - "imagine", - "imbalance", - "imitate", - "impel", - "inactive", - "inbound", - "incur", - "industrial", - "inexact", - "inflamed", - "ingested", - "initiate", - "injury", - "inkling", - "inline", - "inmate", - "innocent", - "inorganic", - "input", - "inquest", - "inroads", - "insult", - "intended", - "inundate", - "invoke", - "inwardly", - "ionic", - "irate", - "iris", - "irony", - "irritate", - "island", - "isolated", - "issued", - "italics", - "itches", - "items", - "itinerary", - "itself", - "ivory", - "jabbed", - "jackets", - "jaded", - "jagged", - "jailed", - "jamming", - "january", - "jargon", - "jaunt", - "javelin", - "jaws", - "jazz", - "jeans", - "jeers", - "jellyfish", - "jeopardy", - "jerseys", - "jester", - "jetting", - "jewels", - "jigsaw", - "jingle", - "jittery", - "jive", - "jobs", - "jockey", - "jogger", - "joining", - "joking", - "jolted", - "jostle", - "journal", - "joyous", - "jubilee", - "judge", - "juggled", - "juicy", - "jukebox", - "july", - "jump", - "junk", - "jury", - "justice", - "juvenile", - "kangaroo", - "karate", - "keep", - "kennel", - "kept", - "kernels", - "kettle", - "keyboard", - "kickoff", - "kidneys", - "king", - "kiosk", - "kisses", - "kitchens", - "kiwi", - "knapsack", - "knee", - "knife", - "knowledge", - "knuckle", - "koala", - "laboratory", - "ladder", - "lagoon", - "lair", - "lakes", - "lamb", - "language", - "laptop", - "large", - "last", - "later", - "launching", - "lava", - "lawsuit", - "layout", - "lazy", - "lectures", - "ledge", - "leech", - "left", - "legion", - "leisure", - "lemon", - "lending", - "leopard", - "lesson", - "lettuce", - "lexicon", - "liar", - "library", - "licks", - "lids", - "lied", - "lifestyle", - "light", - "likewise", - "lilac", - "limits", - "linen", - "lion", - "lipstick", - "liquid", - "listen", - "lively", - "loaded", - "lobster", - "locker", - "lodge", - "lofty", - "logic", - "loincloth", - "long", - "looking", - "lopped", - "lordship", - "losing", - "lottery", - "loudly", - "love", - "lower", - "loyal", - "lucky", - "luggage", - "lukewarm", - "lullaby", - "lumber", - "lunar", - "lurk", - "lush", - "luxury", - "lymph", - "lynx", - "lyrics", - "macro", - "madness", - "magically", - "mailed", - "major", - "makeup", - "malady", - "mammal", - "maps", - "masterful", - "match", - "maul", - "maverick", - "maximum", - "mayor", - "maze", - "meant", - "mechanic", - "medicate", - "meeting", - "megabyte", - "melting", - "memoir", - "menu", - "merger", - "mesh", - "metro", - "mews", - "mice", - "midst", - "mighty", - "mime", - "mirror", - "misery", - "mittens", - "mixture", - "moat", - "mobile", - "mocked", - "mohawk", - "moisture", - "molten", - "moment", - "money", - "moon", - "mops", - "morsel", - "mostly", - "motherly", - "mouth", - "movement", - "mowing", - "much", - "muddy", - "muffin", - "mugged", - "mullet", - "mumble", - "mundane", - "muppet", - "mural", - "musical", - "muzzle", - "myriad", - "mystery", - "myth", - "nabbing", - "nagged", - "nail", - "names", - "nanny", - "napkin", - "narrate", - "nasty", - "natural", - "nautical", - "navy", - "nearby", - "necklace", - "needed", - "negative", - "neither", - "neon", - "nephew", - "nerves", - "nestle", - "network", - "neutral", - "never", - "newt", - "nexus", - "nibs", - "niche", - "niece", - "nifty", - "nightly", - "nimbly", - "nineteen", - "nirvana", - "nitrogen", - "nobody", - "nocturnal", - "nodes", - "noises", - "nomad", - "noodles", - "northern", - "nostril", - "noted", - "nouns", - "novelty", - "nowhere", - "nozzle", - "nuance", - "nucleus", - "nudged", - "nugget", - "nuisance", - "null", - "number", - "nuns", - "nurse", - "nutshell", - "nylon", - "oaks", - "oars", - "oasis", - "oatmeal", - "obedient", - "object", - "obliged", - "obnoxious", - "observant", - "obtains", - "obvious", - "occur", - "ocean", - "october", - "odds", - "odometer", - "offend", - "often", - "oilfield", - "ointment", - "okay", - "older", - "olive", - "olympics", - "omega", - "omission", - "omnibus", - "onboard", - "oncoming", - "oneself", - "ongoing", - "onion", - "online", - "onslaught", - "onto", - "onward", - "oozed", - "opacity", - "opened", - "opposite", - "optical", - "opus", - "orange", - "orbit", - "orchid", - "orders", - "organs", - "origin", - "ornament", - "orphans", - "oscar", - "ostrich", - "otherwise", - "otter", - "ouch", - "ought", - "ounce", - "ourselves", - "oust", - "outbreak", - "oval", - "oven", - "owed", - "owls", - "owner", - "oxidant", - "oxygen", - "oyster", - "ozone", - "pact", - "paddles", - "pager", - "pairing", - "palace", - "pamphlet", - "pancakes", - "paper", - "paradise", - "pastry", - "patio", - "pause", - "pavements", - "pawnshop", - "payment", - "peaches", - "pebbles", - "peculiar", - "pedantic", - "peeled", - "pegs", - "pelican", - "pencil", - "people", - "pepper", - "perfect", - "pests", - "petals", - "phase", - "pheasants", - "phone", - "phrases", - "physics", - "piano", - "picked", - "pierce", - "pigment", - "piloted", - "pimple", - "pinched", - "pioneer", - "pipeline", - "pirate", - "pistons", - "pitched", - "pivot", - "pixels", - "pizza", - "playful", - "pledge", - "pliers", - "plotting", - "plus", - "plywood", - "poaching", - "pockets", - "podcast", - "poetry", - "point", - "poker", - "polar", - "ponies", - "pool", - "popular", - "portents", - "possible", - "potato", - "pouch", - "poverty", - "powder", - "pram", - "present", - "pride", - "problems", - "pruned", - "prying", - "psychic", - "public", - "puck", - "puddle", - "puffin", - "pulp", - "pumpkins", - "punch", - "puppy", - "purged", - "push", - "putty", - "puzzled", - "pylons", - "pyramid", - "python", - "queen", - "quick", - "quote", - "rabbits", - "racetrack", - "radar", - "rafts", - "rage", - "railway", - "raking", - "rally", - "ramped", - "randomly", - "rapid", - "rarest", - "rash", - "rated", - "ravine", - "rays", - "razor", - "react", - "rebel", - "recipe", - "reduce", - "reef", - "refer", - "regular", - "reheat", - "reinvest", - "rejoices", - "rekindle", - "relic", - "remedy", - "renting", - "reorder", - "repent", - "request", - "reruns", - "rest", - "return", - "reunion", - "revamp", - "rewind", - "rhino", - "rhythm", - "ribbon", - "richly", - "ridges", - "rift", - "rigid", - "rims", - "ringing", - "riots", - "ripped", - "rising", - "ritual", - "river", - "roared", - "robot", - "rockets", - "rodent", - "rogue", - "roles", - "romance", - "roomy", - "roped", - "roster", - "rotate", - "rounded", - "rover", - "rowboat", - "royal", - "ruby", - "rudely", - "ruffled", - "rugged", - "ruined", - "ruling", - "rumble", - "runway", - "rural", - "rustled", - "ruthless", - "sabotage", - "sack", - "sadness", - "safety", - "saga", - "sailor", - "sake", - "salads", - "sample", - "sanity", - "sapling", - "sarcasm", - "sash", - "satin", - "saucepan", - "saved", - "sawmill", - "saxophone", - "sayings", - "scamper", - "scenic", - "school", - "science", - "scoop", - "scrub", - "scuba", - "seasons", - "second", - "sedan", - "seeded", - "segments", - "seismic", - "selfish", - "semifinal", - "sensible", - "september", - "sequence", - "serving", - "session", - "setup", - "seventh", - "sewage", - "shackles", - "shelter", - "shipped", - "shocking", - "shrugged", - "shuffled", - "shyness", - "siblings", - "sickness", - "sidekick", - "sieve", - "sifting", - "sighting", - "silk", - "simplest", - "sincerely", - "sipped", - "siren", - "situated", - "sixteen", - "sizes", - "skater", - "skew", - "skirting", - "skulls", - "skydive", - "slackens", - "sleepless", - "slid", - "slower", - "slug", - "smash", - "smelting", - "smidgen", - "smog", - "smuggled", - "snake", - "sneeze", - "sniff", - "snout", - "snug", - "soapy", - "sober", - "soccer", - "soda", - "software", - "soggy", - "soil", - "solved", - "somewhere", - "sonic", - "soothe", - "soprano", - "sorry", - "southern", - "sovereign", - "sowed", - "soya", - "space", - "speedy", - "sphere", - "spiders", - "splendid", - "spout", - "sprig", - "spud", - "spying", - "square", - "stacking", - "stellar", - "stick", - "stockpile", - "strained", - "stunning", - "stylishly", - "subtly", - "succeed", - "suddenly", - "suede", - "suffice", - "sugar", - "suitcase", - "sulking", - "summon", - "sunken", - "superior", - "surfer", - "sushi", - "suture", - "swagger", - "swept", - "swiftly", - "sword", - "swung", - "syllabus", - "symptoms", - "syndrome", - "syringe", - "system", - "taboo", - "tacit", - "tadpoles", - "tagged", - "tail", - "taken", - "talent", - "tamper", - "tanks", - "tapestry", - "tarnished", - "tasked", - "tattoo", - "taunts", - "tavern", - "tawny", - "taxi", - "teardrop", - "technical", - "tedious", - "teeming", - "tell", - "template", - "tender", - "tepid", - "tequila", - "terminal", - "testing", - "tether", - "textbook", - "thaw", - "theatrics", - "thirsty", - "thorn", - "threaten", - "thumbs", - "thwart", - "ticket", - "tidy", - "tiers", - "tiger", - "tilt", - "timber", - "tinted", - "tipsy", - "tirade", - "tissue", - "titans", - "toaster", - "tobacco", - "today", - "toenail", - "toffee", - "together", - "toilet", - "token", - "tolerant", - "tomorrow", - "tonic", - "toolbox", - "topic", - "torch", - "tossed", - "total", - "touchy", - "towel", - "toxic", - "toyed", - "trash", - "trendy", - "tribal", - "trolling", - "truth", - "trying", - "tsunami", - "tubes", - "tucks", - "tudor", - "tuesday", - "tufts", - "tugs", - "tuition", - "tulips", - "tumbling", - "tunnel", - "turnip", - "tusks", - "tutor", - "tuxedo", - "twang", - "tweezers", - "twice", - "twofold", - "tycoon", - "typist", - "tyrant", - "ugly", - "ulcers", - "ultimate", - "umbrella", - "umpire", - "unafraid", - "unbending", - "uncle", - "under", - "uneven", - "unfit", - "ungainly", - "unhappy", - "union", - "unjustly", - "unknown", - "unlikely", - "unmask", - "unnoticed", - "unopened", - "unplugs", - "unquoted", - "unrest", - "unsafe", - "until", - "unusual", - "unveil", - "unwind", - "unzip", - "upbeat", - "upcoming", - "update", - "upgrade", - "uphill", - "upkeep", - "upload", - "upon", - "upper", - "upright", - "upstairs", - "uptight", - "upwards", - "urban", - "urchins", - "urgent", - "usage", - "useful", - "usher", - "using", - "usual", - "utensils", - "utility", - "utmost", - "utopia", - "uttered", - "vacation", - "vague", - "vain", - "value", - "vampire", - "vane", - "vapidly", - "vary", - "vastness", - "vats", - "vaults", - "vector", - "veered", - "vegan", - "vehicle", - "vein", - "velvet", - "venomous", - "verification", - "vessel", - "veteran", - "vexed", - "vials", - "vibrate", - "victim", - "video", - "viewpoint", - "vigilant", - "viking", - "village", - "vinegar", - "violin", - "vipers", - "virtual", - "visited", - "vitals", - "vivid", - "vixen", - "vocal", - "vogue", - "voice", - "volcano", - "vortex", - "voted", - "voucher", - "vowels", - "voyage", - "vulture", - "wade", - "waffle", - "wagtail", - "waist", - "waking", - "wallets", - "wanted", - "warped", - "washing", - "water", - "waveform", - "waxing", - "wayside", - "weavers", - "website", - "wedge", - "weekday", - "weird", - "welders", - "went", - "wept", - "were", - "western", - "wetsuit", - "whale", - "when", - "whipped", - "whole", - "wickets", - "width", - "wield", - "wife", - "wiggle", - "wildly", - "winter", - "wipeout", - "wiring", - "wise", - "withdrawn", - "wives", - "wizard", - "wobbly", - "woes", - "woken", - "wolf", - "womanly", - "wonders", - "woozy", - "worry", - "wounded", - "woven", - "wrap", - "wrist", - "wrong", - "yacht", - "yahoo", - "yanks", - "yard", - "yawning", - "yearbook", - "yellow", - "yesterday", - "yeti", - "yields", - "yodel", - "yoga", - "younger", - "yoyo", - "zapped", - "zeal", - "zebra", - "zero", - "zesty", - "zigzags", - "zinger", - "zippers", - "zodiac", - "zombie", - "zones", - "zoom" - ]; -} diff --git a/cw_wownero/lib/pending_wownero_transaction.dart b/cw_wownero/lib/pending_wownero_transaction.dart deleted file mode 100644 index cf66dc6179..0000000000 --- a/cw_wownero/lib/pending_wownero_transaction.dart +++ /dev/null @@ -1,50 +0,0 @@ -import 'package:cw_core/amount_converter.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_wownero/api/structs/pending_transaction.dart'; -import 'package:cw_wownero/api/transaction_history.dart' - as wownero_transaction_history; - -class DoubleSpendException implements Exception { - DoubleSpendException(); - - @override - String toString() => - 'This transaction cannot be committed. This can be due to many reasons including the wallet not being synced, there is not enough WOW in your available balance, or previous transactions are not yet fully processed.'; -} - -class PendingWowneroTransaction with PendingTransaction { - PendingWowneroTransaction(this.pendingTransactionDescription); - - final PendingTransactionDescription pendingTransactionDescription; - - @override - String get id => pendingTransactionDescription.hash!; - - @override - String get amountFormatted => AmountConverter.amountIntToString( - CryptoCurrency.wow, pendingTransactionDescription.amount!)!; - - @override - String get feeFormatted => AmountConverter.amountIntToString( - CryptoCurrency.wow, pendingTransactionDescription.fee!)!; - - @override - Future commit() async { - try { - wownero_transaction_history.commitTransactionFromPointerAddress( - address: pendingTransactionDescription.pointerAddress!); - } catch (e) { - final message = e.toString(); - - if (message.contains('Reason: double spend')) { - throw DoubleSpendException(); - } - - rethrow; - } - } - - @override - String get hex => throw UnimplementedError(); -} diff --git a/cw_wownero/lib/wownero_account_list.dart b/cw_wownero/lib/wownero_account_list.dart deleted file mode 100644 index 558570722b..0000000000 --- a/cw_wownero/lib/wownero_account_list.dart +++ /dev/null @@ -1,78 +0,0 @@ -import 'package:mobx/mobx.dart'; -import 'package:cw_core/account.dart'; -import 'package:cw_wownero/api/account_list.dart' as account_list; - -part 'wownero_account_list.g.dart'; - -class WowneroAccountList = WowneroAccountListBase with _$WowneroAccountList; - -abstract class WowneroAccountListBase with Store { - WowneroAccountListBase() - : accounts = ObservableList(), - _isRefreshing = false, - _isUpdating = false { - refresh(); - print(account_list.accountSizeNative()); - } - - @observable - ObservableList accounts; - bool _isRefreshing; - bool _isUpdating; - - void update() async { - if (_isUpdating) { - return; - } - - try { - _isUpdating = true; - refresh(); - final accounts = getAll(); - - if (accounts.isNotEmpty) { - this.accounts.clear(); - this.accounts.addAll(accounts); - } - - _isUpdating = false; - } catch (e) { - _isUpdating = false; - rethrow; - } - } - - List getAll() => account_list - .getAllAccount() - .map((accountRow) => Account( - id: accountRow.getId(), - label: accountRow.getLabel())) - .toList(); - - Future addAccount({String? label}) async { - await account_list.addAccount(label: label); - update(); - } - - Future setLabelAccount({int? accountIndex, String? label}) async { - await account_list.setLabelForAccount( - accountIndex: accountIndex, label: label); - update(); - } - - void refresh() { - if (_isRefreshing) { - return; - } - - try { - _isRefreshing = true; - account_list.refreshAccounts(); - _isRefreshing = false; - } catch (e) { - _isRefreshing = false; - print(e); - rethrow; - } - } -} diff --git a/cw_wownero/lib/wownero_account_list.g.dart b/cw_wownero/lib/wownero_account_list.g.dart deleted file mode 100644 index 4b6b5c9942..0000000000 --- a/cw_wownero/lib/wownero_account_list.g.dart +++ /dev/null @@ -1,34 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wownero_account_list.dart'; - -// ************************************************************************** -// StoreGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers - -mixin _$WowneroAccountList on WowneroAccountListBase, Store { - late final _$accountsAtom = - Atom(name: 'WowneroAccountListBase.accounts', context: context); - - @override - ObservableList get accounts { - _$accountsAtom.reportRead(); - return super.accounts; - } - - @override - set accounts(ObservableList value) { - _$accountsAtom.reportWrite(value, super.accounts, () { - super.accounts = value; - }); - } - - @override - String toString() { - return ''' -accounts: ${accounts} - '''; - } -} diff --git a/cw_wownero/lib/wownero_amount_format.dart b/cw_wownero/lib/wownero_amount_format.dart deleted file mode 100644 index 9178128b47..0000000000 --- a/cw_wownero/lib/wownero_amount_format.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:intl/intl.dart'; -import 'package:cw_core/crypto_amount_format.dart'; - -const wowneroAmountLength = 11; -const wowneroAmountDivider = 100000000000; -final wowneroAmountFormat = NumberFormat() - ..maximumFractionDigits = wowneroAmountLength - ..minimumFractionDigits = 1; - -String wowneroAmountToString({required int amount}) => wowneroAmountFormat - .format(cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider)) - .replaceAll(',', ''); - -double wowneroAmountToDouble({required int amount}) => - cryptoAmountToDouble(amount: amount, divider: wowneroAmountDivider); - -int wowneroParseAmount({required String amount}) => - (double.parse(amount) * wowneroAmountDivider).toInt(); diff --git a/cw_wownero/lib/wownero_balance.dart b/cw_wownero/lib/wownero_balance.dart deleted file mode 100644 index fc4618d6ae..0000000000 --- a/cw_wownero/lib/wownero_balance.dart +++ /dev/null @@ -1,30 +0,0 @@ -import 'package:cw_core/balance.dart'; -import 'package:flutter/foundation.dart'; -import 'package:cw_wownero/wownero_amount_format.dart'; - -class WowneroBalance extends Balance { - WowneroBalance({required this.fullBalance, required this.unlockedBalance}) - : formattedFullBalance = wowneroAmountToString(amount: fullBalance), - formattedUnlockedBalance = - wowneroAmountToString(amount: unlockedBalance), - super(unlockedBalance, fullBalance); - - WowneroBalance.fromString( - {required this.formattedFullBalance, - required this.formattedUnlockedBalance}) - : fullBalance = wowneroParseAmount(amount: formattedFullBalance), - unlockedBalance = wowneroParseAmount(amount: formattedUnlockedBalance), - super(wowneroParseAmount(amount: formattedUnlockedBalance), - wowneroParseAmount(amount: formattedFullBalance)); - - final int fullBalance; - final int unlockedBalance; - final String formattedFullBalance; - final String formattedUnlockedBalance; - - @override - String get formattedAvailableBalance => formattedUnlockedBalance; - - @override - String get formattedAdditionalBalance => formattedFullBalance; -} diff --git a/cw_wownero/lib/wownero_subaddress_list.dart b/cw_wownero/lib/wownero_subaddress_list.dart deleted file mode 100644 index 4d2ad89253..0000000000 --- a/cw_wownero/lib/wownero_subaddress_list.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:cw_wownero/api/structs/subaddress_row.dart'; -import 'package:flutter/services.dart'; -import 'package:mobx/mobx.dart'; -import 'package:cw_wownero/api/subaddress_list.dart' as subaddress_list; -import 'package:cw_core/subaddress.dart'; - -part 'wownero_subaddress_list.g.dart'; - -class WowneroSubaddressList = WowneroSubaddressListBase - with _$WowneroSubaddressList; - -abstract class WowneroSubaddressListBase with Store { - WowneroSubaddressListBase() { - _isRefreshing = false; - _isUpdating = false; - subaddresses = ObservableList(); - } - - @observable - ObservableList? subaddresses; - - late bool _isRefreshing; - late bool _isUpdating; - - void update({int? accountIndex}) { - if (_isUpdating) { - return; - } - - try { - _isUpdating = true; - refresh(accountIndex: accountIndex); - subaddresses!.clear(); - subaddresses!.addAll(getAll()); - _isUpdating = false; - } catch (e) { - _isUpdating = false; - rethrow; - } - } - - List getAll() { - var subaddresses = subaddress_list.getAllSubaddresses(); - - if (subaddresses.length > 2) { - final primary = subaddresses.first; - final rest = subaddresses.sublist(1).reversed; - subaddresses = [primary] + rest.toList(); - } - - return subaddresses - .map((subaddressRow) => Subaddress( - id: subaddressRow.getId(), - address: subaddressRow.getAddress(), - label: subaddressRow.getId() == 0 && - subaddressRow.getLabel().toLowerCase() == 'Primary account'.toLowerCase() - ? 'Primary address' - : subaddressRow.getLabel())) - .toList(); - } - - Future addSubaddress({int? accountIndex, String? label}) async { - await subaddress_list.addSubaddress( - accountIndex: accountIndex, label: label); - update(accountIndex: accountIndex); - } - - Future setLabelSubaddress( - {int? accountIndex, int? addressIndex, String? label}) async { - await subaddress_list.setLabelForSubaddress( - accountIndex: accountIndex, addressIndex: addressIndex, label: label); - update(accountIndex: accountIndex); - } - - void refresh({int? accountIndex}) { - if (_isRefreshing) { - return; - } - - try { - _isRefreshing = true; - subaddress_list.refreshSubaddresses(accountIndex: accountIndex); - _isRefreshing = false; - } on PlatformException catch (e) { - _isRefreshing = false; - print(e); - rethrow; - } - } -} diff --git a/cw_wownero/lib/wownero_subaddress_list.g.dart b/cw_wownero/lib/wownero_subaddress_list.g.dart deleted file mode 100644 index a524049918..0000000000 --- a/cw_wownero/lib/wownero_subaddress_list.g.dart +++ /dev/null @@ -1,34 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wownero_subaddress_list.dart'; - -// ************************************************************************** -// StoreGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers - -mixin _$WowneroSubaddressList on WowneroSubaddressListBase, Store { - late final _$subaddressesAtom = - Atom(name: 'WowneroSubaddressListBase.subaddresses', context: context); - - @override - ObservableList? get subaddresses { - _$subaddressesAtom.reportRead(); - return super.subaddresses; - } - - @override - set subaddresses(ObservableList? value) { - _$subaddressesAtom.reportWrite(value, super.subaddresses, () { - super.subaddresses = value; - }); - } - - @override - String toString() { - return ''' -subaddresses: ${subaddresses} - '''; - } -} diff --git a/cw_wownero/lib/wownero_transaction_creation_credentials.dart b/cw_wownero/lib/wownero_transaction_creation_credentials.dart deleted file mode 100644 index 5aa9f62698..0000000000 --- a/cw_wownero/lib/wownero_transaction_creation_credentials.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:cw_core/monero_transaction_priority.dart'; -import 'package:cw_core/output_info.dart'; - -class WowneroTransactionCreationCredentials { - WowneroTransactionCreationCredentials({this.outputs, this.priority}); - - final List? outputs; - final MoneroTransactionPriority? priority; -} diff --git a/cw_wownero/lib/wownero_transaction_creation_exception.dart b/cw_wownero/lib/wownero_transaction_creation_exception.dart deleted file mode 100644 index 3b24be87b1..0000000000 --- a/cw_wownero/lib/wownero_transaction_creation_exception.dart +++ /dev/null @@ -1,8 +0,0 @@ -class WowneroTransactionCreationException implements Exception { - WowneroTransactionCreationException(this.message); - - final String message; - - @override - String toString() => message; -} \ No newline at end of file diff --git a/cw_wownero/lib/wownero_transaction_history.dart b/cw_wownero/lib/wownero_transaction_history.dart deleted file mode 100644 index 24900f434b..0000000000 --- a/cw_wownero/lib/wownero_transaction_history.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'dart:core'; -import 'package:mobx/mobx.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_wownero/wownero_transaction_info.dart'; - -part 'wownero_transaction_history.g.dart'; - -class WowneroTransactionHistory = WowneroTransactionHistoryBase - with _$WowneroTransactionHistory; - -abstract class WowneroTransactionHistoryBase - extends TransactionHistoryBase with Store { - WowneroTransactionHistoryBase() { - transactions = ObservableMap(); - } - - @override - Future save() async {} - - @override - void addOne(WowneroTransactionInfo transaction) => - transactions![transaction.id] = transaction; - - @override - void addMany(Map transactions) => - this.transactions!.addAll(transactions); -} diff --git a/cw_wownero/lib/wownero_transaction_history.g.dart b/cw_wownero/lib/wownero_transaction_history.g.dart deleted file mode 100644 index fda8eaa501..0000000000 --- a/cw_wownero/lib/wownero_transaction_history.g.dart +++ /dev/null @@ -1,18 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wownero_transaction_history.dart'; - -// ************************************************************************** -// StoreGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers - -mixin _$WowneroTransactionHistory on WowneroTransactionHistoryBase, Store { - @override - String toString() { - return ''' - - '''; - } -} diff --git a/cw_wownero/lib/wownero_transaction_info.dart b/cw_wownero/lib/wownero_transaction_info.dart deleted file mode 100644 index 6881a9f0be..0000000000 --- a/cw_wownero/lib/wownero_transaction_info.dart +++ /dev/null @@ -1,90 +0,0 @@ -import 'package:cw_core/format_amount.dart'; -import 'package:cw_core/parseBoolFromString.dart'; -import 'package:cw_core/transaction_direction.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_wownero/api/structs/transaction_info_row.dart'; -import 'package:cw_wownero/api/transaction_history.dart'; -import 'package:cw_wownero/wownero_amount_format.dart'; - -class WowneroTransactionInfo extends TransactionInfo { - WowneroTransactionInfo( - this.id, - this.height, - this.direction, - this.date, - this.isPending, - this.amount, - this.accountIndex, - this.addressIndex, - this.fee); - - WowneroTransactionInfo.fromMap(Map map) - : id = (map['hash'] ?? '') as String, - height = (map['height'] ?? 0) as int, - direction = - parseTransactionDirectionFromNumber(map['direction'] as String) ?? - TransactionDirection.incoming, - date = DateTime.fromMillisecondsSinceEpoch( - (int.parse(map['timestamp'] as String)) * 1000), - isPending = parseBoolFromString(map['isPending'] as String), - amount = map['amount'] as int?, - accountIndex = int.parse(map['accountIndex'] as String), - addressIndex = map['addressIndex'] as int?, - key = getTxKey((map['hash'] ?? '') as String), - fee = map['fee'] as int? ?? 0 { - additionalInfo = { - 'key': key, - 'accountIndex': accountIndex, - 'addressIndex': addressIndex - }; - confirmations = map['confirmations'] as int?; - } - - WowneroTransactionInfo.fromRow(TransactionInfoRow row) - : id = row.getHash(), - height = row.blockHeight, - direction = parseTransactionDirectionFromInt(row.direction) ?? - TransactionDirection.incoming, - date = DateTime.fromMillisecondsSinceEpoch(row.getDatetime() * 1000), - isPending = row.isPending != 0, - amount = row.getAmount(), - accountIndex = row.subaddrAccount, - addressIndex = row.subaddrIndex, - key = getTxKey(row.getHash()), - fee = row.fee { - additionalInfo = { - 'key': key, - 'accountIndex': accountIndex, - 'addressIndex': addressIndex - }; - confirmations = row.confirmations; - } - - final String id; - final int? height; - final TransactionDirection direction; - final DateTime date; - final int? accountIndex; - final bool isPending; - final int? amount; - final int? fee; - final int? addressIndex; - String? recipientAddress; - String? key; - - String? _fiatAmount; - - @override - String amountFormatted() => - '${formatAmount(wowneroAmountToString(amount: amount!))} WOW'; - - @override - String fiatAmount() => _fiatAmount ?? ''; - - @override - void changeFiatAmount(String amount) => _fiatAmount = formatAmount(amount); - - @override - String feeFormatted() => - '${formatAmount(wowneroAmountToString(amount: fee!))} WOW'; -} diff --git a/cw_wownero/lib/wownero_wallet.dart b/cw_wownero/lib/wownero_wallet.dart deleted file mode 100644 index 4f85124d10..0000000000 --- a/cw_wownero/lib/wownero_wallet.dart +++ /dev/null @@ -1,451 +0,0 @@ -import 'dart:async'; - -import 'package:cw_core/account.dart'; -import 'package:cw_core/crypto_currency.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; -import 'package:cw_core/monero_wallet_keys.dart'; -import 'package:cw_core/monero_wallet_utils.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/sync_status.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_wownero/api/structs/pending_transaction.dart'; -import 'package:cw_wownero/api/transaction_history.dart' - as wownero_transaction_history; -import 'package:cw_wownero/api/transaction_history.dart' as transaction_history; -import 'package:cw_wownero/api/wallet.dart'; -import 'package:cw_wownero/api/wallet.dart' as wownero_wallet; -import 'package:cw_wownero/api/wownero_output.dart'; -import 'package:cw_wownero/pending_wownero_transaction.dart'; -import 'package:cw_wownero/wownero_amount_format.dart'; -import 'package:cw_wownero/wownero_balance.dart'; -import 'package:cw_wownero/wownero_transaction_creation_credentials.dart'; -import 'package:cw_wownero/wownero_transaction_creation_exception.dart'; -import 'package:cw_wownero/wownero_transaction_history.dart'; -import 'package:cw_wownero/wownero_transaction_info.dart'; -import 'package:cw_wownero/wownero_wallet_addresses.dart'; -import 'package:mobx/mobx.dart'; - -part 'wownero_wallet.g.dart'; - -const wowneroBlockSize = 1000; - -class WowneroWallet = WowneroWalletBase with _$WowneroWallet; - -abstract class WowneroWalletBase extends WalletBase with Store { - WowneroWalletBase({required WalletInfo walletInfo}) : super(walletInfo) { - transactionHistory = WowneroTransactionHistory(); - balance = ObservableMap.of({ - CryptoCurrency.wow: WowneroBalance( - fullBalance: wownero_wallet.getFullBalance(accountIndex: 0), - unlockedBalance: wownero_wallet.getFullBalance(accountIndex: 0)) - }); - _isTransactionUpdating = false; - _hasSyncAfterStartup = false; - walletAddresses = WowneroWalletAddresses(walletInfo); - _onAccountChangeReaction = - reaction((_) => walletAddresses.account, (Account? account) { - balance = ObservableMap.of(< - CryptoCurrency?, WowneroBalance>{ - currency: WowneroBalance( - fullBalance: - wownero_wallet.getFullBalance(accountIndex: account!.id), - unlockedBalance: - wownero_wallet.getUnlockedBalance(accountIndex: account.id)) - }); - walletAddresses.updateSubaddressList(accountIndex: account.id); - }); - } - - static const int _autoSaveInterval = 30; - - @override - late WowneroWalletAddresses walletAddresses; - - @override - @observable - SyncStatus? syncStatus; - - @override - @observable - ObservableMap? balance; - - @override - String get seed => wownero_wallet.getSeed(); - - @override - MoneroWalletKeys get keys => MoneroWalletKeys( - privateSpendKey: wownero_wallet.getSecretSpendKey(), - privateViewKey: wownero_wallet.getSecretViewKey(), - publicSpendKey: wownero_wallet.getPublicSpendKey(), - publicViewKey: wownero_wallet.getPublicViewKey()); - - SyncListener? _listener; - ReactionDisposer? _onAccountChangeReaction; - late bool _isTransactionUpdating; - late bool _hasSyncAfterStartup; - Timer? _autoSaveTimer; - - void Function({required int height, required int blocksLeft})? onNewBlock; - void Function()? onNewTransaction; - void Function()? syncStatusChanged; - - Future init() async { - await walletAddresses.init(); - balance = ObservableMap.of(< - CryptoCurrency?, WowneroBalance>{ - currency: WowneroBalance( - fullBalance: wownero_wallet.getFullBalance( - accountIndex: walletAddresses.account!.id), - unlockedBalance: wownero_wallet.getUnlockedBalance( - accountIndex: walletAddresses.account!.id)) - }); - _setListeners(); - await updateTransactions(); - - if (walletInfo.isRecovery!) { - wownero_wallet.setRecoveringFromSeed(isRecovery: walletInfo.isRecovery!); - - if (wownero_wallet.getCurrentHeight() <= 1) { - wownero_wallet.setRefreshFromBlockHeight( - height: walletInfo.restoreHeight); - } - } - - // _autoSaveTimer = Timer.periodic( - // Duration(seconds: _autoSaveInterval), (_) async => await save()); - } - - @override - void close() { - _listener?.stop(); - _onAccountChangeReaction?.reaction?.dispose(); - _autoSaveTimer?.cancel(); - } - - @override - Future connectToNode({required Node node}) async { - try { - syncStatus = ConnectingSyncStatus(); - syncStatusChanged?.call(); - await wownero_wallet.setupNode( - address: node.uri.toString(), - login: node.login, - password: node.password, - useSSL: node.isSSL, - isLightWallet: false); // FIXME: hardcoded value - - wownero_wallet.setTrustedDaemon(node.trusted); - syncStatus = ConnectedSyncStatus(); - syncStatusChanged?.call(); - } catch (e) { - syncStatus = FailedSyncStatus(); - syncStatusChanged?.call(); - print(e); - } - } - - @override - Future startSync() async { - try { - _setInitialHeight(); - } catch (_) {} - - try { - syncStatus = StartingSyncStatus(); - wownero_wallet.startRefresh(); - _setListeners(); - _listener?.start(); - syncStatusChanged?.call(); - } catch (e) { - syncStatus = FailedSyncStatus(); - syncStatusChanged?.call(); - print(e); - rethrow; - } - } - - @override - Future createTransaction(Object credentials) async { - final _credentials = credentials as WowneroTransactionCreationCredentials; - final outputs = _credentials.outputs!; - final hasMultiDestination = outputs.length > 1; - final unlockedBalance = wownero_wallet.getUnlockedBalance( - accountIndex: walletAddresses.account!.id); - - PendingTransactionDescription pendingTransactionDescription; - - if (!(syncStatus is SyncedSyncStatus)) { - throw WowneroTransactionCreationException('The wallet is not synced.'); - } - - if (hasMultiDestination) { - if (outputs - .any((item) => item.sendAll! || item.formattedCryptoAmount! <= 0)) { - throw WowneroTransactionCreationException( - 'Wrong balance. Not enough WOW on your balance.'); - } - - final int totalAmount = - outputs.fold(0, (acc, value) => acc + value.formattedCryptoAmount!); - - if (unlockedBalance < totalAmount) { - throw WowneroTransactionCreationException( - 'Wrong balance. Not enough WOW on your balance.'); - } - - final wowneroOutputs = outputs.map((output) { - final outputAddress = - output.isParsedAddress! ? output.extractedAddress : output.address; - - return WowneroOutput( - address: outputAddress, - amount: output.cryptoAmount!.replaceAll(',', '.')); - }).toList(); - - pendingTransactionDescription = - await transaction_history.createTransactionMultDest( - outputs: wowneroOutputs, - priorityRaw: _credentials.priority!.serialize(), - accountIndex: walletAddresses.account!.id); - } else { - final output = outputs.first; - final address = - output.isParsedAddress! ? output.extractedAddress : output.address; - final amount = - output.sendAll! ? null : output.cryptoAmount!.replaceAll(',', '.'); - final formattedAmount = - output.sendAll! ? null : output.formattedCryptoAmount; - - if ((formattedAmount != null && unlockedBalance < formattedAmount) || - (formattedAmount == null && unlockedBalance <= 0)) { - final formattedBalance = wowneroAmountToString(amount: unlockedBalance); - - throw WowneroTransactionCreationException( - 'Incorrect unlocked balance. Unlocked: $formattedBalance. Transaction amount: ${output.cryptoAmount}.'); - } - - pendingTransactionDescription = - await transaction_history.createTransaction( - address: address, - amount: amount, - priorityRaw: _credentials.priority!.serialize(), - accountIndex: walletAddresses.account!.id); - } - - return PendingWowneroTransaction(pendingTransactionDescription); - } - - @override - int calculateEstimatedFee(TransactionPriority priority, int amount) { - // FIXME: hardcoded value; - - if (priority is MoneroTransactionPriority) { - switch (priority) { - case MoneroTransactionPriority.slow: - return 24590000; - case MoneroTransactionPriority.regular: - return 123050000; - case MoneroTransactionPriority.medium: - return 245029999; - case MoneroTransactionPriority.fast: - return 614530000; - case MoneroTransactionPriority.fastest: - return 26021600000; - } - } - - return 0; - } - - @override - Future save({bool prioritySave = false}) async { - print("save is called"); - await walletAddresses.updateAddressesInBox(); - await backupWalletFiles(name!); - return await wownero_wallet.store(prioritySave: prioritySave); - } - - @override - Future changePassword(String password) async { - wownero_wallet.setPasswordSync(password); - } - - Future getNodeHeight() async => wownero_wallet.getNodeHeight(); - - int getSeedHeight(String seed) => wownero_wallet.getSeedHeightSync(seed); - - Future isConnected() async => wownero_wallet.isConnected(); - - Future setAsRecovered() async { - walletInfo.isRecovery = false; - await walletInfo.save(); - } - - @override - Future rescan({int? height}) async { - walletInfo.restoreHeight = height; - walletInfo.isRecovery = true; - wownero_wallet.setRefreshFromBlockHeight(height: height); - wownero_wallet.rescanBlockchainAsync(); - await startSync(); - _askForUpdateBalance(); - walletAddresses.accountList.update(); - await _askForUpdateTransactionHistory(); - await save(); - await walletInfo.save(); - } - - String getTransactionAddress(int accountIndex, int addressIndex) => - wownero_wallet.getAddress( - accountIndex: accountIndex, addressIndex: addressIndex); - - @override - Future> fetchTransactions() async { - wownero_transaction_history.refreshTransactions(); - return _getAllTransactions(null).fold>( - {}, - (Map acc, WowneroTransactionInfo tx) { - acc[tx.id] = tx; - return acc; - }); - } - - Future updateTransactions() async { - try { - if (_isTransactionUpdating) { - return; - } - - _isTransactionUpdating = true; - final transactions = await fetchTransactions(); - transactionHistory!.addMany(transactions); - await transactionHistory!.save(); - _isTransactionUpdating = false; - } catch (e) { - print(e); - _isTransactionUpdating = false; - } - } - - String getSubaddressLabel(int accountIndex, int addressIndex) { - return wownero_wallet.getSubaddressLabel(accountIndex, addressIndex); - } - - bool validateAddress(String address) { - return wownero_wallet.validateAddress(address); - } - - List _getAllTransactions(dynamic _) => - wownero_transaction_history - .getAllTransations() - .map((row) => WowneroTransactionInfo.fromRow(row)) - .toList(); - - void _setListeners() { - _listener?.stop(); - _listener = wownero_wallet.setListeners(_onNewBlock, _onNewTransaction); - } - - void _setInitialHeight() { - if (walletInfo.isRecovery!) { - return; - } - - final currentHeight = getCurrentHeight(); - - if (currentHeight <= 1) { - final height = _getHeightByDate(walletInfo.date); - wownero_wallet.setRecoveringFromSeed(isRecovery: true); - wownero_wallet.setRefreshFromBlockHeight(height: height); - } - } - - int _getHeightDistance(DateTime date) { - final distance = - DateTime.now().millisecondsSinceEpoch - date.millisecondsSinceEpoch; - final distance_sec = distance / 1000; - final daysTmp = (distance_sec / 86400).round(); - final days = daysTmp < 1 ? 1 : daysTmp; - - return days * 2000; - } - - int _getHeightByDate(DateTime date) { - final nodeHeight = wownero_wallet.getNodeHeightSync(); - final heightDistance = _getHeightDistance(date); - - if (nodeHeight <= 0) { - return 0; - } - - return nodeHeight - heightDistance; - } - - void _askForUpdateBalance() { - final unlockedBalance = _getUnlockedBalance(); - final fullBalance = _getFullBalance(); - - if (balance![currency]!.fullBalance != fullBalance || - balance![currency]!.unlockedBalance != unlockedBalance) { - balance![currency] = WowneroBalance( - fullBalance: fullBalance, unlockedBalance: unlockedBalance); - } - } - - Future _askForUpdateTransactionHistory() async => - await updateTransactions(); - - int _getFullBalance() => - wownero_wallet.getFullBalance(accountIndex: walletAddresses.account!.id); - - int _getUnlockedBalance() => wownero_wallet.getUnlockedBalance( - accountIndex: walletAddresses.account!.id); - - void _onNewBlock(int height, int blocksLeft, double ptc) async { - try { - if (walletInfo.isRecovery!) { - await _askForUpdateTransactionHistory(); - _askForUpdateBalance(); - walletAddresses.accountList.update(); - } - - if (blocksLeft < 100) { - await _askForUpdateTransactionHistory(); - _askForUpdateBalance(); - walletAddresses.accountList.update(); - syncStatus = SyncedSyncStatus(); - syncStatusChanged?.call(); - - if (!_hasSyncAfterStartup) { - _hasSyncAfterStartup = true; - await save(); - } - - if (walletInfo.isRecovery!) { - await setAsRecovered(); - } - } else { - syncStatus = SyncingSyncStatus(blocksLeft, ptc, height); - syncStatusChanged?.call(); - } - } catch (e) { - print(e.toString()); - } - onNewBlock?.call(height: height, blocksLeft: blocksLeft); - } - - void _onNewTransaction() async { - try { - await _askForUpdateTransactionHistory(); - _askForUpdateBalance(); - await Future.delayed(Duration(seconds: 1)); - } catch (e) { - print(e.toString()); - } - onNewTransaction?.call(); - } -} diff --git a/cw_wownero/lib/wownero_wallet.g.dart b/cw_wownero/lib/wownero_wallet.g.dart deleted file mode 100644 index 515976e9b1..0000000000 --- a/cw_wownero/lib/wownero_wallet.g.dart +++ /dev/null @@ -1,51 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wownero_wallet.dart'; - -// ************************************************************************** -// StoreGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic, no_leading_underscores_for_local_identifiers - -mixin _$WowneroWallet on WowneroWalletBase, Store { - late final _$syncStatusAtom = - Atom(name: 'WowneroWalletBase.syncStatus', context: context); - - @override - SyncStatus? get syncStatus { - _$syncStatusAtom.reportRead(); - return super.syncStatus; - } - - @override - set syncStatus(SyncStatus? value) { - _$syncStatusAtom.reportWrite(value, super.syncStatus, () { - super.syncStatus = value; - }); - } - - late final _$balanceAtom = - Atom(name: 'WowneroWalletBase.balance', context: context); - - @override - ObservableMap? get balance { - _$balanceAtom.reportRead(); - return super.balance; - } - - @override - set balance(ObservableMap? value) { - _$balanceAtom.reportWrite(value, super.balance, () { - super.balance = value; - }); - } - - @override - String toString() { - return ''' -syncStatus: ${syncStatus}, -balance: ${balance} - '''; - } -} diff --git a/cw_wownero/lib/wownero_wallet_addresses.dart b/cw_wownero/lib/wownero_wallet_addresses.dart deleted file mode 100644 index 2037a53bc2..0000000000 --- a/cw_wownero/lib/wownero_wallet_addresses.dart +++ /dev/null @@ -1,85 +0,0 @@ -import 'package:cw_core/wallet_addresses.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/account.dart'; -import 'package:cw_wownero/wownero_account_list.dart'; -import 'package:cw_wownero/wownero_subaddress_list.dart'; -import 'package:cw_core/subaddress.dart'; -import 'package:mobx/mobx.dart'; - -part 'wownero_wallet_addresses.g.dart'; - -class WowneroWalletAddresses = WowneroWalletAddressesBase - with _$WowneroWalletAddresses; - -abstract class WowneroWalletAddressesBase extends WalletAddresses with Store { - WowneroWalletAddressesBase(WalletInfo walletInfo) : super(walletInfo) { - accountList = WowneroAccountList(); - subaddressList = WowneroSubaddressList(); - } - - @override - @observable - String? address; - - @observable - Account? account; - - @observable - Subaddress? subaddress; - - late WowneroSubaddressList subaddressList; - - late WowneroAccountList accountList; - - @override - Future init() async { - accountList.update(); - account = accountList.accounts.first; - updateSubaddressList(accountIndex: account!.id ?? 0); - await updateAddressesInBox(); - } - - @override - Future updateAddressesInBox() async { - try { - final _subaddressList = WowneroSubaddressList(); - - addressesMap!.clear(); - - accountList.accounts.forEach((account) { - _subaddressList.update(accountIndex: account.id); - _subaddressList.subaddresses!.forEach((subaddress) { - addressesMap![subaddress.address!] = subaddress.label!; - }); - }); - - await saveAddressesInBox(); - } catch (e) { - print(e.toString()); - } - } - - bool validate() { - accountList.update(); - final accountListLength = accountList.accounts.length; - - if (accountListLength <= 0) { - return false; - } - - subaddressList.update(accountIndex: accountList.accounts.first.id); - final subaddressListLength = subaddressList.subaddresses?.length ?? 0; - - if (subaddressListLength <= 0) { - return false; - } - - return true; - } - - void updateSubaddressList({int? accountIndex}) { - subaddressList.update(accountIndex: accountIndex); - subaddress = subaddressList.subaddresses!.first; - address = subaddress!.address; - } -} diff --git a/cw_wownero/lib/wownero_wallet_addresses.g.dart b/cw_wownero/lib/wownero_wallet_addresses.g.dart deleted file mode 100644 index 0c56210dfc..0000000000 --- a/cw_wownero/lib/wownero_wallet_addresses.g.dart +++ /dev/null @@ -1,68 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'wownero_wallet_addresses.dart'; - -// ************************************************************************** -// StoreGenerator -// ************************************************************************** - -// ignore_for_file: non_constant_identifier_names, unnecessary_brace_in_string_interps, unnecessary_lambdas, prefer_expression_function_bodies, lines_longer_than_80_chars, avoid_as, avoid_annotating_with_dynamic - -mixin _$WowneroWalletAddresses on WowneroWalletAddressesBase, Store { - late final _$addressAtom = - Atom(name: 'WowneroWalletAddressesBase.address', context: context); - - @override - String? get address { - _$addressAtom.reportRead(); - return super.address; - } - - @override - set address(String? value) { - _$addressAtom.reportWrite(value, super.address, () { - super.address = value; - }); - } - - late final _$accountAtom = - Atom(name: 'WowneroWalletAddressesBase.account', context: context); - - @override - Account? get account { - _$accountAtom.reportRead(); - return super.account; - } - - @override - set account(Account? value) { - _$accountAtom.reportWrite(value, super.account, () { - super.account = value; - }); - } - - late final _$subaddressAtom = - Atom(name: 'WowneroWalletAddressesBase.subaddress', context: context); - - @override - Subaddress? get subaddress { - _$subaddressAtom.reportRead(); - return super.subaddress; - } - - @override - set subaddress(Subaddress? value) { - _$subaddressAtom.reportWrite(value, super.subaddress, () { - super.subaddress = value; - }); - } - - @override - String toString() { - return ''' -address: ${address}, -account: ${account}, -subaddress: ${subaddress} - '''; - } -} diff --git a/cw_wownero/lib/wownero_wallet_service.dart b/cw_wownero/lib/wownero_wallet_service.dart deleted file mode 100644 index 4e8bee0595..0000000000 --- a/cw_wownero/lib/wownero_wallet_service.dart +++ /dev/null @@ -1,248 +0,0 @@ -import 'dart:io'; -import 'package:collection/collection.dart' show IterableExtension; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/monero_wallet_utils.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_wownero/api/wallet_manager.dart' as wownero_wallet_manager; -import 'package:cw_wownero/api/wallet.dart' as wownero_wallet; -import 'package:cw_wownero/api/exceptions/wallet_opening_exception.dart'; -import 'package:cw_wownero/wownero_wallet.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cw_core/pathForWallet.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_type.dart'; - -class WowneroNewWalletCredentials extends WalletCredentials { - WowneroNewWalletCredentials( - {String? name, String? password, this.language, int seedWordsLength = 14}) - : super(name: name, password: password); - - final String? language; - final int seedWordsLength = 14; -} - -class WowneroRestoreWalletFromSeedCredentials extends WalletCredentials { - WowneroRestoreWalletFromSeedCredentials( - {String? name, String? password, int? height, this.mnemonic}) - : super(name: name, password: password, height: height); - - final String? mnemonic; -} - -class WowneroWalletLoadingException implements Exception { - @override - String toString() => 'Failure to load the wallet.'; -} - -class WowneroRestoreWalletFromKeysCredentials extends WalletCredentials { - WowneroRestoreWalletFromKeysCredentials( - {String? name, - String? password, - this.language, - this.address, - this.viewKey, - this.spendKey, - int? height}) - : super(name: name, password: password, height: height); - - final String? language; - final String? address; - final String? viewKey; - final String? spendKey; -} - -class WowneroWalletService extends WalletService< - WowneroNewWalletCredentials, - WowneroRestoreWalletFromSeedCredentials, - WowneroRestoreWalletFromKeysCredentials> { - WowneroWalletService(this.walletInfoSource); - - final Box walletInfoSource; - - static bool walletFilesExist(String path) => - !File(path).existsSync() && !File('$path.keys').existsSync(); - - @override - WalletType getType() => WalletType.wownero; - - @override - Future create(WowneroNewWalletCredentials credentials, - {int seedWordsLength = 14}) async { - try { - final path = - await pathForWallet(name: credentials.name!, type: getType()); - await wownero_wallet_manager.createWallet( - path: path, - password: credentials.password, - language: credentials.language, - seedWordsLength: seedWordsLength); - final wallet = WowneroWallet(walletInfo: credentials.walletInfo!); - await wallet.init(); - - return wallet; - } catch (e) { - // TODO: Implement Exception for wallet list service. - print('WowneroWalletsManager Error: ${e.toString()}'); - rethrow; - } - } - - @override - Future isWalletExit(String name) async { - try { - final path = await pathForWallet(name: name, type: getType()); - return wownero_wallet_manager.isWalletExist(path: path); - } catch (e) { - // TODO: Implement Exception for wallet list service. - print('WowneroWalletsManager Error: $e'); - rethrow; - } - } - - @override - Future openWallet(String name, String password) async { - try { - final path = await pathForWallet(name: name, type: getType()); - - if (walletFilesExist(path)) { - await repairOldAndroidWallet(name); - } - - await wownero_wallet_manager - .openWalletAsync({'path': path, 'password': password}); - final walletInfo = walletInfoSource.values.firstWhereOrNull( - (info) => info.id == WalletBase.idFor(name, getType()))!; - final wallet = WowneroWallet(walletInfo: walletInfo); - final isValid = wallet.walletAddresses.validate(); - - if (!isValid) { - await restoreOrResetWalletFiles(name); - wallet.close(); - return openWallet(name, password); - } - - await wallet.init(); - - return wallet; - } catch (e) { - // TODO: Implement Exception for wallet list service. - - if ((e.toString().contains('bad_alloc') || - (e is WalletOpeningException && - (e.message == 'std::bad_alloc' || - e.message!.contains('bad_alloc')))) || - (e.toString().contains('does not correspond') || - (e is WalletOpeningException && - e.message!.contains('does not correspond')))) { - await restoreOrResetWalletFiles(name); - return openWallet(name, password); - } - - rethrow; - } - } - - @override - Future remove(String wallet) async { - final path = await pathForWalletDir(name: wallet, type: getType()); - final file = Directory(path); - final isExist = file.existsSync(); - - if (isExist) { - await file.delete(recursive: true); - } - } - - @override - Future restoreFromKeys( - WowneroRestoreWalletFromKeysCredentials credentials) async { - try { - final path = - await pathForWallet(name: credentials.name!, type: getType()); - await wownero_wallet_manager.restoreFromKeys( - path: path, - password: credentials.password, - language: credentials.language, - restoreHeight: credentials.height, - address: credentials.address, - viewKey: credentials.viewKey, - spendKey: credentials.spendKey); - final wallet = WowneroWallet(walletInfo: credentials.walletInfo!); - wallet.walletInfo.isRecovery = true; - await wallet.init(); - - return wallet; - } catch (e) { - // TODO: Implement Exception for wallet list service. - print('WowneroWalletsManager Error: $e'); - rethrow; - } - } - - @override - Future restoreFromSeed( - WowneroRestoreWalletFromSeedCredentials credentials) async { - try { - final path = - await pathForWallet(name: credentials.name!, type: getType()); - await wownero_wallet_manager.restoreFromSeed( - path: path, - password: credentials.password, - seed: credentials.mnemonic, - restoreHeight: credentials.height); - final wallet = WowneroWallet(walletInfo: credentials.walletInfo!); - wallet.walletInfo.isRecovery = true; - - String seedString = credentials.mnemonic ?? ''; - int seedWordsLength = seedString.split(' ').length; - if (seedWordsLength == 14) { - wallet.walletInfo.restoreHeight = - wallet.getSeedHeight(credentials.mnemonic!); - } else { - wallet.walletInfo.restoreHeight = 0; - // TODO use an alternative to wow_seed's get_seed_height - } - - await wallet.init(); - return wallet; - } catch (e) { - // TODO: Implement Exception for wallet list service. - print('WowneroWalletsManager Error: $e'); - rethrow; - } - } - - Future repairOldAndroidWallet(String name) async { - try { - if (!Platform.isAndroid) { - return; - } - - final oldAndroidWalletDirPath = - await outdatedAndroidPathForWalletDir(name: name); - final dir = Directory(oldAndroidWalletDirPath); - - if (!dir.existsSync()) { - return; - } - - final newWalletDirPath = - await pathForWalletDir(name: name, type: getType()); - - dir.listSync().forEach((f) { - final file = File(f.path); - final name = f.path.split('/').last; - final newPath = newWalletDirPath + '/$name'; - final newFile = File(newPath); - - if (!newFile.existsSync()) { - newFile.createSync(); - } - newFile.writeAsBytesSync(file.readAsBytesSync()); - }); - } catch (e) { - print(e.toString()); - } - } -} diff --git a/cw_wownero/pubspec.lock b/cw_wownero/pubspec.lock deleted file mode 100644 index 7044691227..0000000000 --- a/cw_wownero/pubspec.lock +++ /dev/null @@ -1,609 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - _fe_analyzer_shared: - dependency: transitive - description: - name: _fe_analyzer_shared - url: "https://pub.dartlang.org" - source: hosted - version: "47.0.0" - analyzer: - dependency: transitive - description: - name: analyzer - url: "https://pub.dartlang.org" - source: hosted - version: "4.7.0" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.1" - asn1lib: - dependency: transitive - description: - name: asn1lib - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.8.2" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - build: - dependency: transitive - description: - name: build - url: "https://pub.dartlang.org" - source: hosted - version: "2.3.0" - build_config: - dependency: transitive - description: - name: build_config - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - build_daemon: - dependency: transitive - description: - name: build_daemon - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - build_resolvers: - dependency: "direct dev" - description: - name: build_resolvers - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.9" - build_runner: - dependency: "direct dev" - description: - name: build_runner - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - build_runner_core: - dependency: transitive - description: - name: build_runner_core - url: "https://pub.dartlang.org" - source: hosted - version: "7.2.3" - built_collection: - dependency: transitive - description: - name: built_collection - url: "https://pub.dartlang.org" - source: hosted - version: "5.1.1" - built_value: - dependency: transitive - description: - name: built_value - url: "https://pub.dartlang.org" - source: hosted - version: "8.4.1" - characters: - dependency: transitive - description: - name: characters - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - checked_yaml: - dependency: transitive - description: - name: checked_yaml - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - clock: - dependency: transitive - description: - name: clock - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - code_builder: - dependency: transitive - description: - name: code_builder - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.0" - collection: - dependency: "direct main" - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.16.0" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.2" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.2" - cw_core: - dependency: "direct main" - description: - path: "../cw_core" - relative: true - source: path - version: "0.0.1" - dart_style: - dependency: transitive - description: - name: dart_style - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.3" - encrypt: - dependency: transitive - description: - name: encrypt - url: "https://pub.dartlang.org" - source: hosted - version: "5.0.1" - fake_async: - dependency: transitive - description: - name: fake_async - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.0" - ffi: - dependency: "direct main" - description: - name: ffi - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.1" - file: - dependency: transitive - description: - name: file - url: "https://pub.dartlang.org" - source: hosted - version: "6.1.4" - fixnum: - dependency: transitive - description: - name: fixnum - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_mobx: - dependency: "direct main" - description: - name: flutter_mobx - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6+1" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - frontend_server_client: - dependency: transitive - description: - name: frontend_server_client - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - glob: - dependency: transitive - description: - name: glob - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - graphs: - dependency: transitive - description: - name: graphs - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - hive: - dependency: transitive - description: - name: hive - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.3" - hive_generator: - dependency: "direct dev" - description: - name: hive_generator - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.3" - http: - dependency: "direct main" - description: - name: http - url: "https://pub.dartlang.org" - source: hosted - version: "0.13.5" - http_multi_server: - dependency: transitive - description: - name: http_multi_server - url: "https://pub.dartlang.org" - source: hosted - version: "3.2.1" - http_parser: - dependency: transitive - description: - name: http_parser - url: "https://pub.dartlang.org" - source: hosted - version: "4.0.1" - intl: - dependency: "direct main" - description: - name: intl - url: "https://pub.dartlang.org" - source: hosted - version: "0.17.0" - io: - dependency: transitive - description: - name: io - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.3" - js: - dependency: transitive - description: - name: js - url: "https://pub.dartlang.org" - source: hosted - version: "0.6.4" - json_annotation: - dependency: transitive - description: - name: json_annotation - url: "https://pub.dartlang.org" - source: hosted - version: "4.6.0" - logging: - dependency: transitive - description: - name: logging - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.11" - material_color_utilities: - dependency: transitive - description: - name: material_color_utilities - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.4" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - mime: - dependency: transitive - description: - name: mime - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - mobx: - dependency: "direct main" - description: - name: mobx - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7+5" - mobx_codegen: - dependency: "direct dev" - description: - name: mobx_codegen - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.7" - package_config: - dependency: transitive - description: - name: package_config - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.1" - path_provider: - dependency: "direct main" - description: - name: path_provider - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - path_provider_android: - dependency: transitive - description: - name: path_provider_android - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.20" - path_provider_ios: - dependency: transitive - description: - name: path_provider_ios - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.11" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.7" - path_provider_macos: - dependency: transitive - description: - name: path_provider_macos - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.6" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.4" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - platform: - dependency: transitive - description: - name: platform - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.0" - plugin_platform_interface: - dependency: transitive - description: - name: plugin_platform_interface - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" - pointycastle: - dependency: transitive - description: - name: pointycastle - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" - pool: - dependency: transitive - description: - name: pool - url: "https://pub.dartlang.org" - source: hosted - version: "1.5.1" - process: - dependency: transitive - description: - name: process - url: "https://pub.dartlang.org" - source: hosted - version: "4.2.4" - pub_semver: - dependency: transitive - description: - name: pub_semver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - pubspec_parse: - dependency: transitive - description: - name: pubspec_parse - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.1" - shelf: - dependency: transitive - description: - name: shelf - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.2" - shelf_web_socket: - dependency: transitive - description: - name: shelf_web_socket - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.2" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_gen: - dependency: transitive - description: - name: source_gen - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.2" - source_helper: - dependency: transitive - description: - name: source_helper - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.2" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.8.2" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.10.0" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.0" - stream_transform: - dependency: transitive - description: - name: stream_transform - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.2.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.4.9" - timing: - dependency: transitive - description: - name: timing - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.0" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.3.1" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.2" - watcher: - dependency: transitive - description: - name: watcher - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.1" - web_socket_channel: - dependency: transitive - description: - name: web_socket_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.2.0" - win32: - dependency: transitive - description: - name: win32 - url: "https://pub.dartlang.org" - source: hosted - version: "3.0.0" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.0+2" - yaml: - dependency: transitive - description: - name: yaml - url: "https://pub.dartlang.org" - source: hosted - version: "3.1.1" -sdks: - dart: ">=2.17.0 <3.0.0" - flutter: ">=3.0.0" diff --git a/cw_wownero/pubspec.yaml b/cw_wownero/pubspec.yaml deleted file mode 100644 index 14613de75d..0000000000 --- a/cw_wownero/pubspec.yaml +++ /dev/null @@ -1,79 +0,0 @@ -name: cw_wownero -description: A new flutter plugin project. -version: 0.0.1 -publish_to: none -author: Cake Wallet -homepage: https://cakewallet.com - -environment: - sdk: '>=2.12.0 <3.0.0' - flutter: ">=1.20.0" - -dependencies: - flutter: - sdk: flutter - ffi: ^2.0.1 - path_provider: ^2.0.11 - http: ^0.13.4 - mobx: ^2.0.7+4 - flutter_mobx: ^2.0.6+1 - intl: ^0.17.0 - cw_core: - path: ../cw_core - collection: ^1.15.0-nullsafety.4 - -dev_dependencies: - flutter_test: - sdk: flutter - build_runner: ^2.1.7 - build_resolvers: ^2.0.6 - mobx_codegen: ^2.0.6 - hive_generator: ^1.1.2 - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - # This section identifies this Flutter project as a plugin project. - # The androidPackage and pluginClass identifiers should not ordinarily - # be modified. They are used by the tooling to maintain consistency when - # adding or updating assets for this project. - plugin: - platforms: - android: - package: com.cakewallet.cw_wownero - pluginClass: CwWowneroPlugin - ios: - pluginClass: CwWowneroPlugin - - # To add assets to your plugin package, add an assets section, like this: - # assets: - # - images/a_dot_burr.jpeg - # - images/a_dot_ham.jpeg - # - # For details regarding assets in packages, see - # https://flutter.dev/assets-and-images/#from-packages - # - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # To add custom fonts to your plugin package, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts in packages, see - # https://flutter.dev/custom-fonts/#from-packages diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index bfb952856a..cd70d1b959 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -33,25 +33,6 @@ PODS: - Flutter - cw_shared_external/Sodium (0.0.1): - Flutter - - cw_wownero (0.0.2): - - cw_shared_external - - cw_wownero/Boost (= 0.0.2) - - cw_wownero/OpenSSL (= 0.0.2) - - cw_wownero/Sodium (= 0.0.2) - - cw_wownero/Wownero (= 0.0.2) - - Flutter - - cw_wownero/Boost (0.0.2): - - cw_shared_external - - Flutter - - cw_wownero/OpenSSL (0.0.2): - - cw_shared_external - - Flutter - - cw_wownero/Sodium (0.0.2): - - cw_shared_external - - Flutter - - cw_wownero/Wownero (0.0.2): - - cw_shared_external - - Flutter - Flutter (1.0.0) - flutter_libmonero (0.0.1): - Flutter @@ -67,7 +48,6 @@ PODS: DEPENDENCIES: - cw_monero (from `.symlinks/plugins/cw_monero/ios`) - cw_shared_external (from `.symlinks/plugins/cw_shared_external/ios`) - - cw_wownero (from `.symlinks/plugins/cw_wownero/ios`) - Flutter (from `Flutter`) - flutter_libmonero (from `.symlinks/plugins/flutter_libmonero/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) @@ -80,8 +60,6 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/cw_monero/ios" cw_shared_external: :path: ".symlinks/plugins/cw_shared_external/ios" - cw_wownero: - :path: ".symlinks/plugins/cw_wownero/ios" Flutter: :path: Flutter flutter_libmonero: @@ -98,7 +76,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: cw_monero: 9816991daff0e3ad0a8be140e31933b5526babd4 cw_shared_external: 2972d872b8917603478117c9957dfca611845a92 - cw_wownero: 25174994b62eff7bb5a4aa7e6d1f157699087d8e Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a flutter_libmonero: da68a616b73dd0374a8419c684fa6b6df2c44ffe flutter_secure_storage: 7953c38a04c3fdbb00571bcd87d8e3b5ceb9daec diff --git a/example/lib/main.dart b/example/lib/main.dart index 0aaf3e4f6a..9ed2749ece 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,346 +1,341 @@ -import 'dart:async'; -import 'dart:core'; -import 'dart:core' as core; -import 'dart:io'; -import 'dart:math'; - -import 'package:cw_core/monero_amount_format.dart'; -import 'package:cw_core/node.dart'; -import 'package:cw_core/pending_transaction.dart'; -import 'package:cw_core/unspent_coins_info.dart'; -import 'package:cw_core/wallet_base.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cw_core/wallet_type.dart'; -import 'package:cw_wownero/api/wallet.dart'; -import 'package:cw_wownero/pending_wownero_transaction.dart'; -import 'package:cw_wownero/wownero_wallet.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:flutter_libmonero/core/key_service.dart'; -import 'package:flutter_libmonero/core/wallet_creation_service.dart'; -import 'package:flutter_libmonero/view_model/send/output.dart'; -import 'package:flutter_libmonero/wownero/wownero.dart'; -import 'package:flutter_secure_storage/flutter_secure_storage.dart'; -import 'package:hive/hive.dart'; -import 'package:path_provider/path_provider.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -FlutterSecureStorage? storage; -WalletService? walletService; -SharedPreferences? prefs; -KeyService? keysStorage; -WowneroWalletBase? walletBase; -late WalletCreationService _walletCreationService; - -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - Directory appDir = (await getApplicationDocumentsDirectory()); - if (Platform.isIOS) { - appDir = (await getLibraryDirectory()); - } - await Hive.close(); - Hive.init(appDir.path); - - // if (!Hive.isAdapterRegistered(Node.typeId)) { - Hive.registerAdapter(NodeAdapter()); - // } - - // if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { - Hive.registerAdapter(WalletInfoAdapter()); - // } - - // if (!Hive.isAdapterRegistered(WalletType.)) { - Hive.registerAdapter(WalletTypeAdapter()); - // } - - // if (!Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { - Hive.registerAdapter(UnspentCoinsInfoAdapter()); - // } - - wownero.onStartup(); - final _walletInfoSource = await Hive.openBox(WalletInfo.boxName); - walletService = wownero.createWowneroWalletService(_walletInfoSource); - storage = FlutterSecureStorage(); - prefs = await SharedPreferences.getInstance(); - keysStorage = KeyService(storage!); - WalletInfo walletInfo; - late WalletCredentials credentials; - try { - // if (name?.isEmpty ?? true) { - // name = await generateName(); - // } - String name = "namee${Random().nextInt(10000000)}"; - final dirPath = - await pathForWalletDir(name: name, type: WalletType.wownero); - final path = await pathForWallet(name: name, type: WalletType.wownero); - credentials = - // // creating a new wallet - // wownero.createWowneroNewWalletCredentials( - // name: name, language: "English"); - // restoring a previous wallet - wownero.createWowneroRestoreWalletFromSeedCredentials( - name: name, - // height: 2580000, - mnemonic: "", - ); - walletInfo = WalletInfo.external( - id: WalletBase.idFor(name, WalletType.wownero), - name: name, - type: WalletType.wownero, - isRecovery: false, - restoreHeight: credentials.height ?? 0, - date: DateTime.now(), - path: path, - address: "", - dirPath: dirPath); - credentials.walletInfo = walletInfo; - - _walletCreationService = WalletCreationService( - secureStorage: storage, - sharedPreferences: prefs, - walletService: walletService, - keyService: keysStorage, - ); - _walletCreationService.changeWalletType(); - // To restore from a seed - final wallet = await - // _walletCreationService.create(credentials); - _walletCreationService.restoreFromSeed(credentials); - // to create a new wallet - // final wallet = await process(credentials); - walletInfo.address = wallet.walletAddresses.address; - print(walletInfo.address); - await _walletInfoSource.add(walletInfo); - walletBase?.close(); - walletBase = wallet as WowneroWalletBase; - print("${walletBase?.seed}"); - } catch (e, s) { - print(e); - print(s); - } - // print(walletBase); - // loggerPrint(walletBase.toString()); - // loggerPrint("name: ${walletBase!.name} seed: ${walletBase!.seed} id: " - // "${walletBase!.id} walletinfo: ${toStringForinfo(walletBase!.walletInfo)} type: ${walletBase!.type} balance: " - // "${walletBase!.balance.entries.first.value.available} currency: ${walletBase!.currency}"); - await walletBase?.connectToNode( - node: Node(uri: "eu-west-2.wow.xmr.pm:34568", type: WalletType.wownero)); - walletBase!.rescan(height: credentials.height); - walletBase!.getNodeHeight(); - runApp(MyApp()); -} - -String toStringForinfo(WalletInfo info) { - return "id: ${info.id} name: ${info.name} type: ${info.type} recovery: ${info.isRecovery}" - " restoreheight: ${info.restoreHeight} timestamp: ${info.timestamp} dirPath: ${info.dirPath} " - "path: ${info.path} address: ${info.address} addresses: ${info.addresses}"; -} - -Future pathForWalletDir( - {required String name, required WalletType type}) async { - Directory root = (await getApplicationDocumentsDirectory()); - if (Platform.isIOS) { - root = (await getLibraryDirectory()); - } - final prefix = walletTypeToString(type).toLowerCase(); - final walletsDir = Directory('${root.path}/wallets'); - final walletDire = Directory('${walletsDir.path}/$prefix/$name'); - - if (!walletDire.existsSync()) { - walletDire.createSync(recursive: true); - } - - return walletDire.path; -} - -Future pathForWallet( - {required String name, required WalletType type}) async => - await pathForWalletDir(name: name, type: type) - .then((path) => path + '/$name'); - -class MyApp extends StatefulWidget { - @override - _MyAppState createState() => _MyAppState(); -} - -class _MyAppState extends State { - String? _platformVersion = 'Unknown'; - - @override - void initState() { - super.initState(); - initPlatformState(); - } - - // Platform messages are asynchronous, so we initialize in an async method. - Future initPlatformState() async { - String? platformVersion; - // Platform messages may fail, so we use a try/catch PlatformException. - try { - // platformVersion = await FlutterLibwownero.platformVersion; - } on PlatformException { - platformVersion = 'Failed to get platform version.'; - } - - // If the widget was removed from the tree while the asynchronous platform - // message was in flight, we want to discard the reply rather than calling - // setState to update our non-existent appearance. - if (!mounted) return; - - setState(() { - _platformVersion = platformVersion; - }); - } - - @override - Widget build(BuildContext context) { - print(getSyncingHeight()); - return MaterialApp( - home: Scaffold( - appBar: AppBar( - title: const Text('Wownero Plugin example app'), - ), - body: Center( - child: ListView( - children: [ - Text( - "Transactions:${walletBase!.transactionHistory!.transactions}"), - TextButton( - onPressed: () async { - String addr = walletBase!.getTransactionAddress( - wownero.getCurrentAccount(walletBase!).id!, 0); - loggerPrint("addr: $addr"); - for (var bal in walletBase!.balance!.entries) { - loggerPrint( - "key: ${bal.key}, amount ${moneroAmountToString(amount: bal.value.available)}"); - } - }, - child: Text("amount")), - TextButton( - onPressed: () async { - Output output = Output(walletBase!); // - output.address = - "45ssGbDbLTnjdhpAm89PDpHpj6r5xWXBwL6Bh8hpy3PUcEnLgroo9vFJ9UE3HsAT5TTSk3Cqe2boJQHePAXisQSu9i6tz5A"; - output.setCryptoAmount("0.00001011"); - List outputs = [output]; - Object tmp = - wownero.createWowneroTransactionCreationCredentials( - outputs: outputs, - priority: wownero.getDefaultTransactionPriority()); - loggerPrint(tmp); - Future awaitPendingTransaction = - walletBase!.createTransaction(tmp); - loggerPrint(output); - PendingWowneroTransaction pendingWowneroTransaction = - await awaitPendingTransaction - as PendingWowneroTransaction; - loggerPrint(pendingWowneroTransaction); - loggerPrint(pendingWowneroTransaction.id); - loggerPrint(pendingWowneroTransaction.amountFormatted); - loggerPrint(pendingWowneroTransaction.feeFormatted); - loggerPrint(pendingWowneroTransaction - .pendingTransactionDescription.amount); - loggerPrint(pendingWowneroTransaction - .pendingTransactionDescription.hash); - loggerPrint(pendingWowneroTransaction - .pendingTransactionDescription.fee); - loggerPrint(pendingWowneroTransaction - .pendingTransactionDescription.pointerAddress); - try { - await pendingWowneroTransaction.commit(); - loggerPrint( - "transaction ${pendingWowneroTransaction.id} has been sent"); - } catch (e, s) { - loggerPrint("error"); - loggerPrint(e); - loggerPrint(s); - } - }, - child: Text("send Transaction"), - ), - // Text( - // "bob ${wowneroAmountToString(amount: walletBase.transactionHistory.transactions.entries.first.value.amount)}"), - FutureBuilder( - future: walletBase! - .getNodeHeight(), // a previously-obtained Future or null - builder: (BuildContext context, AsyncSnapshot snapshot) { - List children; - if (snapshot.hasData) { - children = [ - const Icon( - Icons.check_circle_outline, - color: Colors.green, - size: 60, - ), - Padding( - padding: const EdgeInsets.only(top: 16), - child: Text('Result: ${snapshot.data}'), - ) - ]; - } else if (snapshot.hasError) { - children = [ - const Icon( - Icons.error_outline, - color: Colors.red, - size: 60, - ), - Padding( - padding: const EdgeInsets.only(top: 16), - child: Text('Error: ${snapshot.error}'), - ) - ]; - } else { - children = const [ - SizedBox( - width: 60, - height: 60, - child: CircularProgressIndicator(), - ), - Padding( - padding: EdgeInsets.only(top: 16), - child: Text('Awaiting result...'), - ) - ]; - } - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: children, - ), - ); - }, - ), - ], - ), - // Text( - // 'Running on: $_platformVersion\n ${walletBase.getNodeHeight()}'), - ), - ), - ); - } -} - -void loggerPrint(core.Object? object) async { - final utcTime = core.DateTime.now().toUtc().toString() + ": "; - core.int defaultPrintLength = 1020 - utcTime.length; - if (object == null || object.toString().length <= defaultPrintLength) { - core.print("$utcTime$object"); - } else { - core.String log = object.toString(); - core.int start = 0; - core.int endIndex = defaultPrintLength; - core.int logLength = log.length; - core.int tmpLogLength = log.length; - while (endIndex < logLength) { - core.print(utcTime + log.substring(start, endIndex)); - endIndex += defaultPrintLength; - start += defaultPrintLength; - tmpLogLength -= defaultPrintLength; - } - if (tmpLogLength > 0) { - core.print(utcTime + log.substring(start, logLength)); - } - } -} +// import 'dart:async'; +// import 'dart:core'; +// import 'dart:core' as core; +// import 'dart:io'; +// import 'dart:math'; +// +// import 'package:cw_core/monero_amount_format.dart'; +// import 'package:cw_core/node.dart'; +// import 'package:cw_core/pending_transaction.dart'; +// import 'package:cw_core/unspent_coins_info.dart'; +// import 'package:cw_core/wallet_base.dart'; +// import 'package:cw_core/wallet_credentials.dart'; +// import 'package:cw_core/wallet_info.dart'; +// import 'package:cw_core/wallet_service.dart'; +// import 'package:cw_core/wallet_type.dart'; +// import 'package:flutter/material.dart'; +// import 'package:flutter/services.dart'; +// import 'package:flutter_libmonero/core/key_service.dart'; +// import 'package:flutter_libmonero/core/wallet_creation_service.dart'; +// import 'package:flutter_libmonero/view_model/send/output.dart'; +// import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +// import 'package:hive/hive.dart'; +// import 'package:path_provider/path_provider.dart'; +// import 'package:shared_preferences/shared_preferences.dart'; +// +// FlutterSecureStorage? storage; +// WalletService? walletService; +// SharedPreferences? prefs; +// KeyService? keysStorage; +// late WalletCreationService _walletCreationService; +// +// void main() async { +// WidgetsFlutterBinding.ensureInitialized(); +// Directory appDir = (await getApplicationDocumentsDirectory()); +// if (Platform.isIOS) { +// appDir = (await getLibraryDirectory()); +// } +// await Hive.close(); +// Hive.init(appDir.path); +// +// // if (!Hive.isAdapterRegistered(Node.typeId)) { +// Hive.registerAdapter(NodeAdapter()); +// // } +// +// // if (!Hive.isAdapterRegistered(WalletInfo.typeId)) { +// Hive.registerAdapter(WalletInfoAdapter()); +// // } +// +// // if (!Hive.isAdapterRegistered(WalletType.)) { +// Hive.registerAdapter(WalletTypeAdapter()); +// // } +// +// // if (!Hive.isAdapterRegistered(UnspentCoinsInfo.typeId)) { +// Hive.registerAdapter(UnspentCoinsInfoAdapter()); +// // } +// +// wownero.onStartup(); +// final _walletInfoSource = await Hive.openBox(WalletInfo.boxName); +// walletService = wownero.createWowneroWalletService(_walletInfoSource); +// storage = FlutterSecureStorage(); +// prefs = await SharedPreferences.getInstance(); +// keysStorage = KeyService(storage!); +// WalletInfo walletInfo; +// late WalletCredentials credentials; +// try { +// // if (name?.isEmpty ?? true) { +// // name = await generateName(); +// // } +// String name = "namee${Random().nextInt(10000000)}"; +// final dirPath = +// await pathForWalletDir(name: name, type: WalletType.wownero); +// final path = await pathForWallet(name: name, type: WalletType.wownero); +// credentials = +// // // creating a new wallet +// // wownero.createWowneroNewWalletCredentials( +// // name: name, language: "English"); +// // restoring a previous wallet +// wownero.createWowneroRestoreWalletFromSeedCredentials( +// name: name, +// // height: 2580000, +// mnemonic: "", +// ); +// walletInfo = WalletInfo.external( +// id: WalletBase.idFor(name, WalletType.wownero), +// name: name, +// type: WalletType.wownero, +// isRecovery: false, +// restoreHeight: credentials.height ?? 0, +// date: DateTime.now(), +// path: path, +// address: "", +// dirPath: dirPath); +// credentials.walletInfo = walletInfo; +// +// _walletCreationService = WalletCreationService( +// secureStorage: storage, +// sharedPreferences: prefs, +// walletService: walletService, +// keyService: keysStorage, +// ); +// _walletCreationService.changeWalletType(); +// // To restore from a seed +// final wallet = await +// // _walletCreationService.create(credentials); +// _walletCreationService.restoreFromSeed(credentials); +// // to create a new wallet +// // final wallet = await process(credentials); +// walletInfo.address = wallet.walletAddresses.address; +// print(walletInfo.address); +// await _walletInfoSource.add(walletInfo); +// walletBase?.close(); +// walletBase = wallet as WowneroWalletBase; +// print("${walletBase?.seed}"); +// } catch (e, s) { +// print(e); +// print(s); +// } +// // print(walletBase); +// // loggerPrint(walletBase.toString()); +// // loggerPrint("name: ${walletBase!.name} seed: ${walletBase!.seed} id: " +// // "${walletBase!.id} walletinfo: ${toStringForinfo(walletBase!.walletInfo)} type: ${walletBase!.type} balance: " +// // "${walletBase!.balance.entries.first.value.available} currency: ${walletBase!.currency}"); +// await walletBase?.connectToNode( +// node: Node(uri: "eu-west-2.wow.xmr.pm:34568", type: WalletType.wownero)); +// walletBase!.rescan(height: credentials.height); +// walletBase!.getNodeHeight(); +// runApp(MyApp()); +// } +// +// String toStringForinfo(WalletInfo info) { +// return "id: ${info.id} name: ${info.name} type: ${info.type} recovery: ${info.isRecovery}" +// " restoreheight: ${info.restoreHeight} timestamp: ${info.timestamp} dirPath: ${info.dirPath} " +// "path: ${info.path} address: ${info.address} addresses: ${info.addresses}"; +// } +// +// Future pathForWalletDir( +// {required String name, required WalletType type}) async { +// Directory root = (await getApplicationDocumentsDirectory()); +// if (Platform.isIOS) { +// root = (await getLibraryDirectory()); +// } +// final prefix = walletTypeToString(type).toLowerCase(); +// final walletsDir = Directory('${root.path}/wallets'); +// final walletDire = Directory('${walletsDir.path}/$prefix/$name'); +// +// if (!walletDire.existsSync()) { +// walletDire.createSync(recursive: true); +// } +// +// return walletDire.path; +// } +// +// Future pathForWallet( +// {required String name, required WalletType type}) async => +// await pathForWalletDir(name: name, type: type) +// .then((path) => path + '/$name'); +// +// class MyApp extends StatefulWidget { +// @override +// _MyAppState createState() => _MyAppState(); +// } +// +// class _MyAppState extends State { +// String? _platformVersion = 'Unknown'; +// +// @override +// void initState() { +// super.initState(); +// initPlatformState(); +// } +// +// // Platform messages are asynchronous, so we initialize in an async method. +// Future initPlatformState() async { +// String? platformVersion; +// // Platform messages may fail, so we use a try/catch PlatformException. +// try { +// // platformVersion = await FlutterLibwownero.platformVersion; +// } on PlatformException { +// platformVersion = 'Failed to get platform version.'; +// } +// +// // If the widget was removed from the tree while the asynchronous platform +// // message was in flight, we want to discard the reply rather than calling +// // setState to update our non-existent appearance. +// if (!mounted) return; +// +// setState(() { +// _platformVersion = platformVersion; +// }); +// } +// +// @override +// Widget build(BuildContext context) { +// print(getSyncingHeight()); +// return MaterialApp( +// home: Scaffold( +// appBar: AppBar( +// title: const Text('Wownero Plugin example app'), +// ), +// body: Center( +// child: ListView( +// children: [ +// Text( +// "Transactions:${walletBase!.transactionHistory!.transactions}"), +// TextButton( +// onPressed: () async { +// String addr = walletBase!.getTransactionAddress( +// wownero.getCurrentAccount(walletBase!).id!, 0); +// loggerPrint("addr: $addr"); +// for (var bal in walletBase!.balance!.entries) { +// loggerPrint( +// "key: ${bal.key}, amount ${moneroAmountToString(amount: bal.value.available)}"); +// } +// }, +// child: Text("amount")), +// TextButton( +// onPressed: () async { +// Output output = Output(walletBase!); // +// output.address = +// "45ssGbDbLTnjdhpAm89PDpHpj6r5xWXBwL6Bh8hpy3PUcEnLgroo9vFJ9UE3HsAT5TTSk3Cqe2boJQHePAXisQSu9i6tz5A"; +// output.setCryptoAmount("0.00001011"); +// List outputs = [output]; +// Object tmp = +// wownero.createWowneroTransactionCreationCredentials( +// outputs: outputs, +// priority: wownero.getDefaultTransactionPriority()); +// loggerPrint(tmp); +// Future awaitPendingTransaction = +// walletBase!.createTransaction(tmp); +// loggerPrint(output); +// PendingWowneroTransaction pendingWowneroTransaction = +// await awaitPendingTransaction +// as PendingWowneroTransaction; +// loggerPrint(pendingWowneroTransaction); +// loggerPrint(pendingWowneroTransaction.id); +// loggerPrint(pendingWowneroTransaction.amountFormatted); +// loggerPrint(pendingWowneroTransaction.feeFormatted); +// loggerPrint(pendingWowneroTransaction +// .pendingTransactionDescription.amount); +// loggerPrint(pendingWowneroTransaction +// .pendingTransactionDescription.hash); +// loggerPrint(pendingWowneroTransaction +// .pendingTransactionDescription.fee); +// loggerPrint(pendingWowneroTransaction +// .pendingTransactionDescription.pointerAddress); +// try { +// await pendingWowneroTransaction.commit(); +// loggerPrint( +// "transaction ${pendingWowneroTransaction.id} has been sent"); +// } catch (e, s) { +// loggerPrint("error"); +// loggerPrint(e); +// loggerPrint(s); +// } +// }, +// child: Text("send Transaction"), +// ), +// // Text( +// // "bob ${wowneroAmountToString(amount: walletBase.transactionHistory.transactions.entries.first.value.amount)}"), +// FutureBuilder( +// future: walletBase! +// .getNodeHeight(), // a previously-obtained Future or null +// builder: (BuildContext context, AsyncSnapshot snapshot) { +// List children; +// if (snapshot.hasData) { +// children = [ +// const Icon( +// Icons.check_circle_outline, +// color: Colors.green, +// size: 60, +// ), +// Padding( +// padding: const EdgeInsets.only(top: 16), +// child: Text('Result: ${snapshot.data}'), +// ) +// ]; +// } else if (snapshot.hasError) { +// children = [ +// const Icon( +// Icons.error_outline, +// color: Colors.red, +// size: 60, +// ), +// Padding( +// padding: const EdgeInsets.only(top: 16), +// child: Text('Error: ${snapshot.error}'), +// ) +// ]; +// } else { +// children = const [ +// SizedBox( +// width: 60, +// height: 60, +// child: CircularProgressIndicator(), +// ), +// Padding( +// padding: EdgeInsets.only(top: 16), +// child: Text('Awaiting result...'), +// ) +// ]; +// } +// return Center( +// child: Column( +// mainAxisAlignment: MainAxisAlignment.center, +// children: children, +// ), +// ); +// }, +// ), +// ], +// ), +// // Text( +// // 'Running on: $_platformVersion\n ${walletBase.getNodeHeight()}'), +// ), +// ), +// ); +// } +// } +// +// void loggerPrint(core.Object? object) async { +// final utcTime = core.DateTime.now().toUtc().toString() + ": "; +// core.int defaultPrintLength = 1020 - utcTime.length; +// if (object == null || object.toString().length <= defaultPrintLength) { +// core.print("$utcTime$object"); +// } else { +// core.String log = object.toString(); +// core.int start = 0; +// core.int endIndex = defaultPrintLength; +// core.int logLength = log.length; +// core.int tmpLogLength = log.length; +// while (endIndex < logLength) { +// core.print(utcTime + log.substring(start, endIndex)); +// endIndex += defaultPrintLength; +// start += defaultPrintLength; +// tmpLogLength -= defaultPrintLength; +// } +// if (tmpLogLength > 0) { +// core.print(utcTime + log.substring(start, logLength)); +// } +// } +// } diff --git a/example/pubspec.lock b/example/pubspec.lock index f2f6bc85c8..44f5991f3f 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,84 +5,96 @@ packages: dependency: transitive description: name: archive - url: "https://pub.dartlang.org" + sha256: eb33140ede1b4039f4ad631f7bf3cfa58e24514e8bf87184bc32f17541af87fc + url: "https://pub.dev" source: hosted version: "3.3.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: b003c3098049a51720352d219b0bb5f219b60fbfb68e7a4748139a06a5676515 + url: "https://pub.dev" source: hosted version: "2.3.1" asn1lib: dependency: transitive description: name: asn1lib - url: "https://pub.dartlang.org" + sha256: c273725e171cea7e69c8953181202a2850297bcc7617916d83b396cd791a2dcd + url: "https://pub.dev" source: hosted version: "1.1.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + url: "https://pub.dev" source: hosted version: "3.0.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" cryptography: dependency: transitive description: name: cryptography - url: "https://pub.dartlang.org" + sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + url: "https://pub.dev" source: hosted version: "2.0.5" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be + url: "https://pub.dev" source: hosted version: "1.0.5" cw_core: @@ -106,46 +118,44 @@ packages: relative: true source: path version: "0.0.1" - cw_wownero: - dependency: transitive - description: - path: "../cw_wownero" - relative: true - source: path - version: "0.0.1" encrypt: dependency: transitive description: name: encrypt - url: "https://pub.dartlang.org" + sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + url: "https://pub.dev" source: hosted version: "5.0.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad + url: "https://pub.dev" source: hosted version: "6.1.2" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + url: "https://pub.dev" source: hosted version: "1.0.1" flutter: @@ -164,49 +174,56 @@ packages: dependency: transitive description: name: flutter_mobx - url: "https://pub.dartlang.org" + sha256: "906d858f3883140624c41eba5d60d0134ab94f565a39fb2a18439bf920931035" + url: "https://pub.dev" source: hosted version: "2.0.6+1" flutter_secure_storage: dependency: transitive description: name: flutter_secure_storage - url: "https://pub.dartlang.org" + sha256: "1b7c2f80ee41861543bc63fee56122a114129c15234731312418ca1eda7d3d7f" + url: "https://pub.dev" source: hosted version: "5.0.2" flutter_secure_storage_linux: dependency: transitive description: name: flutter_secure_storage_linux - url: "https://pub.dartlang.org" + sha256: c6e57a7c000a95e58b4282500cf88df61c57c3b199a390b4f6b458abc40aba0a + url: "https://pub.dev" source: hosted version: "1.1.0" flutter_secure_storage_macos: dependency: transitive description: name: flutter_secure_storage_macos - url: "https://pub.dartlang.org" + sha256: e3c29bf81b8179477d662a9c7c15ea4402876a1eafcb02407227d46bbb86cd20 + url: "https://pub.dev" source: hosted version: "1.1.0" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface - url: "https://pub.dartlang.org" + sha256: "9af003dec5ba9f959300fd76ac8adf5608fbfbc957cdd7a987af206a8e073b32" + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_secure_storage_web: dependency: transitive description: name: flutter_secure_storage_web - url: "https://pub.dartlang.org" + sha256: "926716d84eb45220cb1783af629093301613f5e5b51da7c1813e430d69bd716f" + url: "https://pub.dev" source: hosted version: "1.0.2" flutter_secure_storage_windows: dependency: transitive description: name: flutter_secure_storage_windows - url: "https://pub.dartlang.org" + sha256: cf9fd49c2807f80dc01f449592e1e7971a3697d1e248b653efb8323536dc2961 + url: "https://pub.dev" source: hosted version: "1.1.2" flutter_test: @@ -223,210 +240,240 @@ packages: dependency: transitive description: name: hive - url: "https://pub.dartlang.org" + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" source: hosted version: "2.2.3" http: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "2ed163531e071c2c6b7c659635112f24cb64ecbebf6af46b550d536c0b1aa112" + url: "https://pub.dev" source: hosted version: "0.13.4" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: db3060f22889f3d9d55f6a217565486737037eec3609f7f3eca4d0c67ee0d8a0 + url: "https://pub.dev" source: hosted version: "4.0.1" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mobx: dependency: transitive description: name: mobx - url: "https://pub.dartlang.org" + sha256: e287b19fb09a6e8537bcce36a8628153dd39174f11003fd07491869fd705c27b + url: "https://pub.dev" source: hosted version: "2.0.7+4" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" path_provider: dependency: transitive description: name: path_provider - url: "https://pub.dartlang.org" + sha256: "050e8e85e4b7fecdf2bb3682c1c64c4887a183720c802d323de8a5fd76d372dd" + url: "https://pub.dev" source: hosted version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: cf7c403a541fc68cd398fb91a7eea8ec234813547d5b55245eed644d1246c5d8 + url: "https://pub.dev" source: hosted version: "2.0.16" path_provider_ios: dependency: transitive description: name: path_provider_ios - url: "https://pub.dartlang.org" + sha256: "641df59948e0fda05ca71f1dd6768d6da7f0ceb52aab734bf9050db54fca7f4c" + url: "https://pub.dev" source: hosted version: "2.0.10" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos - url: "https://pub.dartlang.org" + sha256: "2a97e7fbb7ae9dcd0dfc1220a78e9ec3e71da691912e617e8715ff2a13086ae8" + url: "https://pub.dev" source: hosted version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "27dc7a224fcd07444cb5e0e60423ccacea3e13cf00fc5282ac2c918132da931d" + url: "https://pub.dev" source: hosted version: "2.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "075f927ebbab4262ace8d0b283929ac5410c0ac4e7fc123c76429564facfb757" + url: "https://pub.dev" source: hosted version: "2.1.2" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: "0edfe20fdabaf4cd97e234f66a509f8dc7dc9c55ee2c226027be7be86de612c3" + url: "https://pub.dev" source: hosted version: "3.6.0" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: "93982981971e812c94d4a6fa3a57b89f9ec12b38b6380cd3c1370c3b01e4580e" + url: "https://pub.dev" source: hosted version: "3.1.0" shared_preferences: dependency: transitive description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "76917b7d4b9526b2ba416808a7eb9fb2863c1a09cf63ec85f1453da240fa818a" + url: "https://pub.dev" source: hosted version: "2.0.15" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "853801ce6ba7429ec4e923e37317f32a57c903de50b8c33ffcfbdb7e6f0dd39c" + url: "https://pub.dev" source: hosted version: "2.0.12" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.dartlang.org" + sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: "28aefc1261746e7bad3d09799496054beb84e8c4ffcdfed7734e17b4ada459a5" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - url: "https://pub.dartlang.org" + sha256: fbb94bf296576f49be37a1496d5951796211a8db0aa22cc0d68c46440dad808c + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d" + url: "https://pub.dev" source: hosted version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "97f7ab9a7da96d9cf19581f5de520ceb529548498bd6b5e0ccd02d68a0d15eba" + url: "https://pub.dev" source: hosted version: "2.1.1" sky_engine: @@ -438,16 +485,18 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stack_wallet_backup: dependency: transitive description: @@ -461,65 +510,74 @@ packages: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" tuple: dependency: transitive description: name: tuple - url: "https://pub.dartlang.org" + sha256: fe3ae4f0dca3f9aac0888e2e0d117b642ce283a82d7017b54136290c0a3b0dd3 + url: "https://pub.dev" source: hosted version: "2.0.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "1952a663c0e34fbde55916010d54bbb249bf5f2583113c497602f0ee01c6faa4" + url: "https://pub.dev" source: hosted version: "3.0.0" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: "060b6e1c891d956f72b5ac9463466c37cce3fa962a921532fc001e86fe93438e" + url: "https://pub.dev" source: hosted version: "0.2.0+1" sdks: - dart: ">=2.17.5 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=3.0.0" diff --git a/lib/view_model/send/output.dart b/lib/view_model/send/output.dart index a58dbe4cc5..25bb52f599 100644 --- a/lib/view_model/send/output.dart +++ b/lib/view_model/send/output.dart @@ -6,8 +6,6 @@ import 'package:flutter_libmonero/monero/monero.dart'; import 'package:intl/intl.dart'; import 'package:mobx/mobx.dart'; -import '../../wownero/wownero.dart'; - part 'output.g.dart'; const String cryptoNumberPattern = '0.0'; @@ -65,10 +63,6 @@ abstract class OutputBase with Store { case WalletType.monero: _amount = monero.formatterMoneroParseAmount(amount: _cryptoAmount); break; - case WalletType.wownero: - _amount = - wownero.formatterWowneroParseAmount(amount: _cryptoAmount); - break; default: break; } @@ -94,10 +88,6 @@ abstract class OutputBase with Store { if (_wallet.type == WalletType.monero) { return monero.formatterMoneroAmountToDouble(amount: fee); } - - if (_wallet.type == WalletType.wownero) { - return wownero.formatterWowneroAmountToDouble(amount: fee); - } } catch (e) { print(e.toString()); } diff --git a/lib/wownero/cw_wownero.dart b/lib/wownero/cw_wownero.dart deleted file mode 100644 index 284b5e4247..0000000000 --- a/lib/wownero/cw_wownero.dart +++ /dev/null @@ -1,309 +0,0 @@ -part of 'wownero.dart'; - -class CWWowneroAccountList extends WowneroAccountList { - CWWowneroAccountList(this._wallet); - Object _wallet; - - @override - @computed - ObservableList get accounts { - final wowneroWallet = _wallet as WowneroWallet; - final accounts = wowneroWallet.walletAddresses.accountList.accounts - .map((acc) => Account(id: acc.id, label: acc.label)) - .toList(); - return ObservableList.of(accounts); - } - - @override - void update(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.accountList.update(); - } - - @override - void refresh(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.accountList.refresh(); - } - - @override - List getAll(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.walletAddresses.accountList - .getAll() - .map((acc) => Account(id: acc.id, label: acc.label)) - .toList(); - } - - @override - Future addAccount(Object wallet, {String? label}) async { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.accountList.addAccount(label: label); - } - - @override - Future setLabelAccount(Object wallet, - {int? accountIndex, String? label}) async { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.accountList - .setLabelAccount(accountIndex: accountIndex, label: label); - } -} - -class CWWowneroSubaddressList extends WowneroSubaddressList { - CWWowneroSubaddressList(this._wallet); - Object _wallet; - - @override - @computed - ObservableList get subaddresses { - final wowneroWallet = _wallet as WowneroWallet; - final subAddresses = wowneroWallet - .walletAddresses.subaddressList.subaddresses! - .map((sub) => - Subaddress(id: sub.id, address: sub.address, label: sub.label)) - .toList(); - return ObservableList.of(subAddresses); - } - - @override - void update(Object wallet, {int? accountIndex}) { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.subaddressList - .update(accountIndex: accountIndex); - } - - @override - void refresh(Object wallet, {int? accountIndex}) { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.subaddressList - .refresh(accountIndex: accountIndex); - } - - @override - List getAll(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.walletAddresses.subaddressList - .getAll() - .map((sub) => - Subaddress(id: sub.id, label: sub.label, address: sub.address)) - .toList(); - } - - @override - Future addSubaddress(Object wallet, - {int? accountIndex, String? label}) async { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.subaddressList - .addSubaddress(accountIndex: accountIndex, label: label); - } - - @override - Future setLabelSubaddress(Object wallet, - {int? accountIndex, int? addressIndex, String? label}) async { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.subaddressList.setLabelSubaddress( - accountIndex: accountIndex, addressIndex: addressIndex, label: label); - } -} - -class CWWowneroWalletDetails extends WowneroWalletDetails { - CWWowneroWalletDetails(this._wallet); - Object _wallet; - - @computed - Account get account { - final wowneroWallet = _wallet as WowneroWallet; - final acc = wowneroWallet.walletAddresses.account!; - return Account(id: acc.id, label: acc.label); - } - - @computed - WowneroBalance get balance { - final wowneroWallet = _wallet as WowneroWallet; - final balance = wowneroWallet.balance; - var fullBalance = 0; - var unlockedBalance = 0; - // TODO: put actual values - balance?.entries.forEach((element) { - unlockedBalance += element.value.unlockedBalance; - fullBalance += element.value.fullBalance; - }); - return WowneroBalance( - fullBalance: fullBalance, unlockedBalance: unlockedBalance); - //return WowneroBalance( - // fullBalance: balance.fullBalance, - // unlockedBalance: balance.unlockedBalance); - } -} - -class CWWownero extends Wownero { - WowneroAccountList getAccountList(Object wallet) { - return CWWowneroAccountList(wallet); - } - - WowneroSubaddressList getSubaddressList(Object wallet) { - return CWWowneroSubaddressList(wallet); - } - - TransactionHistoryBase? getTransactionHistory(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.transactionHistory; - } - - WowneroWalletDetails getWowneroWalletDetails(Object wallet) { - return CWWowneroWalletDetails(wallet); - } - - int getHeightByDate({DateTime? date}) { - return getWowneroHeightByDate(date: date!); - } - - TransactionPriority getDefaultTransactionPriority() { - return MoneroTransactionPriority.slow; - } - - TransactionPriority? deserializeMoneroTransactionPriority({int? raw}) { - return MoneroTransactionPriority.deserialize(raw: raw); - } - - List getTransactionPriorities() { - return MoneroTransactionPriority.all; - } - - List getWowneroWordList(String language, {int seedWordsLength = 14}) { - switch (language.toLowerCase()) { - case 'english': - switch (seedWordsLength) { - case 25: - return EnglishMnemonics25.words; - default: - return EnglishMnemonics14.words; - } - default: - switch (seedWordsLength) { - case 25: - return EnglishMnemonics25.words; - default: - return EnglishMnemonics14.words; - } - } - } - - WalletCredentials createWowneroRestoreWalletFromKeysCredentials( - {String? name, - String? spendKey, - String? viewKey, - String? address, - String? password, - String? language, - int? height}) { - return WowneroRestoreWalletFromKeysCredentials( - name: name, - spendKey: spendKey, - viewKey: viewKey, - address: address, - password: password, - language: language, - height: height); - } - - WalletCredentials createWowneroRestoreWalletFromSeedCredentials( - {String? name, String? password, int? height, String? mnemonic}) { - return WowneroRestoreWalletFromSeedCredentials( - name: name, password: password, height: height, mnemonic: mnemonic); - } - - WalletCredentials createWowneroNewWalletCredentials( - {String? name, - String? password, - String? language, - int seedWordsLength = 14}) { - return WowneroNewWalletCredentials( - name: name, - password: password, - language: language, - seedWordsLength: seedWordsLength); - } - - Map getKeys(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - final keys = wowneroWallet.keys; - return { - 'privateSpendKey': keys.privateSpendKey, - 'privateViewKey': keys.privateViewKey, - 'publicSpendKey': keys.publicSpendKey, - 'publicViewKey': keys.publicViewKey - }; - } - - Object createWowneroTransactionCreationCredentials( - {List? outputs, TransactionPriority? priority}) { - return WowneroTransactionCreationCredentials( - outputs: outputs! - .map((out) => OutputInfo( - fiatAmount: out.fiatAmount, - cryptoAmount: out.cryptoAmount, - address: out.address, - note: out.note, - sendAll: out.sendAll, - extractedAddress: out.extractedAddress, - isParsedAddress: out.isParsedAddress, - formattedCryptoAmount: out.formattedCryptoAmount)) - .toList(), - priority: priority as MoneroTransactionPriority); - } - - String formatterWowneroAmountToString({int? amount}) { - return wowneroAmountToString(amount: amount!); - } - - double formatterWowneroAmountToDouble({int? amount}) { - return wowneroAmountToDouble(amount: amount!); - } - - int formatterWowneroParseAmount({String? amount}) { - return wowneroParseAmount(amount: amount!); - } - - Account getCurrentAccount(Object wallet) { - final wowneroWallet = wallet as WowneroWallet; - final acc = wowneroWallet.walletAddresses.account!; - return Account(id: acc.id, label: acc.label); - } - - void setCurrentAccount(Object wallet, int id, String label) { - final wowneroWallet = wallet as WowneroWallet; - wowneroWallet.walletAddresses.account = - wownero_account.Account(id: id, label: label); - } - - void onStartup() { - wownero_wallet_api.onStartup(); - } - - int? getTransactionInfoAccountId(TransactionInfo tx) { - final wowneroTransactionInfo = tx as WowneroTransactionInfo; - return wowneroTransactionInfo.accountIndex; - } - - WalletService createWowneroWalletService(Box walletInfoSource) { - return WowneroWalletService(walletInfoSource); - } - - String getTransactionAddress( - Object wallet, int accountIndex, int addressIndex) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.getTransactionAddress(accountIndex, addressIndex); - } - - String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.getSubaddressLabel(accountIndex, addressIndex); - } - - bool validateAddress(Object wallet, String address) { - final wowneroWallet = wallet as WowneroWallet; - return wowneroWallet.validateAddress(address); - } -} diff --git a/lib/wownero/wownero.dart b/lib/wownero/wownero.dart deleted file mode 100644 index e5c511843d..0000000000 --- a/lib/wownero/wownero.dart +++ /dev/null @@ -1,150 +0,0 @@ -import 'package:cw_core/account.dart' as wownero_account; -import 'package:cw_core/balance.dart'; -import 'package:cw_core/monero_transaction_priority.dart'; -import 'package:cw_core/output_info.dart'; -import 'package:cw_core/transaction_history.dart'; -import 'package:cw_core/transaction_info.dart'; -import 'package:cw_core/transaction_priority.dart'; -import 'package:cw_core/wallet_credentials.dart'; -import 'package:cw_core/wallet_info.dart'; -import 'package:cw_core/wallet_service.dart'; -import 'package:cw_wownero/api/wallet.dart' as wownero_wallet_api; -//import 'package:cw_wownero/mnemonics/english.dart'; -import 'package:cw_wownero/mnemonics/english14.dart'; -import 'package:cw_wownero/mnemonics/english25.dart'; -import 'package:cw_wownero/wownero_amount_format.dart'; -import 'package:cw_wownero/wownero_transaction_creation_credentials.dart'; -import 'package:cw_wownero/wownero_transaction_info.dart'; -import 'package:cw_wownero/wownero_wallet.dart'; -import 'package:cw_wownero/wownero_wallet_service.dart'; -import 'package:flutter_libmonero/view_model/send/output.dart'; -import 'package:hive/hive.dart'; -import 'package:cw_core/get_height_by_date.dart'; -import 'package:mobx/mobx.dart'; - -part 'cw_wownero.dart'; - -Wownero wownero = CWWownero(); - -class Account { - Account({this.id, this.label}); - final int? id; - final String? label; -} - -class Subaddress { - Subaddress({this.id, this.accountId, this.label, this.address}); - final int? id; - final int? accountId; - final String? label; - final String? address; -} - -class WowneroBalance extends Balance { - WowneroBalance({required this.fullBalance, required this.unlockedBalance}) - : formattedFullBalance = - wownero.formatterWowneroAmountToString(amount: fullBalance), - formattedUnlockedBalance = - wownero.formatterWowneroAmountToString(amount: unlockedBalance), - super(unlockedBalance, fullBalance); - - WowneroBalance.fromString( - {required this.formattedFullBalance, - required this.formattedUnlockedBalance}) - : fullBalance = - wownero.formatterWowneroParseAmount(amount: formattedFullBalance), - unlockedBalance = wownero.formatterWowneroParseAmount( - amount: formattedUnlockedBalance), - super( - wownero.formatterWowneroParseAmount( - amount: formattedUnlockedBalance), - wownero.formatterWowneroParseAmount(amount: formattedFullBalance)); - - final int fullBalance; - final int unlockedBalance; - final String formattedFullBalance; - final String formattedUnlockedBalance; - - @override - String get formattedAvailableBalance => formattedUnlockedBalance; - - @override - String get formattedAdditionalBalance => formattedFullBalance; -} - -abstract class WowneroWalletDetails { - @observable - Account? account; - - @observable - WowneroBalance? balance; -} - -abstract class Wownero { - WowneroAccountList getAccountList(Object wallet); - - WowneroSubaddressList getSubaddressList(Object wallet); - - TransactionHistoryBase? getTransactionHistory(Object wallet); - - WowneroWalletDetails getWowneroWalletDetails(Object wallet); - - String getTransactionAddress(Object wallet, int accountIndex, int addressIndex); - - int getHeightByDate({DateTime? date}); - - String getSubaddressLabel(Object wallet, int accountIndex, int addressIndex); - - bool validateAddress(Object wallet, String address); - - TransactionPriority getDefaultTransactionPriority(); - TransactionPriority? deserializeMoneroTransactionPriority({int raw}); - List getTransactionPriorities(); - List getWowneroWordList(String language, {int seedWordsLength = 14}); - - WalletCredentials createWowneroRestoreWalletFromKeysCredentials( - {String name, - String spendKey, - String viewKey, - String address, - String password, - String language, - int height}); - WalletCredentials createWowneroRestoreWalletFromSeedCredentials( - {String name, String password, int height, String mnemonic}); - WalletCredentials createWowneroNewWalletCredentials( - {String name, - String password, - String language, - int seedWordsLength = 14}); - Map getKeys(Object wallet); - Object createWowneroTransactionCreationCredentials( - {List outputs, TransactionPriority priority}); - String formatterWowneroAmountToString({int? amount}); - double formatterWowneroAmountToDouble({int? amount}); - int formatterWowneroParseAmount({String? amount}); - Account getCurrentAccount(Object wallet); - void setCurrentAccount(Object wallet, int id, String label); - void onStartup(); - int? getTransactionInfoAccountId(TransactionInfo tx); - WalletService createWowneroWalletService(Box walletInfoSource); -} - -abstract class WowneroSubaddressList { - ObservableList get subaddresses; - void update(Object wallet, {int accountIndex}); - void refresh(Object wallet, {int accountIndex}); - List getAll(Object wallet); - Future addSubaddress(Object wallet, {int accountIndex, String label}); - Future setLabelSubaddress(Object wallet, - {int accountIndex, int addressIndex, String label}); -} - -abstract class WowneroAccountList { - ObservableList get accounts; - void update(Object wallet); - void refresh(Object wallet); - List getAll(Object wallet); - Future addAccount(Object wallet, {String label}); - Future setLabelAccount(Object wallet, {int accountIndex, String label}); -} diff --git a/pubspec.lock b/pubspec.lock index 0c4cee73d9..c033f2f836 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,77 +5,88 @@ packages: dependency: "direct main" description: name: archive - url: "https://pub.dartlang.org" + sha256: eb33140ede1b4039f4ad631f7bf3cfa58e24514e8bf87184bc32f17541af87fc + url: "https://pub.dev" source: hosted version: "3.3.0" args: dependency: transitive description: name: args - url: "https://pub.dartlang.org" + sha256: b003c3098049a51720352d219b0bb5f219b60fbfb68e7a4748139a06a5676515 + url: "https://pub.dev" source: hosted version: "2.3.1" asn1lib: dependency: transitive description: name: asn1lib - url: "https://pub.dartlang.org" + sha256: c273725e171cea7e69c8953181202a2850297bcc7617916d83b396cd791a2dcd + url: "https://pub.dev" source: hosted version: "1.1.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: bfe67ef28df125b7dddcea62755991f807aa39a2492a23e1550161692950bbe0 + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.10.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: e6a326c8af69605aec75ed6c187d06b349707a27fbff8222ca9cc2cff167975c + url: "https://pub.dev" source: hosted version: "1.2.1" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: cfc915e6923fe5ce6e153b0723c753045de46de1b4d63771530504004a45fae0 + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "1.17.0" convert: dependency: transitive description: name: convert - url: "https://pub.dartlang.org" + sha256: "196284f26f69444b7f5c50692b55ec25da86d9e500451dc09333bf2e3ad69259" + url: "https://pub.dev" source: hosted version: "3.0.2" crypto: dependency: transitive description: name: crypto - url: "https://pub.dartlang.org" + sha256: aa274aa7774f8964e4f4f38cc994db7b6158dd36e9187aaceaddc994b35c6c67 + url: "https://pub.dev" source: hosted version: "3.0.2" cryptography: dependency: transitive description: name: cryptography - url: "https://pub.dartlang.org" + sha256: e0e37f79665cd5c86e8897f9abe1accfe813c0cc5299dab22256e22fddc1fef8 + url: "https://pub.dev" source: hosted version: "2.0.5" cw_core: @@ -99,46 +110,44 @@ packages: relative: true source: path version: "0.0.1" - cw_wownero: - dependency: "direct main" - description: - path: cw_wownero - relative: true - source: path - version: "0.0.1" encrypt: dependency: transitive description: name: encrypt - url: "https://pub.dartlang.org" + sha256: "4fd4e4fdc21b9d7d4141823e1e6515cd94e7b8d84749504c232999fba25d9bbb" + url: "https://pub.dev" source: hosted version: "5.0.1" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: "direct main" description: name: ffi - url: "https://pub.dartlang.org" + sha256: a38574032c5f1dd06c4aee541789906c12ccaab8ba01446e800d9c5b79c4a978 + url: "https://pub.dev" source: hosted version: "2.0.1" file: dependency: transitive description: name: file - url: "https://pub.dartlang.org" + sha256: b69516f2c26a5bcac4eee2e32512e1a5205ab312b3536c1c1227b2b942b5f9ad + url: "https://pub.dev" source: hosted version: "6.1.2" fixnum: dependency: transitive description: name: fixnum - url: "https://pub.dartlang.org" + sha256: "04be3e934c52e082558cc9ee21f42f5c1cd7a1262f4c63cd0357c08d5bba81ec" + url: "https://pub.dev" source: hosted version: "1.0.1" flutter: @@ -150,56 +159,64 @@ packages: dependency: "direct dev" description: name: flutter_lints - url: "https://pub.dartlang.org" + sha256: aeb0b80a8b3709709c9cc496cdc027c5b3216796bc0af0ce1007eaf24464fd4c + url: "https://pub.dev" source: hosted version: "2.0.1" flutter_mobx: dependency: transitive description: name: flutter_mobx - url: "https://pub.dartlang.org" + sha256: "906d858f3883140624c41eba5d60d0134ab94f565a39fb2a18439bf920931035" + url: "https://pub.dev" source: hosted version: "2.0.6+1" flutter_secure_storage: dependency: "direct main" description: name: flutter_secure_storage - url: "https://pub.dartlang.org" + sha256: "1b7c2f80ee41861543bc63fee56122a114129c15234731312418ca1eda7d3d7f" + url: "https://pub.dev" source: hosted version: "5.0.2" flutter_secure_storage_linux: dependency: transitive description: name: flutter_secure_storage_linux - url: "https://pub.dartlang.org" + sha256: c6e57a7c000a95e58b4282500cf88df61c57c3b199a390b4f6b458abc40aba0a + url: "https://pub.dev" source: hosted version: "1.1.0" flutter_secure_storage_macos: dependency: transitive description: name: flutter_secure_storage_macos - url: "https://pub.dartlang.org" + sha256: e3c29bf81b8179477d662a9c7c15ea4402876a1eafcb02407227d46bbb86cd20 + url: "https://pub.dev" source: hosted version: "1.1.0" flutter_secure_storage_platform_interface: dependency: transitive description: name: flutter_secure_storage_platform_interface - url: "https://pub.dartlang.org" + sha256: "9af003dec5ba9f959300fd76ac8adf5608fbfbc957cdd7a987af206a8e073b32" + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_secure_storage_web: dependency: transitive description: name: flutter_secure_storage_web - url: "https://pub.dartlang.org" + sha256: "926716d84eb45220cb1783af629093301613f5e5b51da7c1813e430d69bd716f" + url: "https://pub.dev" source: hosted version: "1.0.2" flutter_secure_storage_windows: dependency: transitive description: name: flutter_secure_storage_windows - url: "https://pub.dartlang.org" + sha256: cf9fd49c2807f80dc01f449592e1e7971a3697d1e248b653efb8323536dc2961 + url: "https://pub.dev" source: hosted version: "1.1.2" flutter_test: @@ -216,217 +233,248 @@ packages: dependency: transitive description: name: hive - url: "https://pub.dartlang.org" + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" source: hosted version: "2.2.3" http: dependency: transitive description: name: http - url: "https://pub.dartlang.org" + sha256: "2ed163531e071c2c6b7c659635112f24cb64ecbebf6af46b550d536c0b1aa112" + url: "https://pub.dev" source: hosted version: "0.13.4" http_parser: dependency: transitive description: name: http_parser - url: "https://pub.dartlang.org" + sha256: db3060f22889f3d9d55f6a217565486737037eec3609f7f3eca4d0c67ee0d8a0 + url: "https://pub.dev" source: hosted version: "4.0.1" intl: dependency: transitive description: name: intl - url: "https://pub.dartlang.org" + sha256: "910f85bce16fb5c6f614e117efa303e85a1731bb0081edf3604a2ae6e9a3cc91" + url: "https://pub.dev" source: hosted version: "0.17.0" js: dependency: transitive description: name: js - url: "https://pub.dartlang.org" + sha256: "5528c2f391ededb7775ec1daa69e65a2d61276f7552de2b5f7b8d34ee9fd4ab7" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.6.5" lints: dependency: transitive description: name: lints - url: "https://pub.dartlang.org" + sha256: "5cfd6509652ff5e7fe149b6df4859e687fca9048437857cb2e65c8d780f396e3" + url: "https://pub.dev" source: hosted version: "2.0.0" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: "16db949ceee371e9b99d22f88fa3a73c4e59fd0afed0bd25fc336eb76c198b72" + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.13" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: "6c268b42ed578a53088d834796959e4a1814b5e9e164f147f580a386e5decf42" + url: "https://pub.dev" source: hosted version: "1.8.0" mobx: dependency: transitive description: name: mobx - url: "https://pub.dartlang.org" + sha256: e287b19fb09a6e8537bcce36a8628153dd39174f11003fd07491869fd705c27b + url: "https://pub.dev" source: hosted version: "2.0.7+4" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: db9d4f58c908a4ba5953fcee2ae317c94889433e5024c27ce74a37f94267945b + url: "https://pub.dev" source: hosted version: "1.8.2" path_provider: dependency: transitive description: name: path_provider - url: "https://pub.dartlang.org" + sha256: "050e8e85e4b7fecdf2bb3682c1c64c4887a183720c802d323de8a5fd76d372dd" + url: "https://pub.dev" source: hosted version: "2.0.11" path_provider_android: dependency: transitive description: name: path_provider_android - url: "https://pub.dartlang.org" + sha256: cf7c403a541fc68cd398fb91a7eea8ec234813547d5b55245eed644d1246c5d8 + url: "https://pub.dev" source: hosted version: "2.0.16" path_provider_ios: dependency: transitive description: name: path_provider_ios - url: "https://pub.dartlang.org" + sha256: "641df59948e0fda05ca71f1dd6768d6da7f0ceb52aab734bf9050db54fca7f4c" + url: "https://pub.dev" source: hosted version: "2.0.10" path_provider_linux: dependency: transitive description: name: path_provider_linux - url: "https://pub.dartlang.org" + sha256: ab0987bf95bc591da42dffb38c77398fc43309f0b9b894dcc5d6f40c4b26c379 + url: "https://pub.dev" source: hosted version: "2.1.7" path_provider_macos: dependency: transitive description: name: path_provider_macos - url: "https://pub.dartlang.org" + sha256: "2a97e7fbb7ae9dcd0dfc1220a78e9ec3e71da691912e617e8715ff2a13086ae8" + url: "https://pub.dev" source: hosted version: "2.0.6" path_provider_platform_interface: dependency: transitive description: name: path_provider_platform_interface - url: "https://pub.dartlang.org" + sha256: "27dc7a224fcd07444cb5e0e60423ccacea3e13cf00fc5282ac2c918132da931d" + url: "https://pub.dev" source: hosted version: "2.0.4" path_provider_windows: dependency: transitive description: name: path_provider_windows - url: "https://pub.dartlang.org" + sha256: bcabbe399d4042b8ee687e17548d5d3f527255253b4a639f5f8d2094a9c2b45c + url: "https://pub.dev" source: hosted version: "2.1.3" platform: dependency: transitive description: name: platform - url: "https://pub.dartlang.org" + sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + url: "https://pub.dev" source: hosted version: "3.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "075f927ebbab4262ace8d0b283929ac5410c0ac4e7fc123c76429564facfb757" + url: "https://pub.dev" source: hosted version: "2.1.2" pointycastle: dependency: transitive description: name: pointycastle - url: "https://pub.dartlang.org" + sha256: "0edfe20fdabaf4cd97e234f66a509f8dc7dc9c55ee2c226027be7be86de612c3" + url: "https://pub.dev" source: hosted version: "3.6.0" process: dependency: transitive description: name: process - url: "https://pub.dartlang.org" + sha256: "53fd8db9cec1d37b0574e12f07520d582019cb6c44abf5479a01505099a34a09" + url: "https://pub.dev" source: hosted version: "4.2.4" quiver: dependency: transitive description: name: quiver - url: "https://pub.dartlang.org" + sha256: "93982981971e812c94d4a6fa3a57b89f9ec12b38b6380cd3c1370c3b01e4580e" + url: "https://pub.dev" source: hosted version: "3.1.0" shared_preferences: dependency: "direct main" description: name: shared_preferences - url: "https://pub.dartlang.org" + sha256: "76917b7d4b9526b2ba416808a7eb9fb2863c1a09cf63ec85f1453da240fa818a" + url: "https://pub.dev" source: hosted version: "2.0.15" shared_preferences_android: dependency: transitive description: name: shared_preferences_android - url: "https://pub.dartlang.org" + sha256: "853801ce6ba7429ec4e923e37317f32a57c903de50b8c33ffcfbdb7e6f0dd39c" + url: "https://pub.dev" source: hosted version: "2.0.12" shared_preferences_ios: dependency: transitive description: name: shared_preferences_ios - url: "https://pub.dartlang.org" + sha256: "585a14cefec7da8c9c2fb8cd283a3bb726b4155c0952afe6a0caaa7b2272de34" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_linux: dependency: transitive description: name: shared_preferences_linux - url: "https://pub.dartlang.org" + sha256: "28aefc1261746e7bad3d09799496054beb84e8c4ffcdfed7734e17b4ada459a5" + url: "https://pub.dev" source: hosted version: "2.1.1" shared_preferences_macos: dependency: transitive description: name: shared_preferences_macos - url: "https://pub.dartlang.org" + sha256: fbb94bf296576f49be37a1496d5951796211a8db0aa22cc0d68c46440dad808c + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_platform_interface: dependency: transitive description: name: shared_preferences_platform_interface - url: "https://pub.dartlang.org" + sha256: "992f0fdc46d0a3c0ac2e5859f2de0e577bbe51f78a77ee8f357cbe626a2ad32d" + url: "https://pub.dev" source: hosted version: "2.0.0" shared_preferences_web: dependency: transitive description: name: shared_preferences_web - url: "https://pub.dartlang.org" + sha256: a4b5bc37fe1b368bbc81f953197d55e12f49d0296e7e412dfe2d2d77d6929958 + url: "https://pub.dev" source: hosted version: "2.0.4" shared_preferences_windows: dependency: transitive description: name: shared_preferences_windows - url: "https://pub.dartlang.org" + sha256: "97f7ab9a7da96d9cf19581f5de520ceb529548498bd6b5e0ccd02d68a0d15eba" + url: "https://pub.dev" source: hosted version: "2.1.1" sky_engine: @@ -438,16 +486,18 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.0" stack_wallet_backup: dependency: "direct main" description: @@ -461,65 +511,74 @@ packages: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: ad540f65f92caa91bf21dfc8ffb8c589d6e4dc0c2267818b4cc2792857706206 + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.4.16" tuple: dependency: transitive description: name: tuple - url: "https://pub.dartlang.org" + sha256: fe3ae4f0dca3f9aac0888e2e0d117b642ce283a82d7017b54136290c0a3b0dd3 + url: "https://pub.dev" source: hosted version: "2.0.0" typed_data: dependency: transitive description: name: typed_data - url: "https://pub.dartlang.org" + sha256: "26f87ade979c47a150c9eaab93ccd2bebe70a27dc0b4b29517f2904f04eb11a5" + url: "https://pub.dev" source: hosted version: "1.3.1" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "1952a663c0e34fbde55916010d54bbb249bf5f2583113c497602f0ee01c6faa4" + url: "https://pub.dev" source: hosted version: "3.0.0" xdg_directories: dependency: transitive description: name: xdg_directories - url: "https://pub.dartlang.org" + sha256: "060b6e1c891d956f72b5ac9463466c37cce3fa962a921532fc001e86fe93438e" + url: "https://pub.dev" source: hosted version: "0.2.0+1" sdks: - dart: ">=2.17.5 <3.0.0" + dart: ">=2.18.0 <3.0.0" flutter: ">=3.0.0" diff --git a/pubspec.yaml b/pubspec.yaml index c5058bca33..c918e5c31c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,9 +22,6 @@ dependencies: cw_monero: path: ./cw_monero - cw_wownero: - path: ./cw_wownero - cw_shared_external: path: ./cw_shared_external diff --git a/scripts/android/build_all.sh b/scripts/android/build_all.sh index 0eb4ff4809..66b96190f0 100755 --- a/scripts/android/build_all.sh +++ b/scripts/android/build_all.sh @@ -2,7 +2,5 @@ ./install_ndk.sh ./build_monero_all.sh -./build_wownero.sh -./build_wownero_seed.sh ./copy_monero_deps.sh diff --git a/scripts/android/build_wownero.sh b/scripts/android/build_wownero.sh deleted file mode 100755 index 1160b51172..0000000000 --- a/scripts/android/build_wownero.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/sh - -. ./config.sh - -WOWNERO_URL="https://git.wownero.com/wownero/wownero.git" -WOWNERO_VERSION=v0.10.2.0 -WOWNERO_SHA_HEAD="ab42be18f25c7bdfa6171a890ad11ae262bc44d0" -WOWNERO_SRC_DIR=${WORKDIR}/wownero - -echo "Cloning wownero from - $WOWNERO_URL to - $WOWNERO_DIR_PATH" -git clone ${WOWNERO_URL} ${WOWNERO_SRC_DIR} --branch ${WOWNERO_VERSION} -cd $WOWNERO_SRC_DIR -git reset --hard $WOWNERO_SHA_HEAD -git submodule init -git submodule update - -for arch in "aarch" "aarch64" "i686" "x86_64" -do -FLAGS="" -PREFIX=${WORKDIR}/prefix_${arch} -DEST_LIB_DIR=${PREFIX}/lib/wownero -DEST_INCLUDE_DIR=${PREFIX}/include/wownero -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" -ANDROID_STANDALONE_TOOLCHAIN_PATH="${TOOLCHAIN_BASE_DIR}_${arch}" -PATH="${ANDROID_STANDALONE_TOOLCHAIN_PATH}/bin:${ORIGINAL_PATH}" - -mkdir -p $DEST_LIB_DIR -mkdir -p $DEST_INCLUDE_DIR - -case $arch in - "aarch" ) - CLANG=arm-linux-androideabi-clang - CXXLANG=arm-linux-androideabi-clang++ - BUILD_64=OFF - TAG="android-armv7" - ARCH="armv7-a" - ARCH_ABI="armeabi-v7a" - FLAGS="-D CMAKE_ANDROID_ARM_MODE=ON -D NO_AES=true";; - "aarch64" ) - CLANG=aarch64-linux-androideabi-clang - CXXLANG=aarch64-linux-androideabi-clang++ - BUILD_64=ON - TAG="android-armv8" - ARCH="armv8-a" - ARCH_ABI="arm64-v8a";; - "i686" ) - CLANG=i686-linux-androideabi-clang - CXXLANG=i686-linux-androideabi-clang++ - BUILD_64=OFF - TAG="android-x86" - ARCH="i686" - ARCH_ABI="x86";; - "x86_64" ) - CLANG=x86_64-linux-androideabi-clang - CXXLANG=x86_64-linux-androideabi-clang++ - BUILD_64=ON - TAG="android-x86_64" - ARCH="x86-64" - ARCH_ABI="x86_64";; -esac - -cd $WOWNERO_SRC_DIR -rm -rf ./build/release -mkdir -p ./build/release -cd ./build/release -CC=${CLANG} CXX=${CXXLANG} cmake -DCMAKE_ANDROID_NDK="${ANDROID_NDK_HOME}" -DANDROID_PLATFORM="android-${API}" -DCMAKE_SYSTEM_VERSION="${API}" -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D ANDROID=true -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} $FLAGS ../.. - -make wallet_api -j$THREADS -find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; - -cp -r ./lib/* $DEST_LIB_DIR -cp ../../src/wallet/api/wallet2_api.h $DEST_INCLUDE_DIR -done diff --git a/scripts/android/build_wownero_all.sh b/scripts/android/build_wownero_all.sh deleted file mode 100755 index 7763697f8e..0000000000 --- a/scripts/android/build_wownero_all.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -./build_iconv.sh -./build_boost.sh -./build_openssl.sh -./build_sodium.sh -./build_zmq.sh -./build_wownero.sh -./build_wownero_seed.sh \ No newline at end of file diff --git a/scripts/android/build_wownero_seed.sh b/scripts/android/build_wownero_seed.sh deleted file mode 100755 index 51a36e155f..0000000000 --- a/scripts/android/build_wownero_seed.sh +++ /dev/null @@ -1,66 +0,0 @@ -#!/bin/sh - -. ./config.sh - -SEED_DIR=$WORKDIR/seed -SEED_TAG=0.3.0 -SEED_COMMIT_HASH="ef6910b6bb3b61757c36e2e5db0927d75f1731c8" - -for arch in "aarch" "aarch64" "i686" "x86_64" -do - -FLAGS="" -PREFIX=$WORKDIR/prefix_${arch} -DEST_LIB_DIR=${PREFIX}/lib/ -DEST_INCLUDE_DIR=${PREFIX}/include/ -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" -ANDROID_STANDALONE_TOOLCHAIN_PATH="${TOOLCHAIN_BASE_DIR}_${arch}" -PATH="${ANDROID_STANDALONE_TOOLCHAIN_PATH}/bin:${ORIGINAL_PATH}" - -case $arch in - "aarch" ) - CLANG=arm-linux-androideabi-clang - CXXLANG=arm-linux-androideabi-clang++ - BUILD_64=OFF - TAG="android-armv7" - ARCH="armv7-a" - ARCH_ABI="armeabi-v7a" - FLAGS="-D CMAKE_ANDROID_ARM_MODE=ON";; - "aarch64" ) - CLANG=aarch64-linux-androideabi-clang - CXXLANG=aarch64-linux-androideabi-clang++ - BUILD_64=ON - TAG="android-armv8" - ARCH="armv8-a" - ARCH_ABI="arm64-v8a";; - "i686" ) - CLANG=i686-linux-androideabi-clang - CXXLANG=i686-linux-androideabi-clang++ - BUILD_64=OFF - TAG="android-x86" - ARCH="i686" - ARCH_ABI="x86";; - "x86_64" ) - CLANG=x86_64-linux-androideabi-clang - CXXLANG=x86_64-linux-androideabi-clang++ - BUILD_64=ON - TAG="android-x86_64" - ARCH="x86-64" - ARCH_ABI="x86_64";; -esac - -cd $WORKDIR - -rm -rf $SEED_DIR -git clone -b $SEED_TAG --depth 1 https://git.wownero.com/wowlet/wownero-seed.git $SEED_DIR -cd $SEED_DIR -git reset --hard $SEED_COMMIT_HASH - -CC={$CLANG} CXX={$CXXLANG} cmake -Bbuild -DCMAKE_ANDROID_NDK="${ANDROID_NDK_HOME}" -DANDROID_PLATFORM="android-${API}" -DCMAKE_SYSTEM_VERSION="${API}" -DCMAKE_INSTALL_PREFIX=${PREFIX} ARCH=${ARCH} -D CMAKE_BUILD_TYPE=Release -D CMAKE_SYSTEM_NAME="Android" -D CMAKE_ANDROID_STANDALONE_TOOLCHAIN="${ANDROID_STANDALONE_TOOLCHAIN_PATH}" -D CMAKE_ANDROID_ARCH_ABI=${ARCH_ABI} $FLAGS . - -make -Cbuild -j$THREADS -make -Cbuild install - -done - diff --git a/scripts/android/copy_monero_deps.sh b/scripts/android/copy_monero_deps.sh index 51d5036ec9..8a302291e6 100755 --- a/scripts/android/copy_monero_deps.sh +++ b/scripts/android/copy_monero_deps.sh @@ -12,7 +12,6 @@ sed -i "/\/\*${OS}_VERSION/c\\/\*${OS}_VERSION\*\/ const ${OS}_VERSION = \"$COMM WORKDIR="$(pwd)/"build CW_DIR="$(pwd)"/../../../flutter_libmonero CW_EXRTERNAL_DIR=${CW_DIR}/cw_shared_external/ios/External/android -CW_WOWNERO_EXTERNAL_DIR=${CW_DIR}/cw_wownero/ios/External/android CW_MONERO_EXTERNAL_DIR=${CW_DIR}/cw_monero/ios/External/android for arch in "aarch" "aarch64" "i686" "x86_64" do @@ -48,8 +47,5 @@ fi done mkdir -p ${CW_MONERO_EXTERNAL_DIR}/include -mkdir -p ${CW_WOWNERO_EXTERNAL_DIR}/include cp $CW_EXRTERNAL_DIR/x86/include/monero/wallet2_api.h ${CW_MONERO_EXTERNAL_DIR}/include -cp $CW_EXRTERNAL_DIR/x86/include/wownero/wallet2_api.h ${CW_WOWNERO_EXTERNAL_DIR}/include -cp -R $CW_EXRTERNAL_DIR/x86/include/wownero_seed ${CW_WOWNERO_EXTERNAL_DIR}/include diff --git a/scripts/ios/build_all.sh b/scripts/ios/build_all.sh index fbf0682e7f..c615a3fa84 100755 --- a/scripts/ios/build_all.sh +++ b/scripts/ios/build_all.sh @@ -2,6 +2,5 @@ ./install_missing_headers.sh ./build_monero_all.sh -./build_wownero_all.sh ./setup.sh diff --git a/scripts/ios/build_wownero.sh b/scripts/ios/build_wownero.sh deleted file mode 100755 index 7e4a5b58cc..0000000000 --- a/scripts/ios/build_wownero.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/sh - -. ./config.sh - -WOWNERO_URL="https://git.wownero.com/wownero/wownero.git" -WOWNERO_VERSION=v0.10.2.0 -WOWNERO_SHA_HEAD="ab42be18f25c7bdfa6171a890ad11ae262bc44d0" -WOWNERO_SRC_DIR="${EXTERNAL_IOS_SOURCE_DIR}/wownero" - -BUILD_TYPE=release -PREFIX=${EXTERNAL_IOS_DIR} -DEST_LIB_DIR=${EXTERNAL_IOS_LIB_DIR}/wownero -DEST_INCLUDE_DIR=${EXTERNAL_IOS_INCLUDE_DIR}/wownero - -echo "Cloning wownero from - $WOWNERO_URL to - $WOWNERO_SRC_DIR" -git clone ${WOWNERO_URL} ${WOWNERO_SRC_DIR} --branch ${WOWNERO_VERSION} -cd $WOWNERO_SRC_DIR -git reset --hard $WOWNERO_SHA_HEAD -git checkout $WOWNERO_VERSION -git submodule update --init --force -mkdir -p build -cd .. - -echo $DEST_LIB_DIR -mkdir -p $DEST_LIB_DIR -mkdir -p $DEST_INCLUDE_DIR - -ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ -z $INSTALL_PREFIX ]; then - INSTALL_PREFIX=${ROOT_DIR}/wownero -fi - -for arch in "arm64" #"armv7" "arm64" -do - -echo "Building IOS ${arch}" -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" - -case $arch in - "armv7" ) - DEST_LIB=../../lib-armv7;; - "arm64" ) - DEST_LIB=../../lib-armv8-a;; -esac - -rm -rf wownero/build > /dev/null - -mkdir -p wownero/build/${BUILD_TYPE} -pushd wownero/build/${BUILD_TYPE} -cmake -D IOS=ON \ - -DARCH=${arch} \ - -DCMAKE_BUILD_TYPE=${BUILD_TYPE} \ - -DSTATIC=ON \ - -DBUILD_GUI_DEPS=ON \ - -DINSTALL_VENDORED_LIBUNBOUND=ON \ - -DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX} \ - -DUSE_DEVICE_TREZOR=OFF \ - ../.. -make -j$(nproc) && make install -find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; -cp -r ./lib/* $DEST_LIB_DIR -cp src/cryptonote_basic/libcryptonote_basic.a ${DEST_LIB} -cp src/offshore/liboffshore.a ${DEST_LIB} -popd - -done - -#only for arm64 -cp ${WOWNERO_SRC_DIR}/lib-armv8-a/* $DEST_LIB_DIR -cp ${WOWNERO_SRC_DIR}/include/wallet/api/* $DEST_INCLUDE_DIR diff --git a/scripts/ios/build_wownero_all.sh b/scripts/ios/build_wownero_all.sh deleted file mode 100755 index f49026565f..0000000000 --- a/scripts/ios/build_wownero_all.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/sh - -. ./config.sh -# already done with build_monero_all.sh -#./install_missing_headers.sh -#./build_openssl.sh -#./build_boost.sh -#./build_sodium.sh -#./build_zmq.sh -./build_wownero.sh -./build_wownero_seed.sh \ No newline at end of file diff --git a/scripts/ios/build_wownero_seed.sh b/scripts/ios/build_wownero_seed.sh deleted file mode 100755 index 4c2d2a8554..0000000000 --- a/scripts/ios/build_wownero_seed.sh +++ /dev/null @@ -1,46 +0,0 @@ -#!/bin/sh - -. ./config.sh - -SEED_VERSION=0.3.0 -SEED_SRC_DIR="${EXTERNAL_IOS_SOURCE_DIR}/seed" -SEED_URL="https://git.wownero.com/wowlet/wownero-seed.git" -SEED_SHA_HEAD="ef6910b6bb3b61757c36e2e5db0927d75f1731c8" - -rm -rf "$SEED_SRC_DIR" > /dev/null - -echo "[*] cloning $SEED_URL" -git clone --branch ${SEED_VERSION} ${SEED_URL} ${SEED_SRC_DIR} -cd $SEED_SRC_DIR -git reset --hard $SEED_SHA_HEAD - -BUILD_TYPE=release -PREFIX=${EXTERNAL_IOS_DIR} -DEST_LIB_DIR=${EXTERNAL_IOS_LIB_DIR}/wownero-seed -DEST_INCLUDE_DIR=${EXTERNAL_IOS_INCLUDE_DIR}/wownero-seed - -ROOT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -if [ -z $INSTALL_PREFIX ]; then - INSTALL_PREFIX=${ROOT_DIR}/wownero-seed -fi - -for arch in "arm64" #"armv7" "arm64" -do - -echo "Building wownero-seed IOS ${arch}" -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" - -case $arch in - "armv7" ) - DEST_LIB=../../lib-armv7;; - "arm64" ) - DEST_LIB=../../lib-armv8-a;; -esac - -cmake -Bbuild -DCMAKE_INSTALL_PREFIX="${PREFIX}" -DCMAKE_SYSTEM_NAME="iOS" -DCMAKE_OSX_ARCHITECTURES="${arch}" . -make -Cbuild -j$(nproc) -make -Cbuild install -cp $CMAKE_LIBRARY_PATH/libwownero-seed.a $CMAKE_LIBRARY_PATH/wownero/libwownero-seed.a - -done diff --git a/scripts/ios/setup.sh b/scripts/ios/setup.sh index 51ad0cf6fa..0aa1102bef 100755 --- a/scripts/ios/setup.sh +++ b/scripts/ios/setup.sh @@ -14,35 +14,18 @@ cd $EXTERNAL_IOS_LIB_DIR LIBRANDOMX_PATH=${EXTERNAL_IOS_LIB_DIR}/monero/librandomx.a -if [ -f "$LIBRANDOMX_PATH" ]; then - cp $LIBRANDOMX_PATH ./wownero -fi - libtool -static -o libboost.a ./libboost_*.a -libtool -static -o libwownero.a ./wownero/*.a libtool -static -o libmonero.a ./monero/*.a -CW_WOWNERO_EXTERNAL_LIB=../../../../../cw_wownero/ios/External/ios/lib -CW_WOWNERO_EXTERNAL_INCLUDE=../../../../../cw_wownero/ios/External/ios/include CW_MONERO_EXTERNAL_LIB=../../../../../cw_monero/ios/External/ios/lib CW_MONERO_EXTERNAL_INCLUDE=../../../../../cw_monero/ios/External/ios/include mkdir -p $CW_MONERO_EXTERNAL_INCLUDE -mkdir -p $CW_WOWNERO_EXTERNAL_INCLUDE -mkdir -p $CW_WOWNERO_EXTERNAL_LIB mkdir -p $CW_MONERO_EXTERNAL_LIB -ln ./libboost.a ${CW_WOWNERO_EXTERNAL_LIB}/libboost.a -ln ./libcrypto.a ${CW_WOWNERO_EXTERNAL_LIB}/libcrypto.a -ln ./libssl.a ${CW_WOWNERO_EXTERNAL_LIB}/libssl.a -ln ./libsodium.a ${CW_WOWNERO_EXTERNAL_LIB}/libsodium.a -cp ./libwownero.a $CW_WOWNERO_EXTERNAL_LIB -cp ../include/wownero/* $CW_WOWNERO_EXTERNAL_INCLUDE -cp -r ../include/wownero_seed $CW_WOWNERO_EXTERNAL_INCLUDE - ln ./libboost.a ${CW_MONERO_EXTERNAL_LIB}/libboost.a ln ./libcrypto.a ${CW_MONERO_EXTERNAL_LIB}/libcrypto.a ln ./libssl.a ${CW_MONERO_EXTERNAL_LIB}/libssl.a diff --git a/scripts/linux/build_sharedfile.sh b/scripts/linux/build_sharedfile.sh index 9eb2684b87..1a37d92095 100755 --- a/scripts/linux/build_sharedfile.sh +++ b/scripts/linux/build_sharedfile.sh @@ -12,17 +12,10 @@ OS="LINUX" sed -i "/\/\*${OS}_VERSION/c\\/\*${OS}_VERSION\*\/ const ${OS}_VERSION = \"$COMMIT\";" $VERSIONS_FILE cd build mkdir monero_build -mkdir wownero_build MONERO_BUILD=$(pwd)/monero_build -WOWNERO_BUILD=$(pwd)/wownero_build cd $MONERO_BUILD cmake ../../cmakefiles/monero/${TYPES_OF_BUILD} make -j$(nproc) cp libcw_monero.so ../ -cd $WOWNERO_BUILD -cmake ../../cmakefiles/wownero/${TYPES_OF_BUILD} -make -j$(nproc) -cp libcw_wownero.so ../ - diff --git a/scripts/linux/build_wownero.sh b/scripts/linux/build_wownero.sh deleted file mode 100755 index 4b2d1383cc..0000000000 --- a/scripts/linux/build_wownero.sh +++ /dev/null @@ -1,58 +0,0 @@ -#!/bin/sh - -. ./config.sh - -WOWNERO_URL="https://git.wownero.com/wownero/wownero.git" -WOWNERO_VERSION=v0.10.2.0 -WOWNERO_SHA_HEAD="ab42be18f25c7bdfa6171a890ad11ae262bc44d0" -WOWNERO_SRC_DIR=${WORKDIR}/wownero - -echo "Cloning wownero from - $WOWNERO_URL to - $WOWNERO_DIR_PATH" -git clone ${WOWNERO_URL} ${WOWNERO_SRC_DIR} --branch ${WOWNERO_VERSION} -cd $WOWNERO_SRC_DIR -git reset --hard $WOWNERO_SHA_HEAD -git submodule init -git submodule update - -for arch in $TYPES_OF_BUILD -do -FLAGS="" -PREFIX=${WORKDIR}/prefix_${arch} -DEST_LIB_DIR=${PREFIX}/lib/wownero -DEST_INCLUDE_DIR=${PREFIX}/include/wownero -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" - -mkdir -p $DEST_LIB_DIR -mkdir -p $DEST_INCLUDE_DIR - -case $arch in - "x86_64" ) - BUILD_64=ON - TAG="linux-x86_64" - ARCH="x86-64" - ARCH_ABI="x86_64";; - "aarch64" ) - BUILD_64=ON - TAG="linux-aarch64" - ARCH="aarch64" - ARCH_ABI="aarch64";; -esac - -cd $WOWNERO_SRC_DIR -rm -rf ./build/release -mkdir -p ./build/release -cd ./build/release -cmake -DCMAKE_CXX_FLAGS="-fPIC" -D USE_DEVICE_TREZOR=OFF -D BUILD_GUI_DEPS=1 -D BUILD_TESTS=OFF -D ARCH=${ARCH} -D STATIC=ON -D BUILD_64=${BUILD_64} -D CMAKE_BUILD_TYPE=release -D INSTALL_VENDORED_LIBUNBOUND=ON -D BUILD_TAG=${TAG} $FLAGS ../.. - -make wallet_api -j$THREADS -find . -path ./lib -prune -o -name '*.a' -exec cp '{}' lib \; - -cp -r ./lib/* $DEST_LIB_DIR -cp ../../src/wallet/api/wallet2_api.h $DEST_INCLUDE_DIR - -CW_DIR="$(pwd)"/../../../../../../../flutter_libmonero -CW_WOWNERO_EXTERNAL_DIR=${CW_DIR}/cw_wownero/ios/External/android -mkdir -p $CW_WOWNERO_EXTERNAL_DIR/include -cp ../../src/wallet/api/wallet2_api.h ${CW_WOWNERO_EXTERNAL_DIR}/include -done diff --git a/scripts/linux/build_wownero_seed.sh b/scripts/linux/build_wownero_seed.sh deleted file mode 100755 index d63f2cc260..0000000000 --- a/scripts/linux/build_wownero_seed.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/bin/sh - -. ./config.sh - -SEED_DIR=$WORKDIR/seed -SEED_TAG=0.3.0 -SEED_COMMIT_HASH="ef6910b6bb3b61757c36e2e5db0927d75f1731c8" - -for arch in $TYPES_OF_BUILD -do - -FLAGS="" -PREFIX=$WORKDIR/prefix_${arch} -DEST_LIB_DIR=${PREFIX}/lib/ -DEST_INCLUDE_DIR=${PREFIX}/include/ -export CMAKE_INCLUDE_PATH="${PREFIX}/include" -export CMAKE_LIBRARY_PATH="${PREFIX}/lib" - -case $arch in - "x86_64" ) - BUILD_64=ON - TAG="linux-x86_64" - ARCH="x86-64" - ARCH_ABI="x86_64";; - "aarch64" ) - BUILD_64=ON - TAG="linux-aarch64" - ARCH="aarch64" - ARCH_ABI="aarch64";; -esac - -cd $WORKDIR - -rm -rf $SEED_DIR -git clone -b $SEED_TAG --depth 1 https://git.wownero.com/wowlet/wownero-seed.git $SEED_DIR -cd $SEED_DIR -git reset --hard $SEED_COMMIT_HASH - -CFLAGS=-fPIC CXXFLAGS=-fPIC cmake -Bbuild -DCMAKE_INSTALL_PREFIX=${PREFIX} ARCH=${ARCH} -D CMAKE_BUILD_TYPE=Release $FLAGS . - -make -Cbuild -j$THREADS -make -Cbuild install - -done - diff --git a/scripts/linux/copy_monero_deps.sh b/scripts/linux/copy_monero_deps.sh index 7871b7690a..fdb51e82de 100755 --- a/scripts/linux/copy_monero_deps.sh +++ b/scripts/linux/copy_monero_deps.sh @@ -4,7 +4,6 @@ WORKDIR="$(pwd)/"build CW_DIR="$(pwd)"/../../../flutter_libmonero CW_EXRTERNAL_DIR=${CW_DIR}/cw_shared_external/ios/External/android CW_MONERO_EXTERNAL_DIR=${CW_DIR}/cw_monero/ios/External/android -CW_WOWNERO_EXTERNAL_DIR=${CW_DIR}/cw_wownero/ios/External/android if [ -z ${TYPES_OF_BUILD+x} ]; then TYPES_OF_BUILD=x86_64; fi for arch in $TYPES_OF_BUILD @@ -35,10 +34,7 @@ cp -r ${PREFIX}/include/* $INCLUDE_DIR mkdir -p ${CW_MONERO_EXTERNAL_DIR}/include -mkdir -p ${CW_WOWNERO_EXTERNAL_DIR}/include cp $PREFIX/include/monero/wallet2_api.h ${CW_MONERO_EXTERNAL_DIR}/include -cp $PREFIX/include/wownero/wallet2_api.h ${CW_WOWNERO_EXTERNAL_DIR}/include -cp -R $PREFIX/include/wownero_seed ${CW_WOWNERO_EXTERNAL_DIR}/include done \ No newline at end of file From 69935a3aca892d764c5a461069e2daef4e491727 Mon Sep 17 00:00:00 2001 From: julian-CStack Date: Tue, 21 Mar 2023 17:33:38 -0600 Subject: [PATCH 2/6] remove wownero cmakelists --- .../cmakefiles/wownero/aarch64/CMakeLists.txt | 236 ------------------ .../cmakefiles/wownero/x86_64/CMakeLists.txt | 236 ------------------ 2 files changed, 472 deletions(-) delete mode 100644 scripts/linux/cmakefiles/wownero/aarch64/CMakeLists.txt delete mode 100644 scripts/linux/cmakefiles/wownero/x86_64/CMakeLists.txt diff --git a/scripts/linux/cmakefiles/wownero/aarch64/CMakeLists.txt b/scripts/linux/cmakefiles/wownero/aarch64/CMakeLists.txt deleted file mode 100644 index 85b26b6166..0000000000 --- a/scripts/linux/cmakefiles/wownero/aarch64/CMakeLists.txt +++ /dev/null @@ -1,236 +0,0 @@ -cmake_minimum_required(VERSION 3.4.1) - -add_library( cw_wownero - SHARED -# ../../../cw_wownero/android/jni/wownero_jni.cpp - ../../../../../cw_wownero/ios/Classes/wownero_api.cpp) - -set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../../../build) - -############ -# libsodium -############ - -add_library(sodium STATIC IMPORTED) -set_target_properties(sodium PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libsodium.a) - -############ -# OpenSSL -############ - -add_library(crypto STATIC IMPORTED) -set_target_properties(crypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libcrypto.a) - -add_library(ssl STATIC IMPORTED) -set_target_properties(ssl PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libssl.a) - -############ -# wownero-seed -############ - -add_library(wownero-seed STATIC IMPORTED) -set_target_properties(wownero-seed PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libwownero-seed.a) - -############ -# Boost -############ - -add_library(boost_chrono STATIC IMPORTED) -set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_chrono.a) - -add_library(boost_date_time STATIC IMPORTED) -set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_date_time.a) - -add_library(boost_filesystem STATIC IMPORTED) -set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_filesystem.a) - -add_library(boost_program_options STATIC IMPORTED) -set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_program_options.a) - -add_library(boost_regex STATIC IMPORTED) -set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_regex.a) - -add_library(boost_serialization STATIC IMPORTED) -set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_serialization.a) - -add_library(boost_system STATIC IMPORTED) -set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_system.a) - -add_library(boost_thread STATIC IMPORTED) -set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_thread.a) - -add_library(boost_wserialization STATIC IMPORTED) -set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/libboost_wserialization.a) - -############# -# Wownero -############# - -add_library(wallet_api STATIC IMPORTED) -set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libwallet_api.a) - -add_library(wallet STATIC IMPORTED) -set_target_properties(wallet PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libwallet.a) - -add_library(cryptonote_core STATIC IMPORTED) -set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcryptonote_core.a) - -add_library(cryptonote_basic STATIC IMPORTED) -set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcryptonote_basic.a) - -add_library(cryptonote_format_utils_basic STATIC IMPORTED) -set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcryptonote_format_utils_basic.a) - -add_library(mnemonics STATIC IMPORTED) -set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libmnemonics.a) - -add_library(common STATIC IMPORTED) -set_target_properties(common PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcommon.a) - -add_library(cncrypto STATIC IMPORTED) -set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcncrypto.a) - -add_library(ringct STATIC IMPORTED) -set_target_properties(ringct PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libringct.a) - -add_library(ringct_basic STATIC IMPORTED) -set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libringct_basic.a) - -add_library(blockchain_db STATIC IMPORTED) -set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libblockchain_db.a) - -add_library(lmdb STATIC IMPORTED) -set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/liblmdb.a) - -add_library(easylogging STATIC IMPORTED) -set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libeasylogging.a) - -add_library(unbound STATIC IMPORTED) -set_target_properties(unbound PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libunbound.a) - -add_library(epee STATIC IMPORTED) -set_target_properties(epee PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libepee.a) - -add_library(blocks STATIC IMPORTED) -set_target_properties(blocks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libblocks.a) - -add_library(checkpoints STATIC IMPORTED) -set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libcheckpoints.a) - -add_library(device STATIC IMPORTED) -set_target_properties(device PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libdevice.a) - -add_library(device_trezor STATIC IMPORTED) -set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libdevice_trezor.a) - -add_library(multisig STATIC IMPORTED) -set_target_properties(multisig PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libmultisig.a) - -add_library(version STATIC IMPORTED) -set_target_properties(version PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libversion.a) - -add_library(net STATIC IMPORTED) -set_target_properties(net PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libnet.a) - -add_library(hardforks STATIC IMPORTED) -set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libhardforks.a) - -add_library(randomx STATIC IMPORTED) -set_target_properties(randomx PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/librandomx.a) - -add_library(rpc_base STATIC IMPORTED) -set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/librpc_base.a) - -#add_library(wallet-crypto STATIC IMPORTED) -#set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION -# ${EXTERNAL_LIBS_DIR}/prefix_aarch64/lib/wownero/libwallet-crypto.a) - -set(WALLET_CRYPTO "") - -include_directories( ${EXTERNAL_LIBS_DIR}/prefix_aarch64/include ) - -target_link_libraries( cw_wownero - - wallet_api - wallet - cryptonote_core - cryptonote_basic - cryptonote_format_utils_basic - mnemonics - ringct - ringct_basic - net - common - cncrypto - blockchain_db - lmdb - easylogging - unbound - epee - blocks - checkpoints - device - device_trezor - multisig - version - randomx - hardforks - rpc_base - ${WALLET_CRYPTO} - - boost_chrono - boost_date_time - boost_filesystem - boost_program_options - boost_regex - boost_serialization - boost_system - boost_thread - boost_wserialization - - ssl - crypto - - sodium - - -Wl,--whole-archive - wownero-seed - -Wl,--no-whole-archive ) \ No newline at end of file diff --git a/scripts/linux/cmakefiles/wownero/x86_64/CMakeLists.txt b/scripts/linux/cmakefiles/wownero/x86_64/CMakeLists.txt deleted file mode 100644 index b04e1d0b60..0000000000 --- a/scripts/linux/cmakefiles/wownero/x86_64/CMakeLists.txt +++ /dev/null @@ -1,236 +0,0 @@ -cmake_minimum_required(VERSION 3.4.1) - -add_library( cw_wownero - SHARED -# ../../../cw_wownero/android/jni/wownero_jni.cpp - ../../../../../cw_wownero/ios/Classes/wownero_api.cpp) - -set(EXTERNAL_LIBS_DIR ${CMAKE_SOURCE_DIR}/../../../build) - -############ -# libsodium -############ - -add_library(sodium STATIC IMPORTED) -set_target_properties(sodium PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libsodium.a) - -############ -# OpenSSL -############ - -add_library(crypto STATIC IMPORTED) -set_target_properties(crypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libcrypto.a) - -add_library(ssl STATIC IMPORTED) -set_target_properties(ssl PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libssl.a) - -############ -# wownero-seed -############ - -add_library(wownero-seed STATIC IMPORTED) -set_target_properties(wownero-seed PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libwownero-seed.a) - -############ -# Boost -############ - -add_library(boost_chrono STATIC IMPORTED) -set_target_properties(boost_chrono PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_chrono.a) - -add_library(boost_date_time STATIC IMPORTED) -set_target_properties(boost_date_time PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_date_time.a) - -add_library(boost_filesystem STATIC IMPORTED) -set_target_properties(boost_filesystem PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_filesystem.a) - -add_library(boost_program_options STATIC IMPORTED) -set_target_properties(boost_program_options PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_program_options.a) - -add_library(boost_regex STATIC IMPORTED) -set_target_properties(boost_regex PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_regex.a) - -add_library(boost_serialization STATIC IMPORTED) -set_target_properties(boost_serialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_serialization.a) - -add_library(boost_system STATIC IMPORTED) -set_target_properties(boost_system PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_system.a) - -add_library(boost_thread STATIC IMPORTED) -set_target_properties(boost_thread PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_thread.a) - -add_library(boost_wserialization STATIC IMPORTED) -set_target_properties(boost_wserialization PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/libboost_wserialization.a) - -############# -# Wownero -############# - -add_library(wallet_api STATIC IMPORTED) -set_target_properties(wallet_api PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libwallet_api.a) - -add_library(wallet STATIC IMPORTED) -set_target_properties(wallet PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libwallet.a) - -add_library(cryptonote_core STATIC IMPORTED) -set_target_properties(cryptonote_core PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcryptonote_core.a) - -add_library(cryptonote_basic STATIC IMPORTED) -set_target_properties(cryptonote_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcryptonote_basic.a) - -add_library(cryptonote_format_utils_basic STATIC IMPORTED) -set_target_properties(cryptonote_format_utils_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcryptonote_format_utils_basic.a) - -add_library(mnemonics STATIC IMPORTED) -set_target_properties(mnemonics PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libmnemonics.a) - -add_library(common STATIC IMPORTED) -set_target_properties(common PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcommon.a) - -add_library(cncrypto STATIC IMPORTED) -set_target_properties(cncrypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcncrypto.a) - -add_library(ringct STATIC IMPORTED) -set_target_properties(ringct PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libringct.a) - -add_library(ringct_basic STATIC IMPORTED) -set_target_properties(ringct_basic PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libringct_basic.a) - -add_library(blockchain_db STATIC IMPORTED) -set_target_properties(blockchain_db PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libblockchain_db.a) - -add_library(lmdb STATIC IMPORTED) -set_target_properties(lmdb PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/liblmdb.a) - -add_library(easylogging STATIC IMPORTED) -set_target_properties(easylogging PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libeasylogging.a) - -add_library(unbound STATIC IMPORTED) -set_target_properties(unbound PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libunbound.a) - -add_library(epee STATIC IMPORTED) -set_target_properties(epee PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libepee.a) - -add_library(blocks STATIC IMPORTED) -set_target_properties(blocks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libblocks.a) - -add_library(checkpoints STATIC IMPORTED) -set_target_properties(checkpoints PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libcheckpoints.a) - -add_library(device STATIC IMPORTED) -set_target_properties(device PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libdevice.a) - -add_library(device_trezor STATIC IMPORTED) -set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libdevice_trezor.a) - -add_library(multisig STATIC IMPORTED) -set_target_properties(multisig PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libmultisig.a) - -add_library(version STATIC IMPORTED) -set_target_properties(version PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libversion.a) - -add_library(net STATIC IMPORTED) -set_target_properties(net PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libnet.a) - -add_library(hardforks STATIC IMPORTED) -set_target_properties(hardforks PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libhardforks.a) - -add_library(randomx STATIC IMPORTED) -set_target_properties(randomx PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/librandomx.a) - -add_library(rpc_base STATIC IMPORTED) -set_target_properties(rpc_base PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/librpc_base.a) - -add_library(wallet-crypto STATIC IMPORTED) -set_target_properties(wallet-crypto PROPERTIES IMPORTED_LOCATION - ${EXTERNAL_LIBS_DIR}/prefix_x86_64/lib/wownero/libwallet-crypto.a) - -set(WALLET_CRYPTO "wallet-crypto") - -include_directories( ${EXTERNAL_LIBS_DIR}/prefix_x86_64/include ) - -target_link_libraries( cw_wownero - - wallet_api - wallet - cryptonote_core - cryptonote_basic - cryptonote_format_utils_basic - mnemonics - ringct - ringct_basic - net - common - cncrypto - blockchain_db - lmdb - easylogging - unbound - epee - blocks - checkpoints - device - device_trezor - multisig - version - randomx - hardforks - rpc_base - ${WALLET_CRYPTO} - - boost_chrono - boost_date_time - boost_filesystem - boost_program_options - boost_regex - boost_serialization - boost_system - boost_thread - boost_wserialization - - ssl - crypto - - sodium - - -Wl,--whole-archive - wownero-seed - -Wl,--no-whole-archive ) \ No newline at end of file From 4e5999e59c787a61320c16d5a583a3f68f6594f3 Mon Sep 17 00:00:00 2001 From: julian-CStack Date: Tue, 21 Mar 2023 17:38:20 -0600 Subject: [PATCH 3/6] extra clean up --- .gitignore | 4 ---- pubspec_base.yaml | 1 - scripts/linux/build_monero_all.sh | 2 -- 3 files changed, 7 deletions(-) diff --git a/.gitignore b/.gitignore index aacbf61dee..0e00c13b70 100644 --- a/.gitignore +++ b/.gitignore @@ -116,10 +116,6 @@ cw_shared_external/ios/External/ cw_haven/ios/External/ cw_haven/android/.externalNativeBuild/ cw_haven/android/.cxx/ -# cw_wownero/** -cw_wownero/ios/External/ -cw_wownero/android/.externalNativeBuild/ -cw_wownero/android/.cxx/ lib/bitcoin/bitcoin.dart #lib/monero/monero.dart diff --git a/pubspec_base.yaml b/pubspec_base.yaml index 15892bd2e2..62f1292463 100644 --- a/pubspec_base.yaml +++ b/pubspec_base.yaml @@ -77,7 +77,6 @@ flutter: - assets/images/ - assets/node_list.yml - assets/haven_node_list.yml - - assets/wownero_node_list.yml - assets/bitcoin_electrum_server_list.yml - assets/litecoin_electrum_server_list.yml - assets/text/ diff --git a/scripts/linux/build_monero_all.sh b/scripts/linux/build_monero_all.sh index 3f98077532..57117c69c7 100755 --- a/scripts/linux/build_monero_all.sh +++ b/scripts/linux/build_monero_all.sh @@ -8,7 +8,5 @@ mkdir build ./build_unbound.sh ./build_zmq.sh ./build_monero.sh -./build_wownero.sh -./build_wownero_seed.sh ./copy_monero_deps.sh ./build_sharedfile.sh \ No newline at end of file From 42cf899fa05a386b2f6553b0b6a6ea8e814bfe1d Mon Sep 17 00:00:00 2001 From: julian-CStack Date: Thu, 23 Mar 2023 11:04:45 -0600 Subject: [PATCH 4/6] duo home dir path --- cw_core/lib/pathForWallet.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cw_core/lib/pathForWallet.dart b/cw_core/lib/pathForWallet.dart index 4cc2f5ec2d..bb6b4b251c 100644 --- a/cw_core/lib/pathForWallet.dart +++ b/cw_core/lib/pathForWallet.dart @@ -37,11 +37,11 @@ Future applicationRootDirectory() async { // todo: can merge and do same as regular linux home dir? if (bool.fromEnvironment("IS_ARM")) { appDirectory = await getApplicationDocumentsDirectory(); - appDirectory = Directory("${appDirectory.path}/.stackwallet"); + appDirectory = Directory("${appDirectory.path}/.stackduo"); } else if (Platform.isLinux) { - appDirectory = Directory("${Platform.environment['HOME']}/.stackwallet"); + appDirectory = Directory("${Platform.environment['HOME']}/.stackduo"); } else if (Platform.isWindows) { -// TODO: windows root .stackwallet dir location +// TODO: windows root .stackduo dir location throw Exception("Unsupported platform"); } else if (Platform.isMacOS) { // currently run in ipad mode?? From 8e878a7f12f129b0eab50770a975613d0e6a0081 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 23 Mar 2023 11:41:48 -0500 Subject: [PATCH 5/6] 0.18.0->0.18.2 use official sources rather than cake-tech may need to backport android and/or other compatibility changes cw_monero may not implement all new 0.18.2 features --- scripts/linux/build_monero.sh | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/scripts/linux/build_monero.sh b/scripts/linux/build_monero.sh index e560f61049..97940c17f8 100755 --- a/scripts/linux/build_monero.sh +++ b/scripts/linux/build_monero.sh @@ -1,11 +1,15 @@ #!/bin/sh . ./config.sh -MONERO_BRANCH=release-v0.18.0.0-android +MONERO_URL="https://github.com/monero-project/monero.git" +MONERO_VERSION=v0.18.2.0 +MONERO_SHA_HEAD=99be9a044f3854f339548e2d99c539c18d7b1b01 MONERO_SRC_DIR=${WORKDIR}/monero +MONERO_BRANCH=main -git clone https://github.com/cake-tech/monero.git ${MONERO_SRC_DIR} --branch ${MONERO_BRANCH} +git clone ${MONERO_URL} ${MONERO_SRC_DIR} --branch ${MONERO_VERSION} cd $MONERO_SRC_DIR +git reset --hard $MONERO_SHA_HEAD git submodule init git submodule update From c4c61ccd6ad1dabcf6cb87fbe14e024e03144743 Mon Sep 17 00:00:00 2001 From: sneurlax Date: Thu, 23 Mar 2023 12:15:26 -0500 Subject: [PATCH 6/6] remove hex and txKey members from PendingTransactionRaw FFI remove hex and txky members from Dart FFI --- cw_monero/ios/Classes/monero_api.cpp | 4 ---- cw_monero/lib/api/transaction_history.dart | 4 ---- 2 files changed, 8 deletions(-) diff --git a/cw_monero/ios/Classes/monero_api.cpp b/cw_monero/ios/Classes/monero_api.cpp index 57bac28324..a62a664659 100644 --- a/cw_monero/ios/Classes/monero_api.cpp +++ b/cw_monero/ios/Classes/monero_api.cpp @@ -172,8 +172,6 @@ extern "C" uint64_t amount; uint64_t fee; char *hash; - char *hex; - char *txKey; Monero::PendingTransaction *transaction; PendingTransactionRaw(Monero::PendingTransaction *_transaction) @@ -182,8 +180,6 @@ extern "C" amount = _transaction->amount(); fee = _transaction->fee(); hash = strdup(_transaction->txid()[0].c_str()); - hex = strdup(_transaction->hex()[0].c_str()); - txKey = strdup(_transaction->txKey()[0].c_str()); } }; diff --git a/cw_monero/lib/api/transaction_history.dart b/cw_monero/lib/api/transaction_history.dart index d3564248eb..ae4741cec8 100644 --- a/cw_monero/lib/api/transaction_history.dart +++ b/cw_monero/lib/api/transaction_history.dart @@ -110,8 +110,6 @@ PendingTransactionDescription createTransactionSync( amount: pendingTransactionRawPointer.ref.amount, fee: pendingTransactionRawPointer.ref.fee, hash: pendingTransactionRawPointer.ref.getHash(), - hex: pendingTransactionRawPointer.ref.getHex(), - txKey: pendingTransactionRawPointer.ref.getKey(), pointerAddress: pendingTransactionRawPointer.address); } @@ -168,8 +166,6 @@ PendingTransactionDescription createTransactionMultDestSync( amount: pendingTransactionRawPointer.ref.amount, fee: pendingTransactionRawPointer.ref.fee, hash: pendingTransactionRawPointer.ref.getHash(), - hex: pendingTransactionRawPointer.ref.getHex(), - txKey: pendingTransactionRawPointer.ref.getKey(), pointerAddress: pendingTransactionRawPointer.address); }