├── .gitignore ├── .idea ├── misc.xml └── vcs.xml ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── .gitignore ├── build.gradle ├── fabric.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── wallet │ │ └── crypto │ │ ├── EthereumNetworkRepositoryTest.java │ │ ├── GetKeystoreWalletRepoTest.java │ │ ├── ImportPrivateKey.java │ │ ├── PasswordManagerTest.java │ │ ├── WalletRepoTest.java │ │ ├── WalletTest.java │ │ └── views │ │ ├── CreateWalletTest.java │ │ └── ScreengrabTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── cpp │ │ ├── CMakeLists.txt │ │ └── native-lib.c │ ├── ic_launcher-web.png │ ├── java │ │ └── com │ │ │ └── wallet │ │ │ └── crypto │ │ │ ├── App.kt │ │ │ ├── MercuryConstants.java │ │ │ ├── config │ │ │ └── Config.kt │ │ │ ├── db │ │ │ ├── TokenInfoDao.kt │ │ │ └── TrustDb.kt │ │ │ ├── di │ │ │ ├── AccountsManageModule.java │ │ │ ├── ActivityScope.java │ │ │ ├── AddTokenModule.java │ │ │ ├── AppComponent.java │ │ │ ├── AppInjector.java │ │ │ ├── BuildersModule.java │ │ │ ├── ConfirmationModule.java │ │ │ ├── FragmentInjectable.java │ │ │ ├── FragmentScope.java │ │ │ ├── GasSettingsModule.java │ │ │ ├── ImportModule.java │ │ │ ├── RepositoriesModule.java │ │ │ ├── SendModule.java │ │ │ ├── SettingsFragmentModule.java │ │ │ ├── SettingsModule.java │ │ │ ├── SplashModule.java │ │ │ ├── TokensModule.java │ │ │ ├── ToolsModule.java │ │ │ ├── TransactionDetailModule.java │ │ │ └── TransactionsModule.java │ │ │ ├── entity │ │ │ ├── Account.kt │ │ │ ├── Address.java │ │ │ ├── ApiErrorException.java │ │ │ ├── ErrorEnvelope.java │ │ │ ├── GasSettings.java │ │ │ ├── NetworkInfo.java │ │ │ ├── ServiceErrorException.java │ │ │ ├── ServiceException.java │ │ │ ├── StorableAccounts.kt │ │ │ ├── Ticker.java │ │ │ ├── Token.java │ │ │ ├── TokenInfo.java │ │ │ ├── Transaction.java │ │ │ ├── TransactionContract.java │ │ │ ├── TransactionOperation.java │ │ │ ├── Wallet.kt │ │ │ └── WalletDisplay.kt │ │ │ ├── ext │ │ │ ├── Toast+Extension.kt │ │ │ └── View+Extension.kt │ │ │ ├── interact │ │ │ ├── AddTokenInteract.java │ │ │ ├── CreateTransactionInteract.java │ │ │ ├── CreateWalletInteract.java │ │ │ ├── DeleteWalletInteract.java │ │ │ ├── ExportWalletInteract.java │ │ │ ├── FetchGasSettingsInteract.java │ │ │ ├── FetchTokensInteract.java │ │ │ ├── FetchTransactionsInteract.java │ │ │ ├── FetchWalletsInteract.java │ │ │ ├── FindDefaultNetworkInteract.java │ │ │ ├── FindDefaultWalletInteract.java │ │ │ ├── GetDefaultWalletBalance.java │ │ │ ├── ImportWalletInteract.java │ │ │ ├── SetDefaultWalletInteract.java │ │ │ └── rx │ │ │ │ └── operator │ │ │ │ ├── CompletableErrorProxyOperator.java │ │ │ │ ├── Operators.java │ │ │ │ └── SavePasswordOperator.java │ │ │ ├── repository │ │ │ ├── EthereumNetworkRepository.java │ │ │ ├── OnNetworkChangeListener.java │ │ │ ├── RealmTokenSource.java │ │ │ ├── SharedPreferenceRepository.java │ │ │ ├── TokenRepository.java │ │ │ ├── TransactionInDiskSource.java │ │ │ ├── TransactionInMemorySource.java │ │ │ ├── TransactionLocalSource.java │ │ │ ├── TransactionRepository.java │ │ │ ├── WalletRepository.java │ │ │ └── entity │ │ │ │ ├── DbTokenInfo1.java │ │ │ │ └── RealmTokenInfo.java │ │ │ ├── router │ │ │ ├── AddTokenRouter.java │ │ │ ├── ConfirmationRouter.java │ │ │ ├── ExternalBrowserRouter.java │ │ │ ├── GasSettingsRouter.java │ │ │ ├── ImportWalletRouter.java │ │ │ ├── MainRouter.java │ │ │ ├── ManageWalletsRouter.java │ │ │ ├── MyAddressRouter.java │ │ │ ├── MyTokensRouter.java │ │ │ ├── SendRouter.java │ │ │ ├── SendTokenRouter.java │ │ │ ├── SettingsRouter.java │ │ │ └── TransactionDetailRouter.java │ │ │ ├── service │ │ │ ├── BlockExplorerClient.java │ │ │ ├── CoinmarketcapTickerService.java │ │ │ ├── EthplorerTokenService.java │ │ │ ├── GethKeystoreAccountService.kt │ │ │ ├── MercuryWalletTickerService.java │ │ │ └── TickerService.java │ │ │ ├── ui │ │ │ ├── AddTokenActivity.java │ │ │ ├── BaseActivity.java │ │ │ ├── ChangePasswordActivity.kt │ │ │ ├── ConfirmationActivity.java │ │ │ ├── GasSettingsActivity.java │ │ │ ├── ImportKeystoreFragment.java │ │ │ ├── ImportPrivateKeyFragment.java │ │ │ ├── ImportWalletActivity.java │ │ │ ├── MainActivity.kt │ │ │ ├── MyAddressActivity.java │ │ │ ├── SendActivity.kt │ │ │ ├── SettingsActivity.java │ │ │ ├── SettingsFragment.kt │ │ │ ├── SplashActivity.java │ │ │ ├── TokensActivity.java │ │ │ ├── TransactionDetailActivity.java │ │ │ ├── WalletsActivity.java │ │ │ ├── barcode │ │ │ │ ├── AddressEncoder.kt │ │ │ │ ├── Contents.kt │ │ │ │ ├── QREncoder.kt │ │ │ │ └── QRScanActivity.kt │ │ │ ├── camera │ │ │ │ ├── CameraSource.java │ │ │ │ └── CameraSourcePreview.java │ │ │ ├── dialog │ │ │ │ ├── BaseDialogFragment.kt │ │ │ │ ├── DialogBuilder.kt │ │ │ │ ├── DialogManager.kt │ │ │ │ ├── ExportWalletsDialog.kt │ │ │ │ ├── InputPwdDialog.kt │ │ │ │ ├── NormalDialog.kt │ │ │ │ └── interfaces │ │ │ │ │ ├── DialogListener.kt │ │ │ │ │ ├── INegativeButtonDialogListener.kt │ │ │ │ │ ├── IPositiveButtonDialogListener.kt │ │ │ │ │ └── ISimpleDialogCancelListener.kt │ │ │ └── widget │ │ │ │ ├── OnBackupClickListener.java │ │ │ │ ├── OnDepositClickListener.java │ │ │ │ ├── OnImportKeystoreListener.java │ │ │ │ ├── OnImportPrivateKeyListener.java │ │ │ │ ├── OnTokenClickListener.java │ │ │ │ ├── OnTransactionClickListener.java │ │ │ │ ├── adapter │ │ │ │ ├── TabPagerAdapter.java │ │ │ │ ├── TokensAdapter.java │ │ │ │ ├── TransactionsAdapter.java │ │ │ │ └── WalletsAdapter.java │ │ │ │ ├── entity │ │ │ │ ├── DateSortedItem.java │ │ │ │ ├── SortedItem.java │ │ │ │ ├── TimestampSortedItem.java │ │ │ │ └── TransactionSortedItem.java │ │ │ │ └── holder │ │ │ │ ├── BinderViewHolder.java │ │ │ │ ├── TokenHolder.java │ │ │ │ ├── TransactionDateHolder.java │ │ │ │ ├── TransactionHolder.java │ │ │ │ └── WalletHolder.java │ │ │ ├── util │ │ │ ├── AddressNameConverter.kt │ │ │ ├── BalanceUtils.java │ │ │ ├── ExchangeCalculator.kt │ │ │ ├── FileUtils.kt │ │ │ ├── KS.java │ │ │ ├── KeyboardUtils.java │ │ │ ├── QRURLParser.java │ │ │ ├── RootUtil.java │ │ │ ├── SPHelper.kt │ │ │ ├── SecureRandomUtils.kt │ │ │ └── WalletStorage.kt │ │ │ ├── viewmodel │ │ │ ├── AddTokenViewModel.kt │ │ │ ├── AddTokenViewModelFactory.java │ │ │ ├── BaseNavigationActivity.java │ │ │ ├── BaseViewModel.kt │ │ │ ├── ChangePasswordViewModel.kt │ │ │ ├── ConfirmationViewModel.java │ │ │ ├── ConfirmationViewModelFactory.java │ │ │ ├── CreateAccountViewModel.java │ │ │ ├── CreateAccountViewModelFactory.java │ │ │ ├── GasSettingsViewModel.java │ │ │ ├── GasSettingsViewModelFactory.java │ │ │ ├── ImportWalletViewModel.java │ │ │ ├── ImportWalletViewModelFactory.java │ │ │ ├── MainViewModel.java │ │ │ ├── SendViewModel.java │ │ │ ├── SendViewModelFactory.java │ │ │ ├── SplashViewModel.java │ │ │ ├── SplashViewModelFactory.java │ │ │ ├── TokensViewModel.java │ │ │ ├── TokensViewModelFactory.java │ │ │ ├── TransactionDetailViewModel.java │ │ │ ├── TransactionDetailViewModelFactory.java │ │ │ ├── TransactionsViewModelFactory.java │ │ │ ├── WalletsViewModel.java │ │ │ └── WalletsViewModelFactory.java │ │ │ └── widget │ │ │ ├── AddWalletView.java │ │ │ ├── BackupWarningView.java │ │ │ ├── DepositView.java │ │ │ ├── EmptyTransactionsView.java │ │ │ ├── HelperTextInputLayout.java │ │ │ └── SystemView.java │ ├── res │ │ ├── anim │ │ │ ├── in_from_left.xml │ │ │ ├── in_from_right.xml │ │ │ ├── out_to_left.xml │ │ │ ├── out_to_right.xml │ │ │ ├── push_bottom_in.xml │ │ │ ├── push_bottom_out.xml │ │ │ ├── scale_center_in.xml │ │ │ ├── scale_center_out.xml │ │ │ └── scale_tran_out.xml │ │ ├── drawable-hdpi │ │ │ ├── ic_action_deposit.png │ │ │ ├── ic_facebook.png │ │ │ ├── settings_rpc_server.png │ │ │ └── token_icon.png │ │ ├── drawable-mdpi │ │ │ ├── ic_action_deposit.png │ │ │ ├── ic_facebook.png │ │ │ ├── ic_share_white_24dp.xml │ │ │ ├── settings_rpc_server.png │ │ │ └── token_icon.png │ │ ├── drawable-nodpi │ │ │ ├── no_transactions_mascot.png │ │ │ ├── onboarding_erc20.png │ │ │ └── settings_facebook.png │ │ ├── drawable-v21 │ │ │ └── bg_ripple_primary_color.xml │ │ ├── drawable-xhdpi │ │ │ ├── ic_action_deposit.png │ │ │ ├── ic_facebook.png │ │ │ ├── settings_rpc_server.png │ │ │ └── token_icon.png │ │ ├── drawable-xxhdpi │ │ │ ├── ic_action_deposit.png │ │ │ ├── ic_facebook.png │ │ │ ├── settings_rpc_server.png │ │ │ └── token_icon.png │ │ ├── drawable │ │ │ ├── bg_ripple_primary_color.xml │ │ │ ├── ic_add_black_24dp.xml │ │ │ ├── ic_add_circle_black_24dp.xml │ │ │ ├── ic_add_white_24dp.xml │ │ │ ├── ic_arrow_downward_black_24dp.xml │ │ │ ├── ic_arrow_upward_black_24dp.xml │ │ │ ├── ic_attach_money_white_24dp.xml │ │ │ ├── ic_autorenew_black_24dp.xml │ │ │ ├── ic_backup_black_24dp.xml │ │ │ ├── ic_bug.xml │ │ │ ├── ic_call_received_white_24dp.xml │ │ │ ├── ic_chevron_right_black_24dp.xml │ │ │ ├── ic_code_black_24dp.xml │ │ │ ├── ic_content_paste_black_24dp.xml │ │ │ ├── ic_dashboard_black_24dp.xml │ │ │ ├── ic_delete_forever_black_24dp.xml │ │ │ ├── ic_error_outline_black_24dp.xml │ │ │ ├── ic_file_download_black_24dp.xml │ │ │ ├── ic_home_black_24dp.xml │ │ │ ├── ic_import_export_black_24dp.xml │ │ │ ├── ic_net.xml │ │ │ ├── ic_notifications_black_24dp.xml │ │ │ ├── ic_pwd.xml │ │ │ ├── ic_qq.xml │ │ │ ├── ic_send_white_24dp.xml │ │ │ ├── ic_settings_white_24dp.xml │ │ │ ├── ic_share_black_24dp.xml │ │ │ ├── ic_source.xml │ │ │ ├── ic_swap_horiz_white_24dp.xml │ │ │ ├── ic_toast_error.xml │ │ │ ├── ic_wallet.xml │ │ │ ├── ic_warning_black_24dp.xml │ │ │ ├── selector_btn_text_bg.xml │ │ │ ├── shape_btn_bg.xml │ │ │ ├── shape_dialog_bg.xml │ │ │ ├── shape_tips_bg.xml │ │ │ ├── shape_toast_bg.xml │ │ │ └── splash_background.xml │ │ ├── font │ │ │ ├── roboto_bolt.ttf │ │ │ └── roboto_regular.ttf │ │ ├── layout-land │ │ │ └── layout_dialog_warning_backup.xml │ │ ├── layout │ │ │ ├── account_list_content.xml │ │ │ ├── activity_add_token.xml │ │ │ ├── activity_change_pwd.xml │ │ │ ├── activity_confirm.xml │ │ │ ├── activity_gas_settings.xml │ │ │ ├── activity_import_wallet.xml │ │ │ ├── activity_my_address.xml │ │ │ ├── activity_qrscan.xml │ │ │ ├── activity_send.xml │ │ │ ├── activity_settings.xml │ │ │ ├── activity_splash.xml │ │ │ ├── activity_tokens.xml │ │ │ ├── activity_transaction_detail.xml │ │ │ ├── activity_transactions.xml │ │ │ ├── activity_wallet_gen.xml │ │ │ ├── activity_wallets.xml │ │ │ ├── dialog_normal.xml │ │ │ ├── fragment_import_keystore.xml │ │ │ ├── fragment_import_private_key.xml │ │ │ ├── item_token.xml │ │ │ ├── item_transaction.xml │ │ │ ├── item_transactions_date_head.xml │ │ │ ├── item_wallet_manage.xml │ │ │ ├── layout_app_bar.xml │ │ │ ├── layout_app_bar_with_tab.xml │ │ │ ├── layout_barcode_capture.xml │ │ │ ├── layout_dialog_add_account.xml │ │ │ ├── layout_dialog_backup.xml │ │ │ ├── layout_dialog_create_pwd.xml │ │ │ ├── layout_dialog_deposit.xml │ │ │ ├── layout_dialog_export_wallets.xml │ │ │ ├── layout_dialog_password.xml │ │ │ ├── layout_dialog_warning_backup.xml │ │ │ ├── layout_empty_add_account.xml │ │ │ ├── layout_empty_transactions.xml │ │ │ ├── layout_page_intro.xml │ │ │ ├── layout_simple_toolbar.xml │ │ │ └── layout_system_view.xml │ │ ├── menu │ │ │ ├── confirmation_menu.xml │ │ │ ├── menu_add.xml │ │ │ ├── menu_deposit.xml │ │ │ ├── menu_main_network.xml │ │ │ ├── menu_secondary_network.xml │ │ │ ├── menu_settings.xml │ │ │ ├── menu_share.xml │ │ │ ├── send_menu.xml │ │ │ └── send_settings_menu.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── settings_backup.png │ │ │ ├── settings_bug.png │ │ │ ├── settings_donate.png │ │ │ ├── settings_email.png │ │ │ ├── settings_open_source.png │ │ │ ├── settings_privacy_policy.png │ │ │ ├── settings_rating.png │ │ │ ├── settings_server.png │ │ │ ├── settings_telegram.png │ │ │ ├── settings_terms.png │ │ │ ├── settings_twitter.png │ │ │ └── token_logo.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── settings_backup.png │ │ │ ├── settings_bug.png │ │ │ ├── settings_donate.png │ │ │ ├── settings_email.png │ │ │ ├── settings_open_source.png │ │ │ ├── settings_privacy_policy.png │ │ │ ├── settings_rating.png │ │ │ ├── settings_server.png │ │ │ ├── settings_telegram.png │ │ │ ├── settings_terms.png │ │ │ ├── settings_twitter.png │ │ │ └── token_logo.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── settings_backup.png │ │ │ ├── settings_bug.png │ │ │ ├── settings_donate.png │ │ │ ├── settings_email.png │ │ │ ├── settings_open_source.png │ │ │ ├── settings_privacy_policy.png │ │ │ ├── settings_rating.png │ │ │ ├── settings_server.png │ │ │ ├── settings_telegram.png │ │ │ ├── settings_terms.png │ │ │ ├── settings_twitter.png │ │ │ └── token_logo.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── settings_backup.png │ │ │ ├── settings_bug.png │ │ │ ├── settings_donate.png │ │ │ ├── settings_email.png │ │ │ ├── settings_open_source.png │ │ │ ├── settings_privacy_policy.png │ │ │ ├── settings_rating.png │ │ │ ├── settings_server.png │ │ │ ├── settings_telegram.png │ │ │ ├── settings_terms.png │ │ │ ├── settings_twitter.png │ │ │ └── token_logo.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── backup_warning.png │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ ├── ic_splash.png │ │ │ ├── onboarding_lock.png │ │ │ ├── onboarding_open_source.png │ │ │ ├── onboarding_rocket.png │ │ │ ├── qr_code_icon.png │ │ │ ├── settings_backup.png │ │ │ ├── settings_bug.png │ │ │ ├── settings_donate.png │ │ │ ├── settings_email.png │ │ │ ├── settings_export.png │ │ │ ├── settings_open_source.png │ │ │ ├── settings_privacy_policy.png │ │ │ ├── settings_rating.png │ │ │ ├── settings_server.png │ │ │ ├── settings_telegram.png │ │ │ ├── settings_terms.png │ │ │ ├── settings_twitter.png │ │ │ └── token_logo.png │ │ ├── values-land │ │ │ └── dimens.xml │ │ ├── values-zh │ │ │ └── strings.xml │ │ ├── values │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── helper_input_layout_res.xml │ │ │ ├── ic_launcher_background.xml │ │ │ ├── ids.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ └── xml │ │ │ └── fragment_settings.xml │ └── settings_rating-web.png │ └── test │ └── java │ └── com │ └── wallet │ └── crypto │ └── trustapp │ └── QRExtractorTest.java ├── build.gradle ├── fastlane ├── Appfile ├── Fastfile ├── README.md ├── Screengrabfile └── metadata │ └── android │ └── en-US │ ├── full_description.txt │ ├── images │ ├── featureGraphic.png │ ├── icon.png │ └── phoneScreenshots │ │ ├── screenshot1_intro.png │ │ ├── screenshot2_send.png │ │ ├── screenshot3_tokens.png │ │ ├── screenshot4_import.png │ │ └── screenshot5_transactions.png │ ├── short_description.txt │ ├── title.txt │ └── video.txt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── resources ├── 1.jpg ├── 2.jpg ├── 3.jpg └── 4.jpg ├── settings.gradle └── tn ├── build.gradle └── trustnative.aar /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .DS_Store 3 | /captures 4 | .externalNativeBuild 5 | 6 | ### Android ### 7 | # Built application files 8 | *.apk 9 | *.ap_ 10 | *.iml 11 | *.swp 12 | *.swo 13 | 14 | # Files for the Dalvik VM 15 | *.dex 16 | 17 | # Java class files 18 | *.class 19 | 20 | # Generated files 21 | bin/ 22 | gen/ 23 | 24 | # Gradle files 25 | .gradle/ 26 | /build 27 | app/release 28 | 29 | # Fastlane 30 | fastlane/report.xml 31 | 32 | # Local configuration file (sdk path, etc) 33 | /local.properties 34 | 35 | # Proguard folder generated by Eclipse 36 | proguard/ 37 | 38 | # Log Files 39 | *.log 40 | 41 | # Android Studio Navigation editor temp files 42 | .navigation/ 43 | 44 | ### Android Patch ### 45 | gen-external-apklibs 46 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: android 2 | sudo: false 3 | android: 4 | components: 5 | # Uncomment the lines below if you want to 6 | # use the latest revision of Android SDK Tools 7 | - tools 8 | - platform-tools 9 | 10 | # The BuildTools version used by your project 11 | - build-tools-26.0.2 12 | 13 | # The SDK version used to compile your project 14 | - android-26 15 | 16 | - extra-android-m2repository 17 | - extra-google-android-support 18 | 19 | # Specify at least one system image, 20 | # if you need to run emulator(s) during your tests 21 | - sys-img-x86-android-26 22 | 23 | licenses: 24 | - 'android-sdk-preview-license-.+' 25 | - 'android-sdk-license-.+' 26 | - 'google-gdk-license-.+' 27 | 28 | install: 29 | - true 30 | 31 | script: 32 | - ./gradlew build 33 | 34 | after_success: 35 | - bash <(curl -s https://copilot.blackducksoftware.com/ci/travis/scripts/upload) 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mercury - Ethereum Wallet for Android 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 | ## Features 13 | * 支持多钱包 14 | * 发送/请求付款 15 | * 支持代币 16 | * 消息通知 17 | * 交易历史 18 | * 钱包导入/导出 19 | * 不需要注册登录 20 | * 支持ERC20 21 | * 支持英语 22 | * 支持中文 23 | * 密码保护 24 | * 密码重置 25 | 26 | ## 后续计划 27 | * 指纹保护 28 | * 支持只读钱包 29 | * 支持助记词 30 | 31 | 32 | 根据[Trust](https://github.com/MercuryWallet/trust-wallet-android-source)修改优化 33 | 34 | ## Dependencies: 35 | * [Web3j](https://github.com/web3j/web3j) 36 | * [zxing](https://github.com/zxing/zxing) 37 | 38 | ... 39 | 40 | 41 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/fabric.properties: -------------------------------------------------------------------------------- 1 | #Contains API Secret used to validate your application. Commit to internal source control; avoid making secret public. 2 | #Thu Dec 21 15:16:27 KRAT 2017 3 | #Wed Dec 13 10:43:28 KRAT 2017 4 | apiSecret=8973b953bafdeaf177a2bae935a2bfba6158575b615f75305af25cf01a6adac6 5 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/marat/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wallet/crypto/EthereumNetworkRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import com.wallet.crypto.repository.EthereumNetworkRepository; 8 | import com.wallet.crypto.repository.SharedPreferenceRepository; 9 | import com.wallet.crypto.repository.SharedPreferenceRepository; 10 | 11 | import org.junit.Before; 12 | import org.junit.runner.RunWith; 13 | 14 | @RunWith(AndroidJUnit4.class) 15 | public class EthereumNetworkRepositoryTest { 16 | 17 | private EthereumNetworkRepository networkRepository; 18 | 19 | @Before 20 | public void setUp() { 21 | Context context = InstrumentationRegistry.getTargetContext(); 22 | SharedPreferenceRepository preferenceRepositoryType = new SharedPreferenceRepository(context); 23 | networkRepository = new EthereumNetworkRepository(preferenceRepositoryType); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wallet/crypto/WalletTest.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import com.wallet.crypto.controller.Controller; 8 | import com.wallet.crypto.model.VMAccount; 9 | 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | 13 | /** 14 | * Instrumentation test, which will execute on an Android device. 15 | * 16 | * @see Testing documentation 17 | */ 18 | @RunWith(AndroidJUnit4.class) 19 | public class WalletTest { 20 | @Test 21 | public void useAppContext() throws Exception { 22 | // Context of the app under test. 23 | Context appContext = InstrumentationRegistry.getTargetContext(); 24 | } 25 | 26 | @Test 27 | public void deleteAccountTest() throws Exception { 28 | Controller controller = Controller.with(InstrumentationRegistry.getTargetContext()); 29 | VMAccount account = controller.createAccount("test password"); 30 | assert(account != null); 31 | 32 | try { 33 | controller.deleteAccount(account.getAddress()); 34 | } catch (Exception e) { 35 | assert(false); 36 | } 37 | 38 | assert(controller.getAccount(account.getAddress()) != null); 39 | } 40 | 41 | @Test 42 | public void createAccountTest() throws Exception { 43 | Controller controller = Controller.with(InstrumentationRegistry.getTargetContext()); 44 | VMAccount account = controller.createAccount("test password"); 45 | assert(account != null); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/wallet/crypto/views/CreateWalletTest.java: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/androidTest/java/com/wallet/crypto/views/CreateWalletTest.java -------------------------------------------------------------------------------- /app/src/main/cpp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4.1) 2 | 3 | add_library(native-lib SHARED 4 | native-lib.c) 5 | 6 | # Include libraries needed for native-lib lib 7 | target_link_libraries(native-lib 8 | android 9 | log) 10 | -------------------------------------------------------------------------------- /app/src/main/cpp/native-lib.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | 6 | 7 | JNIEXPORT jstring JNICALL 8 | Java_com_wallet_crypto_trustapp_controller_PasswordManager_getKeyStringFromNative( JNIEnv* env, jobject thiz ) 9 | { 10 | // TODO: fill in your key - must be 32 bytes 11 | const jstring key = "ThisIsNotTheKeyYoureLookingFor!!"; 12 | return (*env)->NewStringUTF(env, key); 13 | } 14 | 15 | JNIEXPORT jbyteArray JNICALL 16 | Java_com_wallet_crypto_trustapp_controller_PasswordManager_getIvStringFromNative( JNIEnv* env, jobject thiz ) 17 | { 18 | // TODO: fill in your iv - must be 16 bytes 19 | const jstring iv = "NorTheInitVector"; 20 | return (*env)->NewStringUTF(env, iv); 21 | } -------------------------------------------------------------------------------- /app/src/main/ic_launcher-web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/ic_launcher-web.png -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/App.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto 2 | 3 | import android.app.Activity 4 | import android.content.Context 5 | import android.support.multidex.MultiDexApplication 6 | 7 | import com.wallet.crypto.di.AppInjector 8 | 9 | import javax.inject.Inject 10 | 11 | import dagger.android.AndroidInjector 12 | import dagger.android.DispatchingAndroidInjector 13 | import dagger.android.HasActivityInjector 14 | import io.realm.Realm 15 | import kotlin.properties.Delegates 16 | 17 | class App : MultiDexApplication(), HasActivityInjector { 18 | 19 | @Inject 20 | lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector 21 | 22 | override fun onCreate() { 23 | super.onCreate() 24 | 25 | context = this 26 | Realm.init(this) 27 | AppInjector.init(this) 28 | 29 | } 30 | 31 | override fun activityInjector(): AndroidInjector? { 32 | return dispatchingAndroidInjector 33 | } 34 | 35 | companion object { 36 | 37 | var context: App by Delegates.notNull() 38 | private set 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/db/TokenInfoDao.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wallet.crypto.db 18 | 19 | import android.arch.lifecycle.LiveData 20 | import android.arch.persistence.room.Dao 21 | import android.arch.persistence.room.Insert 22 | import android.arch.persistence.room.OnConflictStrategy 23 | import android.arch.persistence.room.Query 24 | import com.wallet.crypto.repository.entity.DbTokenInfo1 25 | 26 | /** 27 | * Interface for database access for User related operations. 28 | */ 29 | @Dao 30 | interface TokenInfoDao { 31 | @Insert(onConflict = OnConflictStrategy.REPLACE) 32 | fun insert(tokenInfo: DbTokenInfo1) 33 | 34 | @Query("SELECT * FROM dbtokeninfo1 WHERE address = :address") 35 | fun findByAddress(address: String): LiveData 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/ActivityScope.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import java.lang.annotation.Retention; 4 | 5 | import javax.inject.Scope; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Scope 10 | @Retention(RUNTIME) 11 | public @interface ActivityScope { 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/AddTokenModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.interact.AddTokenInteract; 4 | import com.wallet.crypto.interact.FindDefaultWalletInteract; 5 | import com.wallet.crypto.repository.TokenRepository; 6 | import com.wallet.crypto.repository.WalletRepository; 7 | import com.wallet.crypto.router.MyTokensRouter; 8 | import com.wallet.crypto.viewmodel.AddTokenViewModelFactory; 9 | 10 | import dagger.Module; 11 | import dagger.Provides; 12 | 13 | @Module 14 | public class AddTokenModule { 15 | 16 | @Provides 17 | AddTokenViewModelFactory addTokenViewModelFactory( 18 | AddTokenInteract addTokenInteract, 19 | FindDefaultWalletInteract findDefaultWalletInteract, 20 | MyTokensRouter myTokensRouter) { 21 | return new AddTokenViewModelFactory( 22 | addTokenInteract, findDefaultWalletInteract, myTokensRouter); 23 | } 24 | 25 | @Provides 26 | AddTokenInteract provideAddTokenInteract( 27 | TokenRepository tokenRepository, 28 | WalletRepository walletRepository) { 29 | return new AddTokenInteract(walletRepository, tokenRepository); 30 | } 31 | 32 | @Provides 33 | FindDefaultWalletInteract provideFindDefaultWalletInteract(WalletRepository walletRepository) { 34 | return new FindDefaultWalletInteract(walletRepository); 35 | } 36 | 37 | @Provides 38 | MyTokensRouter provideMyTokensRouter() { 39 | return new MyTokensRouter(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/AppComponent.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.App; 4 | 5 | import javax.inject.Singleton; 6 | 7 | import dagger.BindsInstance; 8 | import dagger.Component; 9 | import dagger.android.support.AndroidSupportInjectionModule; 10 | 11 | @Singleton 12 | @Component(modules = { 13 | AndroidSupportInjectionModule.class, 14 | ToolsModule.class, 15 | RepositoriesModule.class, 16 | BuildersModule.class }) 17 | public interface AppComponent { 18 | 19 | @Component.Builder 20 | interface Builder { 21 | @BindsInstance 22 | Builder application(App app); 23 | AppComponent build(); 24 | } 25 | void inject(App app); 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/FragmentInjectable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2017 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wallet.crypto.di; 18 | 19 | /** 20 | * Marks an activity / fragment injectable. 21 | */ 22 | public interface FragmentInjectable { 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/FragmentScope.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import java.lang.annotation.Retention; 4 | 5 | import javax.inject.Scope; 6 | 7 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 8 | 9 | @Scope 10 | @Retention(RUNTIME) 11 | public @interface FragmentScope { 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/GasSettingsModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | 4 | import com.wallet.crypto.interact.FindDefaultNetworkInteract; 5 | import com.wallet.crypto.repository.EthereumNetworkRepository; 6 | import com.wallet.crypto.viewmodel.GasSettingsViewModelFactory; 7 | 8 | import dagger.Module; 9 | import dagger.Provides; 10 | 11 | @Module 12 | public class GasSettingsModule { 13 | 14 | @Provides 15 | public GasSettingsViewModelFactory provideGasSettingsViewModelFactory(FindDefaultNetworkInteract findDefaultNetworkInteract) { 16 | return new GasSettingsViewModelFactory(findDefaultNetworkInteract); 17 | } 18 | 19 | @Provides 20 | FindDefaultNetworkInteract provideFindDefaultNetworkInteract( 21 | EthereumNetworkRepository ethereumNetworkRepositoryType) { 22 | return new FindDefaultNetworkInteract(ethereumNetworkRepositoryType); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/ImportModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.interact.ImportWalletInteract; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | import com.wallet.crypto.viewmodel.ImportWalletViewModelFactory; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | 10 | @Module 11 | class ImportModule { 12 | @Provides 13 | ImportWalletViewModelFactory provideImportWalletViewModelFactory( 14 | ImportWalletInteract importWalletInteract) { 15 | return new ImportWalletViewModelFactory(importWalletInteract); 16 | } 17 | 18 | @Provides 19 | ImportWalletInteract provideImportWalletInteract(WalletRepository walletRepository) { 20 | return new ImportWalletInteract(walletRepository); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/SendModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.router.ConfirmationRouter; 4 | import com.wallet.crypto.viewmodel.SendViewModelFactory; 5 | 6 | import dagger.Module; 7 | import dagger.Provides; 8 | 9 | @Module 10 | class SendModule { 11 | @Provides 12 | SendViewModelFactory provideSendViewModelFactory(ConfirmationRouter confirmationRouter) { 13 | return new SendViewModelFactory(confirmationRouter); 14 | } 15 | 16 | @Provides 17 | ConfirmationRouter provideConfirmationRouter() { 18 | return new ConfirmationRouter(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/SettingsFragmentModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.interact.FindDefaultWalletInteract; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | import com.wallet.crypto.router.ManageWalletsRouter; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | 10 | @Module 11 | class SettingsFragmentModule { 12 | @Provides 13 | FindDefaultWalletInteract provideFindDefaultWalletInteract(WalletRepository walletRepository) { 14 | return new FindDefaultWalletInteract(walletRepository); 15 | } 16 | 17 | @Provides 18 | ManageWalletsRouter provideManageWalletsRouter() { 19 | return new ManageWalletsRouter(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/SettingsModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.ui.SettingsFragment; 4 | 5 | import dagger.Module; 6 | import dagger.android.ContributesAndroidInjector; 7 | 8 | @Module 9 | public interface SettingsModule { 10 | @FragmentScope 11 | @ContributesAndroidInjector(modules = {SettingsFragmentModule.class}) 12 | SettingsFragment settingsFragment(); 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/SplashModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.interact.FetchWalletsInteract; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | import com.wallet.crypto.viewmodel.SplashViewModelFactory; 6 | 7 | import dagger.Module; 8 | import dagger.Provides; 9 | 10 | @Module 11 | public class SplashModule { 12 | 13 | @Provides 14 | SplashViewModelFactory provideSplashViewModelFactory(FetchWalletsInteract fetchWalletsInteract) { 15 | return new SplashViewModelFactory(fetchWalletsInteract); 16 | } 17 | 18 | @Provides 19 | FetchWalletsInteract provideFetchWalletInteract(WalletRepository walletRepository) { 20 | return new FetchWalletsInteract(walletRepository); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/ToolsModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import android.content.Context; 4 | 5 | import com.google.gson.Gson; 6 | import com.safframework.http.interceptor.LoggingInterceptor; 7 | import com.wallet.crypto.App; 8 | 9 | import javax.inject.Singleton; 10 | 11 | import dagger.Module; 12 | import dagger.Provides; 13 | import okhttp3.OkHttpClient; 14 | 15 | @Module 16 | class ToolsModule { 17 | @Provides 18 | Context provideContext(App application) { 19 | return application.getApplicationContext(); 20 | } 21 | 22 | @Singleton 23 | @Provides 24 | Gson provideGson() { 25 | return new Gson(); 26 | } 27 | 28 | @Singleton 29 | @Provides 30 | OkHttpClient okHttpClient() { 31 | return new OkHttpClient.Builder() 32 | .addInterceptor(loggingInterceptor) 33 | .build(); 34 | } 35 | 36 | private LoggingInterceptor loggingInterceptor = new LoggingInterceptor.Builder() 37 | .loggable(true) // TODO: 发布到生产环境需要改成false 38 | .request() 39 | .requestTag("Request") 40 | .response() 41 | .responseTag("Response") 42 | .build(); 43 | } 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/di/TransactionDetailModule.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.di; 2 | 3 | import com.wallet.crypto.interact.FindDefaultNetworkInteract; 4 | import com.wallet.crypto.interact.FindDefaultWalletInteract; 5 | import com.wallet.crypto.repository.EthereumNetworkRepository; 6 | import com.wallet.crypto.repository.WalletRepository; 7 | import com.wallet.crypto.router.ExternalBrowserRouter; 8 | import com.wallet.crypto.viewmodel.TransactionDetailViewModelFactory; 9 | 10 | import dagger.Module; 11 | import dagger.Provides; 12 | 13 | @Module 14 | public class TransactionDetailModule { 15 | 16 | @Provides 17 | TransactionDetailViewModelFactory provideTransactionDetailViewModelFactory( 18 | FindDefaultNetworkInteract findDefaultNetworkInteract, 19 | FindDefaultWalletInteract findDefaultWalletInteract, 20 | ExternalBrowserRouter externalBrowserRouter) { 21 | return new TransactionDetailViewModelFactory( 22 | findDefaultNetworkInteract, findDefaultWalletInteract, externalBrowserRouter); 23 | } 24 | 25 | @Provides 26 | FindDefaultNetworkInteract provideFindDefaultNetworkInteract( 27 | EthereumNetworkRepository ethereumNetworkRepository) { 28 | return new FindDefaultNetworkInteract(ethereumNetworkRepository); 29 | } 30 | 31 | @Provides 32 | ExternalBrowserRouter externalBrowserRouter() { 33 | return new ExternalBrowserRouter(); 34 | } 35 | 36 | @Provides 37 | FindDefaultWalletInteract findDefaultWalletInteract(WalletRepository walletRepository) { 38 | return new FindDefaultWalletInteract(walletRepository); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/Account.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity 2 | 3 | import java.io.Serializable 4 | 5 | /** 6 | * @author Aaron 7 | * @email aaron@magicwindow.cn 8 | * @date 08/03/2018 16:34 9 | * @description 10 | */ 11 | data class Account(var address: String, 12 | var dateAdded: Long 13 | // var privateKey: String, 14 | // var publicKey: String, 15 | // var mnemonic: List, 16 | // var mnemonicPath: String, 17 | // var keystore: String 18 | ) : Serializable { 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/Address.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.text.TextUtils; 4 | 5 | import org.web3j.crypto.WalletUtils; 6 | 7 | import java.util.regex.Pattern; 8 | 9 | public class Address { 10 | 11 | private static final Pattern ignoreCaseAddrPattern = Pattern.compile("(?i)^(0x)?[0-9a-f]{40}$"); 12 | private static final Pattern lowerCaseAddrPattern = Pattern.compile("^(0x)?[0-9a-f]{40}$"); 13 | private static final Pattern upperCaseAddrPattern = Pattern.compile("^(0x)?[0-9A-F]{40}$"); 14 | 15 | public final String value; 16 | 17 | public Address(String value) { 18 | this.value = value; 19 | } 20 | 21 | public static boolean isAddress(String address) { 22 | return WalletUtils.isValidAddress(address); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/ApiErrorException.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | public class ApiErrorException extends Exception { 4 | private final ErrorEnvelope errorEnvelope; 5 | 6 | public ApiErrorException(ErrorEnvelope errorEnvelope) { 7 | super(errorEnvelope.message); 8 | 9 | this.errorEnvelope = errorEnvelope; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/ErrorEnvelope.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | import com.wallet.crypto.MercuryConstants; 6 | 7 | public class ErrorEnvelope { 8 | public final int code; 9 | @Nullable 10 | public final String message; 11 | @Nullable 12 | private final Throwable throwable; 13 | 14 | public ErrorEnvelope(@Nullable String message) { 15 | this(MercuryConstants.ErrorCode.UNKNOWN, message); 16 | } 17 | 18 | public ErrorEnvelope(int code, @Nullable String message) { 19 | this(code, message, null); 20 | } 21 | 22 | public ErrorEnvelope(int code, @Nullable String message, @Nullable Throwable throwable) { 23 | this.code = code; 24 | this.message = message; 25 | this.throwable = throwable; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/GasSettings.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | 4 | import android.os.Parcel; 5 | import android.os.Parcelable; 6 | 7 | import java.math.BigInteger; 8 | 9 | public class GasSettings implements Parcelable { 10 | public final BigInteger gasPrice; 11 | public final BigInteger gasLimit; 12 | 13 | public GasSettings(BigInteger gasPrice, BigInteger gasLimit) { 14 | this.gasPrice = gasPrice; 15 | this.gasLimit = gasLimit; 16 | } 17 | 18 | private GasSettings(Parcel in) { 19 | gasPrice = new BigInteger(in.readString()); 20 | gasLimit = new BigInteger(in.readString()); 21 | } 22 | 23 | public static final Creator CREATOR = new Creator() { 24 | @Override 25 | public GasSettings createFromParcel(Parcel in) { 26 | return new GasSettings(in); 27 | } 28 | 29 | @Override 30 | public GasSettings[] newArray(int size) { 31 | return new GasSettings[size]; 32 | } 33 | }; 34 | 35 | @Override 36 | public int describeContents() { 37 | return 0; 38 | } 39 | 40 | @Override 41 | public void writeToParcel(Parcel parcel, int i) { 42 | parcel.writeString(gasPrice.toString(10)); 43 | parcel.writeString(gasLimit.toString(10)); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/NetworkInfo.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | public class NetworkInfo { 4 | public final String name; 5 | public final String symbol; 6 | public final String rpcServerUrl; 7 | public final String backendUrl; 8 | public final String etherscanUrl; 9 | public final int chainId; 10 | public final boolean isMainNetwork; 11 | 12 | public NetworkInfo( 13 | String name, 14 | String symbol, 15 | String rpcServerUrl, 16 | String backendUrl, 17 | String etherscanUrl, 18 | int chainId, 19 | boolean isMainNetwork) { 20 | this.name = name; 21 | this.symbol = symbol; 22 | this.rpcServerUrl = rpcServerUrl; 23 | this.backendUrl = backendUrl; 24 | this.etherscanUrl = etherscanUrl; 25 | this.chainId = chainId; 26 | this.isMainNetwork = isMainNetwork; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/ServiceErrorException.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.support.annotation.Nullable; 4 | 5 | public class ServiceErrorException extends Exception { 6 | 7 | public static final int UNKNOWN_ERROR = -1; 8 | public static final int INVALID_DATA = 1; 9 | public static final int KEY_STORE_ERROR = 1001; 10 | public static final int FAIL_TO_SAVE_IV_FILE = 1002; 11 | public static final int KEY_STORE_SECRET = 1003; 12 | public static final int USER_NOT_AUTHENTICATED = 1004; 13 | public static final int KEY_IS_GONE = 1005; 14 | public static final int IV_OR_ALIAS_NO_ON_DISK = 1006; 15 | public static final int INVALID_KEY = 1007; 16 | 17 | public final int code; 18 | 19 | public ServiceErrorException(int code, @Nullable String message, Throwable throwable) { 20 | super(message, throwable); 21 | this.code = code; 22 | } 23 | 24 | public ServiceErrorException(int code, @Nullable String message) { 25 | this(code, message, null); 26 | } 27 | 28 | public ServiceErrorException(int code) { 29 | this(code, null); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | public class ServiceException extends Exception { 4 | public final ErrorEnvelope error; 5 | 6 | public ServiceException(String message) { 7 | super(message); 8 | 9 | error = new ErrorEnvelope(message); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/StorableAccounts.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity 2 | 3 | /** 4 | * @author Aaron 5 | * @email aaron@magicwindow.cn 6 | * @date 08/03/2018 16:34 7 | * @description 8 | */ 9 | data class StorableAccounts(var account: MutableList) 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/Ticker.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import com.google.gson.annotations.SerializedName; 4 | 5 | public class Ticker { 6 | public String id; 7 | public String name; 8 | public String symbol; 9 | public String price; 10 | @SerializedName("percent_change_24h") 11 | public String percentChange24h; 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/Token.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | import java.math.BigDecimal; 7 | 8 | public class Token implements Parcelable { 9 | public final TokenInfo tokenInfo; 10 | public final BigDecimal balance; 11 | 12 | public Token(TokenInfo tokenInfo, BigDecimal balance) { 13 | this.tokenInfo = tokenInfo; 14 | this.balance = balance; 15 | } 16 | 17 | private Token(Parcel in) { 18 | tokenInfo = in.readParcelable(TokenInfo.class.getClassLoader()); 19 | balance = new BigDecimal(in.readString()); 20 | } 21 | 22 | public static final Creator CREATOR = new Creator() { 23 | @Override 24 | public Token createFromParcel(Parcel in) { 25 | return new Token(in); 26 | } 27 | 28 | @Override 29 | public Token[] newArray(int size) { 30 | return new Token[size]; 31 | } 32 | }; 33 | 34 | @Override 35 | public int describeContents() { 36 | return 0; 37 | } 38 | 39 | @Override 40 | public void writeToParcel(Parcel dest, int flags) { 41 | dest.writeParcelable(tokenInfo, flags); 42 | dest.writeString(balance.toString()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/TokenInfo.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class TokenInfo implements Parcelable { 7 | public final String address; 8 | public final String name; 9 | public final String symbol; 10 | public final int decimals; 11 | 12 | public TokenInfo(String address, String name, String symbol, int decimals) { 13 | this.address = address; 14 | this.name = name; 15 | this.symbol = symbol; 16 | this.decimals = decimals; 17 | } 18 | 19 | private TokenInfo(Parcel in) { 20 | address = in.readString(); 21 | name = in.readString(); 22 | symbol = in.readString(); 23 | decimals = in.readInt(); 24 | } 25 | 26 | public static final Creator CREATOR = new Creator() { 27 | @Override 28 | public TokenInfo createFromParcel(Parcel in) { 29 | return new TokenInfo(in); 30 | } 31 | 32 | @Override 33 | public TokenInfo[] newArray(int size) { 34 | return new TokenInfo[size]; 35 | } 36 | }; 37 | 38 | @Override 39 | public int describeContents() { 40 | return 0; 41 | } 42 | 43 | @Override 44 | public void writeToParcel(Parcel dest, int flags) { 45 | dest.writeString(address); 46 | dest.writeString(name); 47 | dest.writeString(symbol); 48 | dest.writeInt(decimals); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/TransactionContract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity; 2 | 3 | import android.os.Parcel; 4 | import android.os.Parcelable; 5 | 6 | public class TransactionContract implements Parcelable { 7 | public String address; 8 | public String name; 9 | public String totalSupply; 10 | public long decimals; 11 | public String symbol; 12 | 13 | protected TransactionContract(Parcel in) { 14 | address = in.readString(); 15 | name = in.readString(); 16 | totalSupply = in.readString(); 17 | decimals = in.readLong(); 18 | symbol = in.readString(); 19 | } 20 | 21 | public static final Creator CREATOR = new Creator() { 22 | @Override 23 | public TransactionContract createFromParcel(Parcel in) { 24 | return new TransactionContract(in); 25 | } 26 | 27 | @Override 28 | public TransactionContract[] newArray(int size) { 29 | return new TransactionContract[size]; 30 | } 31 | }; 32 | 33 | @Override 34 | public int describeContents() { 35 | return 0; 36 | } 37 | 38 | @Override 39 | public void writeToParcel(Parcel parcel, int i) { 40 | parcel.writeString(address); 41 | parcel.writeString(name); 42 | parcel.writeString(totalSupply); 43 | parcel.writeLong(decimals); 44 | parcel.writeString(symbol); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/Wallet.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity 2 | 3 | import java.io.Serializable 4 | 5 | class Wallet(address: String) :Serializable { 6 | val address: String = address 7 | get() = generateAddress(field) 8 | 9 | 10 | private fun generateAddress(address: String): String { 11 | return if (!address.startsWith("0x") && !address.startsWith("0X")) { 12 | "0x$address" 13 | } else address 14 | } 15 | 16 | 17 | fun sameAddress(address: String): Boolean { 18 | return this.address == address 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/entity/WalletDisplay.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.entity 2 | 3 | import com.wallet.crypto.util.ExchangeCalculator 4 | import java.math.BigDecimal 5 | import java.math.BigInteger 6 | 7 | /** 8 | * @author Aaron 9 | * @email aaron@magicwindow.cn 10 | * @date 08/03/2018 16:58 11 | * @description 12 | */ 13 | class WalletDisplay : Comparable { 14 | 15 | var name: String? = null 16 | var publicKey: String? = null 17 | get() = field!!.toLowerCase() 18 | var balanceNative: BigInteger? = null 19 | private set 20 | var type: Byte = 0 21 | 22 | val balance: Double 23 | get() = 24 | BigDecimal(balanceNative).divide(ExchangeCalculator.ONE_ETHER, 8, BigDecimal.ROUND_UP).toDouble() 25 | 26 | constructor(name: String, publicKey: String, balance: BigInteger, type: Byte) { 27 | this.name = name 28 | this.publicKey = publicKey 29 | this.balanceNative = balance 30 | this.type = type 31 | } 32 | 33 | constructor(name: String, publicKey: String) { 34 | this.name = name 35 | this.publicKey = publicKey 36 | this.balanceNative = null 37 | this.type = CONTACT 38 | } 39 | 40 | fun setBalance(balance: BigInteger) { 41 | this.balanceNative = balance 42 | } 43 | 44 | override operator fun compareTo(o: Any): Int { 45 | return name!!.compareTo((o as WalletDisplay).name!!) 46 | } 47 | 48 | companion object { 49 | 50 | val NORMAL: Byte = 0 51 | val WATCH_ONLY: Byte = 1 52 | val CONTACT: Byte = 2 53 | } 54 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/AddTokenInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.repository.TokenRepository; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Completable; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | 9 | public class AddTokenInteract { 10 | private final TokenRepository tokenRepository; 11 | private final WalletRepository walletRepository; 12 | 13 | public AddTokenInteract( 14 | WalletRepository walletRepository, TokenRepository tokenRepository) { 15 | this.walletRepository = walletRepository; 16 | this.tokenRepository = tokenRepository; 17 | } 18 | 19 | public Completable add(String address, String symbol, int decimals) { 20 | return walletRepository 21 | .getDefaultWallet() 22 | .flatMapCompletable( 23 | wallet -> tokenRepository 24 | .addToken(wallet, address, symbol, decimals) 25 | .observeOn(AndroidSchedulers.mainThread())); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/CreateTransactionInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | 4 | import com.wallet.crypto.entity.Wallet; 5 | import com.wallet.crypto.repository.TransactionRepository; 6 | 7 | import java.math.BigInteger; 8 | 9 | import io.reactivex.Single; 10 | import io.reactivex.android.schedulers.AndroidSchedulers; 11 | 12 | public class CreateTransactionInteract { 13 | private final TransactionRepository transactionRepository; 14 | 15 | public CreateTransactionInteract(TransactionRepository transactionRepository) { 16 | this.transactionRepository = transactionRepository; 17 | } 18 | 19 | public Single create(String password,Wallet from, String to, BigInteger subunitAmount, BigInteger gasPrice, BigInteger gasLimit, String data) { 20 | return transactionRepository.createTransaction(from, to, subunitAmount, gasPrice, gasLimit, data, password) 21 | .observeOn(AndroidSchedulers.mainThread()); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/CreateWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.interact.rx.operator.Operators; 5 | import com.wallet.crypto.repository.WalletRepository; 6 | 7 | import io.reactivex.Single; 8 | 9 | import static com.wallet.crypto.interact.rx.operator.Operators.completableErrorProxy; 10 | 11 | public class CreateWalletInteract { 12 | 13 | private final WalletRepository walletRepository; 14 | 15 | public CreateWalletInteract(WalletRepository walletRepository) { 16 | this.walletRepository = walletRepository; 17 | } 18 | 19 | /** 20 | * 创建钱包 21 | * 22 | * @return 23 | * @param pwd 24 | */ 25 | public Single create(String pwd) { 26 | return walletRepository 27 | .createWallet(pwd) 28 | .compose(Operators.savePassword(walletRepository)) 29 | .flatMap(this::passwordVerification); 30 | } 31 | 32 | private Single passwordVerification(Wallet wallet) { 33 | return walletRepository 34 | .exportWallet(wallet) 35 | .flatMap(keyStore -> walletRepository.findWallet(wallet.getAddress())) 36 | .onErrorResumeNext(throwable -> walletRepository 37 | .deleteWallet(wallet.getAddress()) 38 | .lift(completableErrorProxy(throwable)) 39 | .toSingle(() -> wallet)); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/DeleteWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Single; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | 9 | /** 10 | * Delete and fetch wallets 11 | */ 12 | public class DeleteWalletInteract { 13 | private final WalletRepository walletRepository; 14 | 15 | public DeleteWalletInteract(WalletRepository walletRepository) { 16 | this.walletRepository = walletRepository; 17 | } 18 | 19 | public Single delete(Wallet wallet) { 20 | return walletRepository.deleteWallet(wallet.getAddress()) 21 | .andThen(walletRepository.fetchWallets()) 22 | .observeOn(AndroidSchedulers.mainThread()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/ExportWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Single; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | 9 | public class ExportWalletInteract { 10 | 11 | private final WalletRepository walletRepository; 12 | 13 | public ExportWalletInteract(WalletRepository walletRepository) { 14 | this.walletRepository = walletRepository; 15 | } 16 | 17 | public Single export(Wallet wallet) { 18 | return walletRepository 19 | .exportWallet(wallet) 20 | .observeOn(AndroidSchedulers.mainThread()); 21 | } 22 | 23 | public Single exportPrivateKey(String pwd,Wallet wallet) { 24 | return walletRepository 25 | .exportPrivateKey(pwd,wallet) 26 | .observeOn(AndroidSchedulers.mainThread()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FetchGasSettingsInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | 4 | import com.wallet.crypto.entity.GasSettings; 5 | import com.wallet.crypto.repository.SharedPreferenceRepository; 6 | 7 | public class FetchGasSettingsInteract { 8 | private final SharedPreferenceRepository repository; 9 | 10 | public FetchGasSettingsInteract(SharedPreferenceRepository repository) { 11 | this.repository = repository; 12 | } 13 | 14 | public GasSettings fetch(boolean forTokenTransfer) { 15 | return repository.getGasSettings(forTokenTransfer); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FetchTokensInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import android.util.Log; 4 | 5 | import com.wallet.crypto.entity.Token; 6 | import com.wallet.crypto.entity.Wallet; 7 | import com.wallet.crypto.repository.TokenRepository; 8 | 9 | import io.reactivex.Observable; 10 | import io.reactivex.Single; 11 | import io.reactivex.android.schedulers.AndroidSchedulers; 12 | import io.reactivex.schedulers.Schedulers; 13 | 14 | public class FetchTokensInteract { 15 | 16 | private final TokenRepository tokenRepository; 17 | 18 | public FetchTokensInteract(TokenRepository tokenRepository) { 19 | this.tokenRepository = tokenRepository; 20 | } 21 | 22 | public Observable fetch(Wallet wallet) { 23 | Log.d("aaron","FetchTokensInteract address:"+wallet.getAddress()); 24 | 25 | return tokenRepository.fetch(wallet.getAddress()) 26 | .subscribeOn(Schedulers.io()) 27 | .observeOn(AndroidSchedulers.mainThread()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FetchTransactionsInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Transaction; 4 | import com.wallet.crypto.entity.Wallet; 5 | import com.wallet.crypto.repository.TransactionRepository; 6 | 7 | import io.reactivex.Observable; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | 10 | public class FetchTransactionsInteract { 11 | 12 | private final TransactionRepository transactionRepository; 13 | 14 | public FetchTransactionsInteract(TransactionRepository transactionRepository) { 15 | this.transactionRepository = transactionRepository; 16 | } 17 | 18 | public Observable fetch(Wallet wallet) { 19 | return transactionRepository 20 | .fetchTransaction(wallet) 21 | .observeOn(AndroidSchedulers.mainThread()); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FetchWalletsInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Single; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | 9 | public class FetchWalletsInteract { 10 | 11 | private final WalletRepository accountRepository; 12 | 13 | public FetchWalletsInteract(WalletRepository accountRepository) { 14 | this.accountRepository = accountRepository; 15 | } 16 | 17 | public Single fetch() { 18 | return accountRepository 19 | .fetchWallets() 20 | .observeOn(AndroidSchedulers.mainThread()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FindDefaultNetworkInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.NetworkInfo; 4 | import com.wallet.crypto.repository.EthereumNetworkRepository; 5 | import com.wallet.crypto.service.EthplorerTokenService; 6 | 7 | import io.reactivex.Single; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | 10 | public class FindDefaultNetworkInteract { 11 | 12 | private final EthereumNetworkRepository ethereumNetworkRepository; 13 | 14 | public FindDefaultNetworkInteract(EthereumNetworkRepository ethereumNetworkRepository) { 15 | this.ethereumNetworkRepository = ethereumNetworkRepository; 16 | } 17 | 18 | public Single find() { 19 | return Single.just(ethereumNetworkRepository.getDefaultNetwork()) 20 | .observeOn(AndroidSchedulers.mainThread()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/FindDefaultWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Flowable; 7 | import io.reactivex.Single; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | 10 | public class FindDefaultWalletInteract { 11 | 12 | private final WalletRepository walletRepository; 13 | 14 | public FindDefaultWalletInteract(WalletRepository walletRepository) { 15 | this.walletRepository = walletRepository; 16 | } 17 | 18 | public Single find() { 19 | return walletRepository 20 | .getDefaultWallet() 21 | .onErrorResumeNext(walletRepository 22 | .fetchWallets() 23 | .to(single -> Flowable.fromArray(single.blockingGet())) 24 | .firstOrError() 25 | .flatMapCompletable(walletRepository::setDefaultWallet) 26 | .andThen(walletRepository.getDefaultWallet())) 27 | .observeOn(AndroidSchedulers.mainThread()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/ImportWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.interact.rx.operator.Operators; 5 | import com.wallet.crypto.repository.WalletRepository; 6 | 7 | import io.reactivex.Single; 8 | import io.reactivex.android.schedulers.AndroidSchedulers; 9 | 10 | public class ImportWalletInteract { 11 | 12 | private final WalletRepository walletRepository; 13 | 14 | public ImportWalletInteract(WalletRepository walletRepository) { 15 | this.walletRepository = walletRepository; 16 | } 17 | 18 | public Single importKeystore(String keystore, String password) { 19 | return walletRepository 20 | .importKeystoreToWallet(keystore, password) 21 | .compose(Operators.savePassword(walletRepository)) 22 | .observeOn(AndroidSchedulers.mainThread()); 23 | } 24 | 25 | public Single importPrivateKey(String privateKey,String pwd) { 26 | return walletRepository 27 | .importPrivateKeyToWallet(privateKey,pwd) 28 | .compose(Operators.savePassword(walletRepository)) 29 | .observeOn(AndroidSchedulers.mainThread()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/SetDefaultWalletInteract.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Completable; 7 | import io.reactivex.android.schedulers.AndroidSchedulers; 8 | 9 | public class SetDefaultWalletInteract { 10 | 11 | private WalletRepository accountRepository; 12 | 13 | public SetDefaultWalletInteract(WalletRepository walletRepositoryType) { 14 | this.accountRepository = walletRepositoryType; 15 | } 16 | 17 | public Completable set(Wallet wallet) { 18 | return accountRepository 19 | .setDefaultWallet(wallet) 20 | .observeOn(AndroidSchedulers.mainThread()); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/rx/operator/CompletableErrorProxyOperator.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact.rx.operator; 2 | 3 | import io.reactivex.CompletableObserver; 4 | import io.reactivex.CompletableOperator; 5 | import io.reactivex.observers.DisposableCompletableObserver; 6 | 7 | public class CompletableErrorProxyOperator implements CompletableOperator { 8 | 9 | private final Throwable throwable; 10 | 11 | CompletableErrorProxyOperator(Throwable throwable) { 12 | this.throwable = throwable; 13 | } 14 | 15 | @Override 16 | public CompletableObserver apply(CompletableObserver observer) throws Exception { 17 | return new DisposableCompletableObserver() { 18 | @Override 19 | public void onComplete() { 20 | if (!isDisposed()) { 21 | observer.onError(throwable); 22 | } 23 | } 24 | 25 | @Override 26 | public void onError(Throwable ex) { 27 | if (!isDisposed()) { 28 | observer.onError(ex); 29 | } 30 | } 31 | }; 32 | } 33 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/rx/operator/Operators.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact.rx.operator; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.CompletableOperator; 7 | import io.reactivex.SingleTransformer; 8 | 9 | public class Operators { 10 | 11 | public static SingleTransformer savePassword(WalletRepository walletRepository) { 12 | return new SavePasswordOperator(walletRepository); 13 | } 14 | 15 | public static CompletableOperator completableErrorProxy(Throwable throwable) { 16 | return new CompletableErrorProxyOperator(throwable); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/interact/rx/operator/SavePasswordOperator.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.interact.rx.operator; 2 | 3 | import com.wallet.crypto.entity.Wallet; 4 | import com.wallet.crypto.repository.WalletRepository; 5 | 6 | import io.reactivex.Single; 7 | import io.reactivex.SingleSource; 8 | import io.reactivex.SingleTransformer; 9 | 10 | public class SavePasswordOperator implements SingleTransformer { 11 | 12 | private final WalletRepository walletRepository; 13 | 14 | public SavePasswordOperator(WalletRepository walletRepository) { 15 | this.walletRepository = walletRepository; 16 | } 17 | 18 | @Override 19 | public SingleSource apply(Single upstream) { 20 | Wallet wallet = upstream.blockingGet(); 21 | return Single.fromCallable(() -> wallet); 22 | // return passwordStore 23 | // .setPassword(wallet, password) 24 | // .onErrorResumeNext(err -> walletRepository.deleteWallet(wallet.getAddress()) 25 | // .lift(observer -> new DisposableCompletableObserver() { 26 | // @Override 27 | // public void onComplete() { 28 | // observer.onError(err); 29 | // } 30 | // 31 | // @Override 32 | // public void onError(Throwable e) { 33 | // observer.onError(e); 34 | // } 35 | // })) 36 | // .toSingle(() -> wallet); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/repository/OnNetworkChangeListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.repository; 2 | 3 | import com.wallet.crypto.entity.NetworkInfo; 4 | 5 | public interface OnNetworkChangeListener { 6 | void onNetworkChanged(NetworkInfo networkInfo); 7 | } 8 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/repository/TransactionInDiskSource.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.repository; 2 | 3 | import com.wallet.crypto.entity.Transaction; 4 | import com.wallet.crypto.entity.Wallet; 5 | 6 | import io.reactivex.Single; 7 | 8 | public class TransactionInDiskSource implements TransactionLocalSource { 9 | @Override 10 | public Single fetchTransaction(Wallet wallet) { 11 | return null; 12 | } 13 | 14 | @Override 15 | public void putTransactions(Wallet wallet, Transaction[] transactions) { 16 | 17 | } 18 | 19 | @Override 20 | public void clear() { 21 | 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/repository/TransactionLocalSource.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.repository; 2 | 3 | import com.wallet.crypto.entity.Transaction; 4 | import com.wallet.crypto.entity.Wallet; 5 | 6 | import io.reactivex.Single; 7 | 8 | public interface TransactionLocalSource { 9 | Single fetchTransaction(Wallet wallet); 10 | 11 | void putTransactions(Wallet wallet, Transaction[] transactions); 12 | 13 | void clear(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/repository/entity/DbTokenInfo1.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.repository.entity; 2 | 3 | import android.arch.persistence.room.Entity; 4 | import android.arch.persistence.room.PrimaryKey; 5 | 6 | 7 | @Entity 8 | public class DbTokenInfo1 { 9 | @PrimaryKey 10 | private String address; 11 | private String name; 12 | private String symbol; 13 | private int decimals; 14 | private long addedTime; 15 | 16 | public int getDecimals() { 17 | return decimals; 18 | } 19 | 20 | public void setDecimals(int decimals) { 21 | this.decimals = decimals; 22 | } 23 | 24 | public String getSymbol() { 25 | return symbol; 26 | } 27 | 28 | public void setSymbol(String symbol) { 29 | this.symbol = symbol; 30 | } 31 | 32 | public String getName() { 33 | return name; 34 | } 35 | 36 | public void setName(String name) { 37 | this.name = name; 38 | } 39 | 40 | public String getAddress() { 41 | return address; 42 | } 43 | 44 | public void setAddress(String address) { 45 | this.address = address; 46 | } 47 | 48 | public long getAddedTime() { 49 | return addedTime; 50 | } 51 | 52 | public void setAddedTime(long addedTime) { 53 | this.addedTime = addedTime; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/repository/entity/RealmTokenInfo.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.repository.entity; 2 | 3 | import io.realm.RealmObject; 4 | import io.realm.annotations.PrimaryKey; 5 | 6 | public class RealmTokenInfo extends RealmObject { 7 | @PrimaryKey 8 | private String address; 9 | private String name; 10 | private String symbol; 11 | private int decimals; 12 | private long addedTime; 13 | 14 | public int getDecimals() { 15 | return decimals; 16 | } 17 | 18 | public void setDecimals(int decimals) { 19 | this.decimals = decimals; 20 | } 21 | 22 | public String getSymbol() { 23 | return symbol; 24 | } 25 | 26 | public void setSymbol(String symbol) { 27 | this.symbol = symbol; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getAddress() { 39 | return address; 40 | } 41 | 42 | public void setAddress(String address) { 43 | this.address = address; 44 | } 45 | 46 | public long getAddedTime() { 47 | return addedTime; 48 | } 49 | 50 | public void setAddedTime(long addedTime) { 51 | this.addedTime = addedTime; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/AddTokenRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.ui.AddTokenActivity; 7 | 8 | public class AddTokenRouter { 9 | 10 | public void open(Context context) { 11 | Intent intent = new Intent(context, AddTokenActivity.class); 12 | context.startActivity(intent); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/ConfirmationRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.wallet.crypto.MercuryConstants; 8 | import com.wallet.crypto.ui.ConfirmationActivity; 9 | 10 | import java.math.BigInteger; 11 | 12 | public class ConfirmationRouter { 13 | public void open(Context context, String to, BigInteger amount, String contractAddress, int decimals, String symbol, boolean sendingTokens) { 14 | Intent intent = new Intent(context, ConfirmationActivity.class); 15 | intent.putExtra(MercuryConstants.EXTRA_TO_ADDRESS, to); 16 | intent.putExtra(MercuryConstants.EXTRA_AMOUNT, amount.toString()); 17 | intent.putExtra(MercuryConstants.EXTRA_CONTRACT_ADDRESS, contractAddress); 18 | intent.putExtra(MercuryConstants.EXTRA_DECIMALS, decimals); 19 | intent.putExtra(MercuryConstants.EXTRA_SYMBOL, symbol); 20 | intent.putExtra(MercuryConstants.EXTRA_SENDING_TOKENS, sendingTokens); 21 | context.startActivity(intent); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/ExternalBrowserRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.net.Uri; 6 | 7 | public class ExternalBrowserRouter { 8 | 9 | public void open(Context context, Uri uri) { 10 | Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uri); 11 | context.startActivity(launchBrowser); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/GasSettingsRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | 4 | import android.app.Activity; 5 | import android.content.Intent; 6 | 7 | import com.wallet.crypto.MercuryConstants; 8 | import com.wallet.crypto.entity.GasSettings; 9 | import com.wallet.crypto.ui.GasSettingsActivity; 10 | import com.wallet.crypto.viewmodel.GasSettingsViewModel; 11 | 12 | public class GasSettingsRouter { 13 | public void open(Activity context, GasSettings gasSettings) { 14 | Intent intent = new Intent(context, GasSettingsActivity.class); 15 | intent.putExtra(MercuryConstants.EXTRA_GAS_PRICE, gasSettings.gasPrice.toString()); 16 | intent.putExtra(MercuryConstants.EXTRA_GAS_LIMIT, gasSettings.gasLimit.toString()); 17 | context.startActivityForResult(intent, GasSettingsViewModel.SET_GAS_SETTINGS); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/ImportWalletRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.wallet.crypto.ui.ImportWalletActivity; 8 | 9 | public class ImportWalletRouter { 10 | 11 | public void open(Context context) { 12 | Intent intent = new Intent(context, ImportWalletActivity.class); 13 | context.startActivity(intent); 14 | } 15 | 16 | public void openForResult(Activity activity, int requestCode) { 17 | Intent intent = new Intent(activity, ImportWalletActivity.class); 18 | activity.startActivityForResult(intent, requestCode); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/MainRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.ui.MainActivity; 7 | 8 | public class MainRouter { 9 | public void open(Context context, boolean isClearStack) { 10 | Intent intent = new Intent(context, MainActivity.class); 11 | if (isClearStack) { 12 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 13 | } 14 | context.startActivity(intent); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/ManageWalletsRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.ui.WalletsActivity; 7 | 8 | public class ManageWalletsRouter { 9 | 10 | public void open(Context context, boolean isClearStack) { 11 | Intent intent = new Intent(context, WalletsActivity.class); 12 | if (isClearStack) { 13 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); 14 | } 15 | context.startActivity(intent); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/MyAddressRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.entity.Wallet; 7 | import com.wallet.crypto.ui.MyAddressActivity; 8 | 9 | import static com.wallet.crypto.MercuryConstants.Key.WALLET; 10 | 11 | public class MyAddressRouter { 12 | 13 | public void open(Context context, Wallet wallet) { 14 | Intent intent = new Intent(context, MyAddressActivity.class); 15 | intent.putExtra(WALLET, wallet); 16 | context.startActivity(intent); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/MyTokensRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.entity.Wallet; 7 | import com.wallet.crypto.ui.TokensActivity; 8 | 9 | import static com.wallet.crypto.MercuryConstants.Key.WALLET; 10 | 11 | public class MyTokensRouter { 12 | 13 | public void open(Context context, Wallet wallet) { 14 | Intent intent = new Intent(context, TokensActivity.class); 15 | intent.putExtra(WALLET, wallet); 16 | intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); 17 | context.startActivity(intent); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/SendRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.ui.SendActivity; 7 | 8 | public class SendRouter { 9 | 10 | public void open(Context context) { 11 | Intent intent = new Intent(context, SendActivity.class); 12 | context.startActivity(intent); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/SendTokenRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | import com.wallet.crypto.MercuryConstants; 8 | import com.wallet.crypto.ui.SendActivity; 9 | 10 | public class SendTokenRouter { 11 | public void open(Context context, String address, String symbol, int decimals) { 12 | Intent intent = new Intent(context, SendActivity.class); 13 | intent.putExtra(MercuryConstants.EXTRA_SENDING_TOKENS, true); 14 | intent.putExtra(MercuryConstants.EXTRA_CONTRACT_ADDRESS, address); 15 | intent.putExtra(MercuryConstants.EXTRA_SYMBOL, symbol); 16 | intent.putExtra(MercuryConstants.EXTRA_DECIMALS, decimals); 17 | context.startActivity(intent); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/SettingsRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.ui.SettingsActivity; 7 | 8 | public class SettingsRouter { 9 | 10 | public void open(Context context) { 11 | Intent intent = new Intent(context, SettingsActivity.class); 12 | context.startActivity(intent); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/router/TransactionDetailRouter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.router; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | 6 | import com.wallet.crypto.entity.Transaction; 7 | import com.wallet.crypto.ui.TransactionDetailActivity; 8 | 9 | import static com.wallet.crypto.MercuryConstants.Key.TRANSACTION; 10 | 11 | public class TransactionDetailRouter { 12 | 13 | public void open(Context context, Transaction transaction) { 14 | Intent intent = new Intent(context, TransactionDetailActivity.class); 15 | intent.putExtra(TRANSACTION, transaction); 16 | context.startActivity(intent); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/service/TickerService.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.service; 2 | 3 | import com.wallet.crypto.entity.Ticker; 4 | 5 | import io.reactivex.Observable; 6 | 7 | public interface TickerService { 8 | 9 | Observable fetchTickerPrice(String ticker); 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/SettingsActivity.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui; 2 | 3 | import android.app.Fragment; 4 | import android.os.Bundle; 5 | import android.view.MenuItem; 6 | 7 | import com.wallet.crypto.R; 8 | import com.wallet.crypto.router.MainRouter; 9 | 10 | import javax.inject.Inject; 11 | 12 | import dagger.android.AndroidInjector; 13 | import dagger.android.DispatchingAndroidInjector; 14 | import dagger.android.HasFragmentInjector; 15 | 16 | public class SettingsActivity extends BaseActivity implements HasFragmentInjector { 17 | 18 | @Inject 19 | DispatchingAndroidInjector fragmentInjector; 20 | 21 | @Override 22 | protected void onCreate(Bundle savedInstanceState) { 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.activity_settings); 25 | toolbar(); 26 | // Display the fragment as the main content. 27 | getFragmentManager().beginTransaction() 28 | .replace(R.id.fragment_container, new SettingsFragment()) 29 | .commit(); 30 | } 31 | 32 | @Override 33 | public boolean onOptionsItemSelected(MenuItem item) { 34 | switch (item.getItemId()) { 35 | case android.R.id.home: { 36 | new MainRouter().open(this, true); 37 | return true; 38 | } 39 | } 40 | return super.onOptionsItemSelected(item); 41 | } 42 | 43 | @Override 44 | public void onBackPressed() { 45 | new MainRouter().open(this, true); 46 | } 47 | 48 | @Override 49 | public AndroidInjector fragmentInjector() { 50 | return fragmentInjector; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/SplashActivity.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui; 2 | 3 | import android.arch.lifecycle.ViewModelProviders; 4 | import android.os.Bundle; 5 | 6 | import com.wallet.crypto.entity.Wallet; 7 | import com.wallet.crypto.router.MainRouter; 8 | import com.wallet.crypto.router.ManageWalletsRouter; 9 | import com.wallet.crypto.viewmodel.SplashViewModel; 10 | import com.wallet.crypto.viewmodel.SplashViewModelFactory; 11 | 12 | import javax.inject.Inject; 13 | //import io.fabric.sdk.android.Fabric; 14 | 15 | public class SplashActivity extends BaseActivity { 16 | 17 | @Inject 18 | SplashViewModelFactory splashViewModelFactory; 19 | SplashViewModel splashViewModel; 20 | 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | 26 | splashViewModel = ViewModelProviders.of(this, splashViewModelFactory) 27 | .get(SplashViewModel.class); 28 | splashViewModel.wallets().observe(this, this::onWallets); 29 | } 30 | 31 | private void onWallets(Wallet[] wallets) { 32 | // Start home activity 33 | if (wallets.length == 0) { 34 | new ManageWalletsRouter().open(this, false); 35 | } else { 36 | new MainRouter().open(this, false); 37 | } 38 | finish(); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/DialogManager.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog 2 | 3 | import android.support.v4.app.Fragment 4 | import android.support.v4.app.FragmentActivity 5 | import com.wallet.crypto.R 6 | 7 | /** 8 | * @Description 9 | * @Author sean 10 | * @Email xiao.lu@magicwindow.cn 11 | * @Date 21/06/2018 3:53 PM 12 | * @Version 13 | */ 14 | fun Fragment.showCusDialog(dialogFragment: BaseDialogFragment): BaseDialogFragment = 15 | DialogBuilder(activity!!, dialogFragment.javaClass) 16 | .setCancelableOnTouchOutside(false) 17 | .setTargetFragment(this, 10001) 18 | .setAnimStyle(R.style.AnimScaleCenter) 19 | .showAllowingStateLoss() 20 | 21 | 22 | fun FragmentActivity.showCusDialog(dialogFragment: BaseDialogFragment): BaseDialogFragment = 23 | DialogBuilder(this, dialogFragment.javaClass) 24 | .setCancelableOnTouchOutside(false) 25 | .setAnimStyle(R.style.AnimScaleCenter) 26 | .showAllowingStateLoss() 27 | 28 | fun FragmentActivity.dialogBuilder(dialogFragment: BaseDialogFragment): DialogBuilder = 29 | DialogBuilder(this, dialogFragment.javaClass) 30 | .setCancelableOnTouchOutside(false) -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/ExportWalletsDialog.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog 2 | 3 | import android.view.LayoutInflater 4 | import cn.magicwindow.core.config.Config 5 | import com.wallet.crypto.R 6 | import com.wallet.crypto.ext.click 7 | import kotlinx.android.synthetic.main.layout_dialog_export_wallets.view.* 8 | 9 | /** 10 | * @Description 11 | * @Author sean 12 | * @Email xiao.lu@magicwindow.cn 13 | * @Date 21/06/2018 3:04 PM 14 | * @Version 15 | */ 16 | class ExportWalletsDialog : BaseDialogFragment() { 17 | 18 | override fun build(initialBuilder: Builder): Builder { 19 | val view = LayoutInflater.from(context).inflate(R.layout.layout_dialog_export_wallets, null) 20 | view.keystore.click { 21 | positiveListeners?.onPositiveButtonClicked(Config.DIALOG_EXPORT_KEYSTORE_CODE) 22 | dismiss() 23 | } 24 | view.privatekey.click { 25 | positiveListeners?.onPositiveButtonClicked(Config.DIALOG_EXPORT_PRIVATEKEY_CODE) 26 | dismiss() 27 | } 28 | view.cancel.click { dismiss() } 29 | return initialBuilder.setView(view) 30 | } 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/InputPwdDialog.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog 2 | 3 | import android.view.LayoutInflater 4 | import cn.magicwindow.core.config.Config 5 | import com.wallet.crypto.R 6 | import com.wallet.crypto.ext.click 7 | import com.wallet.crypto.ext.setTextChangeListener 8 | import com.wallet.crypto.ext.toast 9 | import com.wallet.crypto.util.KeyboardUtils 10 | import kotlinx.android.synthetic.main.layout_dialog_create_pwd.* 11 | import kotlinx.android.synthetic.main.layout_dialog_create_pwd.view.* 12 | 13 | /** 14 | * @Description 15 | * @Author sean 16 | * @Email xiao.lu@magicwindow.cn 17 | * @Date 21/06/2018 3:04 PM 18 | * @Version 19 | */ 20 | class InputPwdDialog : BaseDialogFragment() { 21 | 22 | var text = "" 23 | override fun build(initialBuilder: Builder): Builder { 24 | val view = LayoutInflater.from(context).inflate(R.layout.layout_dialog_create_pwd, null) 25 | view.password.setTextChangeListener { 26 | beforeTextChanged { s, start, before, count -> } 27 | onTextChanged { s, start, before, count -> } 28 | afterTextChanged { text = it.toString() } 29 | } 30 | view.btn_cancel.click { dismiss() } 31 | view.btn_ok.click { 32 | if (text.isEmpty()) return@click toast("请输入密码").show() 33 | positiveListeners?.onPositiveButtonClicked(Config.DIALOG_CREATE_PWD_REQUEST_CODE, text) 34 | KeyboardUtils.hideKeyboard(password) 35 | dismiss() 36 | } 37 | view.postDelayed({ KeyboardUtils.showKeyboard(password) }, 500) 38 | return initialBuilder.setView(view) 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/interfaces/DialogListener.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog.interfaces 2 | 3 | /** 4 | * @Author Aaron 5 | * @Email aaron@magicwindow.cn 6 | * @Description 7 | */ 8 | interface DialogListener 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/interfaces/INegativeButtonDialogListener.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog.interfaces 2 | 3 | import com.wallet.crypto.ui.dialog.interfaces.DialogListener 4 | 5 | /** 6 | * Implement this interface in Activity or Fragment to react to negative dialog buttons. 7 | * 8 | * @author Tomáš Kypta 9 | * @since 2.1.0 10 | */ 11 | interface INegativeButtonDialogListener : DialogListener { 12 | 13 | fun onNegativeButtonClicked(requestCode: Int) 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/interfaces/IPositiveButtonDialogListener.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.dialog.interfaces 2 | 3 | import com.wallet.crypto.ui.dialog.interfaces.DialogListener 4 | 5 | /** 6 | * Implement this interface in Activity or Fragment to react to positive dialog buttons. 7 | * 8 | * @author Tomáš Kypta 9 | * @since 2.1.0 10 | */ 11 | interface IPositiveButtonDialogListener : DialogListener { 12 | 13 | fun onPositiveButtonClicked(requestCode: Int, any: Any = "") 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/dialog/interfaces/ISimpleDialogCancelListener.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Inmite s.r.o. (www.inmite.eu). 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wallet.crypto.ui.dialog.interfaces 18 | 19 | import com.wallet.crypto.ui.dialog.interfaces.DialogListener 20 | 21 | /** 22 | * Implement this interface in Activity or Fragment to react when the dialog is cancelled. 23 | * This listener is common for all types of dialogs. 24 | * 25 | * @author Tomáš Kypta 26 | */ 27 | interface ISimpleDialogCancelListener : DialogListener { 28 | 29 | fun onCancelled(requestCode: Int) 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnBackupClickListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | import android.view.View; 4 | 5 | import com.wallet.crypto.entity.Wallet; 6 | 7 | public interface OnBackupClickListener { 8 | void onBackupClick(View view, Wallet wallet); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnDepositClickListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | import android.net.Uri; 4 | import android.view.View; 5 | 6 | public interface OnDepositClickListener { 7 | 8 | void onDepositClick(View view, Uri uri); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnImportKeystoreListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | public interface OnImportKeystoreListener { 4 | void onKeystore(String keystore, String password); 5 | } 6 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnImportPrivateKeyListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | public interface OnImportPrivateKeyListener { 4 | 5 | void onPrivateKey(String privateKey,String pwd); 6 | } 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnTokenClickListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | import android.view.View; 4 | 5 | import com.wallet.crypto.entity.Token; 6 | 7 | public interface OnTokenClickListener { 8 | void onTokenClick(View view, Token token); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/OnTransactionClickListener.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget; 2 | 3 | import android.view.View; 4 | 5 | import com.wallet.crypto.entity.Transaction; 6 | 7 | public interface OnTransactionClickListener { 8 | void onTransactionClick(View view, Transaction transaction); 9 | } 10 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/adapter/TabPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | import android.support.v4.util.Pair; 7 | 8 | import java.util.List; 9 | 10 | public class TabPagerAdapter extends FragmentPagerAdapter { 11 | 12 | private final List> pages; 13 | 14 | public TabPagerAdapter(FragmentManager fm, List> pages) { 15 | super(fm); 16 | 17 | this.pages = pages; 18 | } 19 | 20 | // Return fragment with respect to position. 21 | @Override 22 | public Fragment getItem(int position) { 23 | return pages.get(position).second; 24 | } 25 | 26 | @Override 27 | public int getCount() { 28 | return pages.size(); 29 | } 30 | 31 | // This method returns the title of the tab according to its position. 32 | @Override 33 | public CharSequence getPageTitle(int position) { 34 | return pages.get(position).first; 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/adapter/TokensAdapter.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.adapter; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.ViewGroup; 5 | 6 | import com.wallet.crypto.R; 7 | import com.wallet.crypto.entity.Token; 8 | import com.wallet.crypto.ui.widget.OnTokenClickListener; 9 | import com.wallet.crypto.ui.widget.holder.TokenHolder; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | public class TokensAdapter extends RecyclerView.Adapter { 16 | 17 | private final OnTokenClickListener onTokenClickListener; 18 | private final List items = new ArrayList<>(); 19 | 20 | public TokensAdapter(OnTokenClickListener onTokenClickListener) { 21 | this.onTokenClickListener = onTokenClickListener; 22 | } 23 | 24 | @Override 25 | public TokenHolder onCreateViewHolder(ViewGroup parent, int viewType) { 26 | TokenHolder tokenHolder = new TokenHolder(R.layout.item_token, parent); 27 | tokenHolder.setOnTokenClickListener(onTokenClickListener); 28 | return tokenHolder; 29 | } 30 | 31 | @Override 32 | public void onBindViewHolder(TokenHolder holder, int position) { 33 | holder.bind(items.get(position)); 34 | } 35 | 36 | @Override 37 | public int getItemCount() { 38 | return items.size(); 39 | } 40 | 41 | public void setTokens(Token[] tokens) { 42 | items.clear(); 43 | items.addAll(Arrays.asList(tokens)); 44 | notifyDataSetChanged(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/entity/DateSortedItem.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.entity; 2 | 3 | import android.text.format.DateUtils; 4 | 5 | import com.wallet.crypto.ui.widget.holder.TransactionDateHolder; 6 | 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | import java.util.TimeZone; 10 | 11 | public class DateSortedItem extends TimestampSortedItem { 12 | public DateSortedItem(Date value) { 13 | super(TransactionDateHolder.VIEW_TYPE, value, 0, DESC); 14 | } 15 | 16 | @Override 17 | public Date getTimestamp() { 18 | return value; 19 | } 20 | 21 | @Override 22 | public boolean areContentsTheSame(SortedItem newItem) { 23 | return viewType == newItem.viewType && value.equals(((TimestampSortedItem) newItem).value); 24 | } 25 | 26 | @Override 27 | public boolean areItemsTheSame(SortedItem other) { 28 | return viewType == other.viewType; 29 | } 30 | 31 | public static DateSortedItem round(long timeStampInSec) { 32 | Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 33 | calendar.setTimeInMillis(timeStampInSec * DateUtils.SECOND_IN_MILLIS); 34 | calendar.set(Calendar.MILLISECOND, 999); 35 | calendar.set(Calendar.SECOND, 59); 36 | calendar.set(Calendar.MINUTE, 59); 37 | calendar.set(Calendar.HOUR_OF_DAY, 23); 38 | return new DateSortedItem(calendar.getTime()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/entity/SortedItem.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | public abstract class SortedItem { 7 | protected final List tags = new ArrayList<>(); 8 | 9 | public final int viewType; 10 | public final T value; 11 | public final int weight; 12 | 13 | public SortedItem(int viewType, T value, int weight) { 14 | this.viewType = viewType; 15 | this.value = value; 16 | this.weight = weight; 17 | } 18 | 19 | public abstract int compare(SortedItem other); 20 | 21 | public abstract boolean areContentsTheSame(SortedItem newItem); 22 | 23 | public abstract boolean areItemsTheSame(SortedItem other); 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/entity/TimestampSortedItem.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.entity; 2 | 3 | import java.util.Date; 4 | 5 | public abstract class TimestampSortedItem extends SortedItem { 6 | 7 | public static final int ADC = 1; 8 | public static final int DESC = -1; 9 | 10 | private static final int IS_TIMESTAMP_TAG = 1; 11 | 12 | private final int order; 13 | 14 | 15 | public TimestampSortedItem(int viewType, T value, int weight, int order) { 16 | super(viewType, value, weight); 17 | tags.add(IS_TIMESTAMP_TAG); 18 | this.order = order; 19 | } 20 | 21 | public abstract Date getTimestamp(); 22 | 23 | @Override 24 | public int compare(SortedItem other) { 25 | if (other.tags.contains(IS_TIMESTAMP_TAG)) { 26 | TimestampSortedItem otherTimestamp = (TimestampSortedItem) other; 27 | return order * (getTimestamp().compareTo(otherTimestamp.getTimestamp()));/* 28 | ? 1 : getTimestamp() == otherTimestamp.getTimestamp() ? 0 : -1);*/ 29 | } 30 | return Integer.MIN_VALUE; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/entity/TransactionSortedItem.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.entity; 2 | 3 | import android.text.format.DateUtils; 4 | 5 | import com.wallet.crypto.entity.Transaction; 6 | 7 | import java.util.Calendar; 8 | import java.util.Date; 9 | import java.util.TimeZone; 10 | 11 | public class TransactionSortedItem extends TimestampSortedItem { 12 | 13 | public TransactionSortedItem(int viewType, Transaction value, int order) { 14 | super(viewType, value, 0, order); 15 | } 16 | 17 | @Override 18 | public int compare(SortedItem other) { 19 | return super.compare(other); 20 | // return other.viewType == TransactionHolder.VIEW_TYPE || 21 | // ? super.compare(other) 22 | // : weight - other.weight; 23 | } 24 | 25 | @Override 26 | public boolean areContentsTheSame(SortedItem newItem) { 27 | if (viewType == newItem.viewType) { 28 | Transaction transaction = (Transaction)newItem.value; 29 | return value.hash.equals(transaction.hash) && value.timeStamp == transaction.timeStamp; 30 | } 31 | return false; 32 | } 33 | 34 | @Override 35 | public boolean areItemsTheSame(SortedItem other) { 36 | return viewType == other.viewType; 37 | } 38 | 39 | @Override 40 | public Date getTimestamp() { 41 | Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC")); 42 | calendar.setTimeInMillis(value.timeStamp * DateUtils.SECOND_IN_MILLIS); 43 | return calendar.getTime(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/holder/BinderViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.holder; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | 12 | public abstract class BinderViewHolder extends RecyclerView.ViewHolder { 13 | public BinderViewHolder(int resId, ViewGroup parent) { 14 | super(LayoutInflater.from(parent.getContext()) 15 | .inflate(resId, parent, false)); 16 | } 17 | 18 | public abstract void bind(@Nullable T data, @NonNull Bundle addition); 19 | 20 | public void bind(@Nullable T data) { 21 | bind(data, Bundle.EMPTY); 22 | } 23 | 24 | protected T findViewById(int id) { 25 | return itemView.findViewById(id); 26 | } 27 | 28 | protected Context getContext() { 29 | return itemView.getContext(); 30 | } 31 | 32 | protected String getString(int stringResId) { 33 | return getContext().getString(stringResId); 34 | } 35 | 36 | 37 | public String getString(int stringResId, Object... args) { 38 | return getContext().getString(stringResId, args); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/ui/widget/holder/TransactionDateHolder.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.ui.widget.holder; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.text.format.DateFormat; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import com.wallet.crypto.R; 11 | 12 | import java.util.Calendar; 13 | import java.util.Date; 14 | import java.util.TimeZone; 15 | 16 | public class TransactionDateHolder extends BinderViewHolder { 17 | 18 | // private static final String DATE_TEMPLATE = "MM/dd/yy H:mm:ss zzz"; 19 | 20 | public static final int VIEW_TYPE = 1004; 21 | private final TextView title; 22 | 23 | public TransactionDateHolder(int resId, ViewGroup parent) { 24 | super(resId, parent); 25 | 26 | title = findViewById(R.id.title); 27 | } 28 | 29 | @Override 30 | public void bind(@Nullable Date data, @NonNull Bundle addition) { 31 | if (data == null) { 32 | title.setText(null); 33 | } else { 34 | java.text.DateFormat dateFormat = DateFormat.getMediumDateFormat(getContext()); 35 | dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); 36 | Calendar calendar = Calendar.getInstance(); 37 | calendar.setTimeZone(TimeZone.getTimeZone("UTC")); 38 | calendar.setTime(data); 39 | title.setText(dateFormat.format(calendar.getTime())); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/util/ExchangeCalculator.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.util 2 | 3 | import java.math.BigDecimal 4 | import java.text.DecimalFormat 5 | 6 | /** 7 | * @author Aaron 8 | * @email aaron@magicwindow.cn 9 | * @date 08/03/2018 14:21 10 | * @description 11 | */ 12 | class ExchangeCalculator private constructor() { 13 | private val TAG = "ExchangeCalculator" 14 | 15 | private val lastUpdateTimestamp: Long = 0 16 | var rateForChartDisplay = 1.0 17 | private set 18 | private val formatterUsd = DecimalFormat("#,###,###.##") 19 | private val formatterCrypt = DecimalFormat("#,###,###.####") 20 | private val formatterCryptExact = DecimalFormat("#,###,###.#######") 21 | 22 | 23 | companion object { 24 | 25 | val ONE_ETHER = BigDecimal("1000000000000000000") 26 | 27 | val instance: ExchangeCalculator by lazy { ExchangeCalculator() } 28 | 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/util/KeyboardUtils.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.util; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.view.inputmethod.InputMethodManager; 6 | 7 | public class KeyboardUtils { 8 | 9 | public static void showKeyboard(View view) { 10 | InputMethodManager inputMethodManager 11 | = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 12 | if (inputMethodManager != null) { 13 | inputMethodManager.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT); 14 | } 15 | } 16 | 17 | public static void hideKeyboard(View view) { 18 | InputMethodManager inputMethodManager 19 | = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); 20 | if (inputMethodManager != null) { 21 | inputMethodManager.hideSoftInputFromWindow( 22 | view.getWindowToken(), 0); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/util/RootUtil.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.File; 5 | import java.io.InputStreamReader; 6 | 7 | /** @author Kevin Kowalewski */ 8 | public class RootUtil { 9 | public static boolean isDeviceRooted() { 10 | return checkRootMethod1() || checkRootMethod2() || checkRootMethod3(); 11 | } 12 | 13 | private static boolean checkRootMethod1() { 14 | String buildTags = android.os.Build.TAGS; 15 | return buildTags != null && buildTags.contains("test-keys"); 16 | } 17 | 18 | private static boolean checkRootMethod2() { 19 | String[] paths = { "/system/app/Superuser.apk", "/sbin/su", "/system/bin/su", "/system/xbin/su", "/data/local/xbin/su", "/data/local/bin/su", "/system/sd/xbin/su", 20 | "/system/bin/failsafe/su", "/data/local/su", "/su/bin/su"}; 21 | for (String path : paths) { 22 | if (new File(path).exists()) { 23 | return true; 24 | } 25 | } 26 | return false; 27 | } 28 | 29 | private static boolean checkRootMethod3() { 30 | Process process = null; 31 | try { 32 | process = Runtime.getRuntime().exec(new String[] { "/system/xbin/which", "su" }); 33 | BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream())); 34 | if (in.readLine() != null) return true; 35 | return false; 36 | } catch (Throwable t) { 37 | return false; 38 | } finally { 39 | if (process != null) process.destroy(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/util/SecureRandomUtils.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.util 2 | 3 | import org.web3j.crypto.LinuxSecureRandom 4 | 5 | import java.security.SecureRandom 6 | 7 | /** 8 | * Utility class for working with SecureRandom implementation. 9 | * 10 | * 11 | * 12 | * This is to address issues with SecureRandom on Android. For more information, refer to the 13 | * following [issue](https://github.com/web3j/web3j/issues/146). 14 | */ 15 | internal object SecureRandomUtils { 16 | 17 | private val SECURE_RANDOM: SecureRandom 18 | 19 | // Taken from BitcoinJ implementation 20 | // https://github.com/bitcoinj/bitcoinj/blob/3cb1f6c6c589f84fe6e1fb56bf26d94cccc85429/core/src/main/java/org/bitcoinj/core/Utils.java#L573 21 | private var isAndroid = -1 22 | 23 | val isAndroidRuntime: Boolean 24 | get() { 25 | if (isAndroid == -1) { 26 | val runtime = System.getProperty("java.runtime.name") 27 | isAndroid = if (runtime != null && runtime == "Android Runtime") 1 else 0 28 | } 29 | return isAndroid == 1 30 | } 31 | 32 | init { 33 | if (isAndroidRuntime) { 34 | LinuxSecureRandom() 35 | } 36 | SECURE_RANDOM = SecureRandom() 37 | } 38 | 39 | fun secureRandom(): SecureRandom { 40 | return SECURE_RANDOM 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/AddTokenViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel 2 | 3 | import android.arch.lifecycle.LiveData 4 | import android.arch.lifecycle.MutableLiveData 5 | import android.content.Context 6 | 7 | import com.wallet.crypto.interact.AddTokenInteract 8 | import com.wallet.crypto.interact.FindDefaultWalletInteract 9 | import com.wallet.crypto.router.MyTokensRouter 10 | import io.reactivex.functions.Action 11 | import io.reactivex.functions.Consumer 12 | 13 | class AddTokenViewModel internal constructor( 14 | private val addTokenInteract: AddTokenInteract, 15 | private val findDefaultWalletInteract: FindDefaultWalletInteract, 16 | private val myTokensRouter: MyTokensRouter) : BaseViewModel() { 17 | 18 | private val result = MutableLiveData() 19 | 20 | fun save(address: String, symbol: String, decimals: Int) { 21 | addTokenInteract 22 | .add(address, symbol, decimals) 23 | .subscribe({ this.onSaved() }, { this.onError(it) }) 24 | } 25 | 26 | private fun onSaved() { 27 | progress.postValue(false) 28 | result.postValue(true) 29 | } 30 | 31 | fun result(): LiveData { 32 | return result 33 | } 34 | 35 | fun showTokens(context: Context) { 36 | findDefaultWalletInteract 37 | .find() 38 | .subscribe { w -> myTokensRouter.open(context, w) } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/AddTokenViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.wallet.crypto.interact.AddTokenInteract; 8 | import com.wallet.crypto.interact.FindDefaultWalletInteract; 9 | import com.wallet.crypto.router.MyTokensRouter; 10 | 11 | public class AddTokenViewModelFactory implements ViewModelProvider.Factory { 12 | 13 | private final AddTokenInteract addTokenInteract; 14 | private final FindDefaultWalletInteract findDefaultWalletInteract; 15 | private final MyTokensRouter myTokensRouter; 16 | 17 | public AddTokenViewModelFactory( 18 | AddTokenInteract addTokenInteract, 19 | FindDefaultWalletInteract findDefaultWalletInteract, 20 | MyTokensRouter myTokensRouter) { 21 | this.addTokenInteract = addTokenInteract; 22 | this.findDefaultWalletInteract = findDefaultWalletInteract; 23 | this.myTokensRouter = myTokensRouter; 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public T create(@NonNull Class modelClass) { 29 | return (T) new AddTokenViewModel(addTokenInteract, findDefaultWalletInteract, myTokensRouter); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/BaseNavigationActivity.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.support.annotation.MenuRes; 4 | import android.support.annotation.NonNull; 5 | import android.support.design.widget.BottomNavigationView; 6 | import android.view.MenuItem; 7 | 8 | import com.wallet.crypto.R; 9 | import com.wallet.crypto.ui.BaseActivity; 10 | 11 | public class BaseNavigationActivity extends BaseActivity implements BottomNavigationView.OnNavigationItemSelectedListener { 12 | 13 | private BottomNavigationView navigation; 14 | 15 | protected void initBottomNavigation() { 16 | navigation = findViewById(R.id.bottom_navigation); 17 | navigation.setOnNavigationItemSelectedListener(this); 18 | } 19 | 20 | protected void setBottomMenu(@MenuRes int menuRes) { 21 | navigation.getMenu().clear(); 22 | navigation.inflateMenu(menuRes); 23 | } 24 | 25 | @Override 26 | public boolean onNavigationItemSelected(@NonNull MenuItem item) { 27 | return false; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/BaseViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel 2 | 3 | import android.arch.lifecycle.LiveData 4 | import android.arch.lifecycle.MutableLiveData 5 | import android.arch.lifecycle.ViewModel 6 | import android.util.Log 7 | 8 | import com.wallet.crypto.MercuryConstants 9 | import com.wallet.crypto.entity.ErrorEnvelope 10 | import com.wallet.crypto.entity.ServiceException 11 | 12 | import io.reactivex.disposables.Disposable 13 | 14 | open class BaseViewModel : ViewModel() { 15 | 16 | protected val error = MutableLiveData() 17 | protected val progress = MutableLiveData() 18 | protected var disposable: Disposable? = null 19 | 20 | override fun onCleared() { 21 | cancel() 22 | } 23 | 24 | protected fun cancel() { 25 | if (disposable != null && !disposable!!.isDisposed) { 26 | disposable!!.dispose() 27 | } 28 | } 29 | 30 | 31 | fun error(): LiveData { 32 | return error 33 | } 34 | 35 | fun progress(): LiveData { 36 | return progress 37 | } 38 | 39 | protected fun onError(throwable: Throwable) { 40 | if (throwable is ServiceException) { 41 | error.postValue(throwable.error) 42 | } else { 43 | error.postValue(ErrorEnvelope(MercuryConstants.ErrorCode.UNKNOWN, null, throwable)) 44 | // TODO: Add dialog with offer send error log to developers: notify about error. 45 | Log.d("SESSION", "Err", throwable) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/ChangePasswordViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel 2 | 3 | import com.wallet.crypto.entity.Wallet 4 | import com.wallet.crypto.ext.toast 5 | import com.wallet.crypto.repository.SharedPreferenceRepository 6 | import com.wallet.crypto.util.WalletStorage 7 | import io.reactivex.Completable 8 | import io.reactivex.android.schedulers.AndroidSchedulers 9 | import io.reactivex.schedulers.Schedulers 10 | 11 | /** 12 | * @Description 13 | * @Author sean 14 | * @Email xiao.lu@magicwindow.cn 15 | * @Date 25/06/2018 2:37 PM 16 | * @Version 17 | */ 18 | class ChangePasswordViewModel : BaseViewModel() { 19 | 20 | var newPwd: String? = null 21 | var oldPwd: String? = null 22 | 23 | fun change(sp: SharedPreferenceRepository?, block: () -> Unit) { 24 | if (oldPwd.isNullOrEmpty()) { 25 | toast("请输入原始密码").show() 26 | return 27 | } 28 | if (newPwd.isNullOrEmpty()) { 29 | toast("请输入新密码").show() 30 | return 31 | } 32 | progress.postValue(true) 33 | Completable.fromCallable { 34 | val account = WalletStorage.getInstance().modifyPassword(sp!!.currentWalletAddress, oldPwd!!, newPwd!!) 35 | Wallet(account.address.toLowerCase()) 36 | }.subscribeOn(Schedulers.io()) 37 | .observeOn(AndroidSchedulers.mainThread()) 38 | .subscribe({ 39 | toast("修改成功").show() 40 | progress.value = false 41 | block() 42 | }, this::onError) 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/CreateAccountViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | public class CreateAccountViewModel extends BaseViewModel { 4 | 5 | public CreateAccountViewModel() { 6 | 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/CreateAccountViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | 4 | import android.arch.lifecycle.ViewModel; 5 | import android.arch.lifecycle.ViewModelProvider; 6 | import android.support.annotation.NonNull; 7 | 8 | public class CreateAccountViewModelFactory implements ViewModelProvider.Factory { 9 | 10 | public CreateAccountViewModelFactory() { } 11 | 12 | @NonNull 13 | @Override 14 | public T create(@NonNull Class modelClass) { 15 | return (T) new CreateAccountViewModel(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/GasSettingsViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | 4 | import android.arch.lifecycle.ViewModel; 5 | import android.arch.lifecycle.ViewModelProvider; 6 | import android.support.annotation.NonNull; 7 | 8 | import com.wallet.crypto.interact.FindDefaultNetworkInteract; 9 | 10 | public class GasSettingsViewModelFactory implements ViewModelProvider.Factory { 11 | 12 | FindDefaultNetworkInteract findDefaultNetworkInteract; 13 | 14 | public GasSettingsViewModelFactory(FindDefaultNetworkInteract findDefaultNetworkInteract) { 15 | this.findDefaultNetworkInteract = findDefaultNetworkInteract; 16 | } 17 | 18 | @NonNull 19 | @Override 20 | public T create(@NonNull Class modelClass) { 21 | return (T) new GasSettingsViewModel(findDefaultNetworkInteract); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/ImportWalletViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.lifecycle.MutableLiveData; 5 | 6 | import com.wallet.crypto.entity.Wallet; 7 | import com.wallet.crypto.interact.ImportWalletInteract; 8 | import com.wallet.crypto.ui.widget.OnImportKeystoreListener; 9 | import com.wallet.crypto.ui.widget.OnImportPrivateKeyListener; 10 | 11 | public class ImportWalletViewModel extends BaseViewModel implements OnImportKeystoreListener, OnImportPrivateKeyListener { 12 | 13 | private final ImportWalletInteract importWalletInteract; 14 | private final MutableLiveData wallet = new MutableLiveData<>(); 15 | 16 | ImportWalletViewModel(ImportWalletInteract importWalletInteract) { 17 | this.importWalletInteract = importWalletInteract; 18 | } 19 | 20 | @Override 21 | public void onKeystore(String keystore, String password) { 22 | getProgress().postValue(true); 23 | importWalletInteract 24 | .importKeystore(keystore, password) 25 | .subscribe(this::onWallet, this::onError); 26 | } 27 | 28 | @Override 29 | public void onPrivateKey(String privateKey,String pwd) { 30 | getProgress().postValue(true); 31 | importWalletInteract 32 | .importPrivateKey(privateKey,pwd) 33 | .subscribe(this::onWallet, this::onError); 34 | } 35 | 36 | public LiveData wallet() { 37 | return wallet; 38 | } 39 | 40 | private void onWallet(Wallet wallet) { 41 | getProgress().postValue(false); 42 | this.wallet.postValue(wallet); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/ImportWalletViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.wallet.crypto.interact.ImportWalletInteract; 8 | 9 | public class ImportWalletViewModelFactory implements ViewModelProvider.Factory { 10 | 11 | private final ImportWalletInteract importWalletInteract; 12 | 13 | public ImportWalletViewModelFactory(ImportWalletInteract importWalletInteract) { 14 | this.importWalletInteract = importWalletInteract; 15 | } 16 | 17 | @NonNull 18 | @Override 19 | public T create(@NonNull Class modelClass) { 20 | return (T) new ImportWalletViewModel(importWalletInteract); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/SendViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.MutableLiveData; 4 | import android.content.Context; 5 | 6 | import com.wallet.crypto.entity.Transaction; 7 | import com.wallet.crypto.entity.Wallet; 8 | import com.wallet.crypto.router.ConfirmationRouter; 9 | 10 | import java.math.BigInteger; 11 | 12 | public class SendViewModel extends BaseViewModel { 13 | private final MutableLiveData defaultWallet = new MutableLiveData<>(); 14 | private final MutableLiveData transaction = new MutableLiveData<>(); 15 | private final ConfirmationRouter confirmationRouter; 16 | 17 | SendViewModel(ConfirmationRouter confirmationRouter) { 18 | this.confirmationRouter = confirmationRouter; 19 | } 20 | 21 | public void openConfirmation(Context context, String to, BigInteger amount, String contractAddress, int decimals, String symbol, boolean sendingTokens) { 22 | confirmationRouter.open(context, to, amount, contractAddress, decimals, symbol, sendingTokens); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/SendViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | 6 | import com.wallet.crypto.router.ConfirmationRouter; 7 | 8 | import io.reactivex.annotations.NonNull; 9 | 10 | public class SendViewModelFactory implements ViewModelProvider.Factory { 11 | 12 | private final ConfirmationRouter confirmationRouter; 13 | 14 | public SendViewModelFactory(ConfirmationRouter confirmationRouter) { 15 | this.confirmationRouter = confirmationRouter; 16 | } 17 | 18 | @NonNull 19 | @Override 20 | public T create(@NonNull Class modelClass) { 21 | return (T) new SendViewModel(confirmationRouter); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/SplashViewModel.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.LiveData; 4 | import android.arch.lifecycle.MutableLiveData; 5 | import android.arch.lifecycle.ViewModel; 6 | 7 | import com.wallet.crypto.entity.Wallet; 8 | import com.wallet.crypto.interact.FetchWalletsInteract; 9 | 10 | public class SplashViewModel extends ViewModel { 11 | private final FetchWalletsInteract fetchWalletsInteract; 12 | private MutableLiveData wallets = new MutableLiveData<>(); 13 | 14 | SplashViewModel(FetchWalletsInteract fetchWalletsInteract) { 15 | this.fetchWalletsInteract = fetchWalletsInteract; 16 | 17 | fetchWalletsInteract 18 | .fetch() 19 | .subscribe(wallets::postValue, this::onError); 20 | } 21 | 22 | private void onError(Throwable throwable) { 23 | wallets.postValue(new Wallet[0]); 24 | } 25 | 26 | public LiveData wallets() { 27 | return wallets; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/SplashViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.wallet.crypto.interact.FetchWalletsInteract; 8 | 9 | public class SplashViewModelFactory implements ViewModelProvider.Factory { 10 | 11 | private final FetchWalletsInteract fetchWalletsInteract; 12 | 13 | public SplashViewModelFactory(FetchWalletsInteract fetchWalletsInteract) { 14 | this.fetchWalletsInteract = fetchWalletsInteract; 15 | } 16 | @NonNull 17 | @Override 18 | public T create(@NonNull Class modelClass) { 19 | return (T) new SplashViewModel(fetchWalletsInteract); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/viewmodel/TransactionDetailViewModelFactory.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.viewmodel; 2 | 3 | import android.arch.lifecycle.ViewModel; 4 | import android.arch.lifecycle.ViewModelProvider; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.wallet.crypto.interact.FindDefaultNetworkInteract; 8 | import com.wallet.crypto.interact.FindDefaultWalletInteract; 9 | import com.wallet.crypto.router.ExternalBrowserRouter; 10 | 11 | public class TransactionDetailViewModelFactory implements ViewModelProvider.Factory { 12 | 13 | private final FindDefaultNetworkInteract findDefaultNetworkInteract; 14 | private final FindDefaultWalletInteract findDefaultWalletInteract; 15 | private final ExternalBrowserRouter externalBrowserRouter; 16 | 17 | public TransactionDetailViewModelFactory( 18 | FindDefaultNetworkInteract findDefaultNetworkInteract, 19 | FindDefaultWalletInteract findDefaultWalletInteract, 20 | ExternalBrowserRouter externalBrowserRouter) { 21 | this.findDefaultNetworkInteract = findDefaultNetworkInteract; 22 | this.findDefaultWalletInteract = findDefaultWalletInteract; 23 | this.externalBrowserRouter = externalBrowserRouter; 24 | } 25 | 26 | @NonNull 27 | @Override 28 | public T create(@NonNull Class modelClass) { 29 | return (T) new TransactionDetailViewModel( 30 | findDefaultNetworkInteract, 31 | findDefaultWalletInteract, 32 | externalBrowserRouter); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/wallet/crypto/widget/EmptyTransactionsView.java: -------------------------------------------------------------------------------- 1 | package com.wallet.crypto.widget; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.view.LayoutInflater; 6 | import android.widget.FrameLayout; 7 | 8 | import com.wallet.crypto.R; 9 | import com.wallet.crypto.entity.NetworkInfo; 10 | 11 | public class EmptyTransactionsView extends FrameLayout { 12 | 13 | public EmptyTransactionsView(@NonNull Context context, OnClickListener onClickListener) { 14 | super(context); 15 | 16 | LayoutInflater.from(getContext()) 17 | .inflate(R.layout.layout_empty_transactions, this, true); 18 | 19 | findViewById(R.id.action_buy).setOnClickListener(onClickListener); 20 | } 21 | 22 | public void setNetworkInfo(NetworkInfo networkInfo) { 23 | if (networkInfo.isMainNetwork) { 24 | findViewById(R.id.action_buy).setVisibility(VISIBLE); 25 | } else { 26 | findViewById(R.id.action_buy).setVisibility(GONE); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/anim/in_from_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/in_from_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/out_to_left.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/out_to_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/anim/push_bottom_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_center_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_center_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/anim/scale_tran_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 18 | 19 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_action_deposit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-hdpi/ic_action_deposit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-hdpi/ic_facebook.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/settings_rpc_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-hdpi/settings_rpc_server.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/token_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-hdpi/token_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_action_deposit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-mdpi/ic_action_deposit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-mdpi/ic_facebook.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_share_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/settings_rpc_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-mdpi/settings_rpc_server.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/token_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-mdpi/token_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/no_transactions_mascot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-nodpi/no_transactions_mascot.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/onboarding_erc20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-nodpi/onboarding_erc20.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-nodpi/settings_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-nodpi/settings_facebook.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-v21/bg_ripple_primary_color.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_action_deposit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xhdpi/ic_action_deposit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xhdpi/ic_facebook.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/settings_rpc_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xhdpi/settings_rpc_server.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/token_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xhdpi/token_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_action_deposit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xxhdpi/ic_action_deposit.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xxhdpi/ic_facebook.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/settings_rpc_server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xxhdpi/settings_rpc_server.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/token_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/drawable-xxhdpi/token_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_ripple_primary_color.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_circle_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_add_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_downward_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_arrow_upward_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_attach_money_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_autorenew_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_backup_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_call_received_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_chevron_right_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_code_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_content_paste_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_dashboard_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_delete_forever_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_error_outline_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_file_download_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_home_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_import_export_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_net.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_notifications_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pwd.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_qq.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_send_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_settings_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_share_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_source.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_swap_horiz_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_toast_error.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_wallet.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 12 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_warning_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/selector_btn_text_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_btn_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_dialog_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_tips_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shape_toast_bg.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/splash_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_bolt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/font/roboto_bolt.ttf -------------------------------------------------------------------------------- /app/src/main/res/font/roboto_regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/snailflying/ETHWallet/e4efffa05b3d5021af02cd6c9516d111d254057c/app/src/main/res/font/roboto_regular.ttf -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_import_wallet.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_qrscan.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_splash.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_tokens.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 23 | 24 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_wallets.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 18 | 23 | 24 | 31 | 38 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_transactions_date_head.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 23 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_app_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_app_bar_with_tab.xml: -------------------------------------------------------------------------------- 1 | 9 | 17 | 26 | 27 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_barcode_capture.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog_backup.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog_password.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 17 | 18 | 26 | 31 | 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_empty_transactions.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 14 | 22 |