From c0f91efb415b15fd3aed114c95e95b1ec3e32889 Mon Sep 17 00:00:00 2001 From: JunZhang Date: Fri, 12 Jun 2020 15:55:41 +0800 Subject: [PATCH] support generic watch-only wallet (#34) --- app/build.gradle | 2 +- .../cold/ui/fragment/main/AssetFragment.java | 5 +- .../main/ExportGenericXpubFragment.java | 16 +- ...ment.java => PsbtBroadcastTxFragment.java} | 27 +++- .../fragment/main/PsbtSignedTxFragment.java | 32 +++- .../fragment/main/PsbtTxConfirmFragment.java | 7 +- .../cold/ui/fragment/main/TxListFragment.java | 3 +- .../cobo/cold/viewmodel/QrScanViewModel.java | 7 +- .../com/cobo/cold/viewmodel/WatchWallet.java | 30 ++++ ...ent.xml => broadcast_psbt_tx_fragment.xml} | 16 +- .../main/res/layout/electrum_tx_detail.xml | 4 +- .../main/res/layout/export_xpub_generic.xml | 145 ++++++++++++++++++ .../main/res/navigation/nav_graph_main.xml | 18 ++- app/src/main/res/values-zh-rCN/strings.xml | 3 +- app/src/main/res/values/strings.xml | 5 +- 15 files changed, 280 insertions(+), 40 deletions(-) rename app/src/main/java/com/cobo/cold/ui/fragment/main/{BlueWalletBroadcastTxFragment.java => PsbtBroadcastTxFragment.java} (64%) rename app/src/main/res/layout/{broadcast_blue_tx_fragment.xml => broadcast_psbt_tx_fragment.xml} (83%) create mode 100644 app/src/main/res/layout/export_xpub_generic.xml diff --git a/app/build.gradle b/app/build.gradle index 33e76b7..b5be597 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -170,7 +170,7 @@ dependencies { implementation 'net.lingala.zip4j:zip4j:1.3.2@jar' implementation 'com.wei.android.lib:fingerprintidentify:1.2.6' implementation 'com.github.donkingliang:ConsecutiveScroller:2.5.0' - implementation 'com.github.CoboVault:bc32-java:v0.05-alpha' + implementation 'com.github.CoboVault:bc32-java:v0.0.6-alpha' annotationProcessor 'androidx.room:room-compiler:2.1.0' implementation project(':encryption-core') diff --git a/app/src/main/java/com/cobo/cold/ui/fragment/main/AssetFragment.java b/app/src/main/java/com/cobo/cold/ui/fragment/main/AssetFragment.java index 26411b9..2c8e6bc 100644 --- a/app/src/main/java/com/cobo/cold/ui/fragment/main/AssetFragment.java +++ b/app/src/main/java/com/cobo/cold/ui/fragment/main/AssetFragment.java @@ -115,8 +115,7 @@ public class AssetFragment extends BaseFragment @Override public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { inflater.inflate(R.menu.asset_hasmore, menu); - if (watchWallet == WatchWallet.COBO - || watchWallet == WatchWallet.BLUE) { + if (!watchWallet.supportSdcard()) { menu.findItem(R.id.action_sdcard).setVisible(false); } super.onCreateOptionsMenu(menu, inflater); @@ -193,10 +192,10 @@ public class AssetFragment extends BaseFragment private void showFileList() { switch (watchWallet) { case ELECTRUM: - case GENERIC: navigate(R.id.action_to_txnListFragment); break; case WASABI: + case GENERIC: navigate(R.id.action_to_psbtListFragment); break; } diff --git a/app/src/main/java/com/cobo/cold/ui/fragment/main/ExportGenericXpubFragment.java b/app/src/main/java/com/cobo/cold/ui/fragment/main/ExportGenericXpubFragment.java index b0c98a9..6bad5c3 100644 --- a/app/src/main/java/com/cobo/cold/ui/fragment/main/ExportGenericXpubFragment.java +++ b/app/src/main/java/com/cobo/cold/ui/fragment/main/ExportGenericXpubFragment.java @@ -27,8 +27,7 @@ import com.cobo.coinlib.Util; import com.cobo.coinlib.utils.Coins; import com.cobo.cold.R; import com.cobo.cold.databinding.ExportSdcardModalBinding; -import com.cobo.cold.databinding.ExportXpubBinding; -import com.cobo.cold.ui.MainActivity; +import com.cobo.cold.databinding.ExportXpubGenericBinding; import com.cobo.cold.ui.SetupVaultActivity; import com.cobo.cold.ui.fragment.BaseFragment; import com.cobo.cold.ui.modal.ModalDialog; @@ -44,13 +43,13 @@ import static com.cobo.cold.viewmodel.GlobalViewModel.showNoSdcardModal; import static com.cobo.cold.viewmodel.GlobalViewModel.writeToSdcard; -public class ExportGenericXpubFragment extends BaseFragment { +public class ExportGenericXpubFragment extends BaseFragment { private JSONObject xpubInfo; @Override protected int setView() { - return R.layout.export_xpub; + return R.layout.export_xpub_generic; } @Override @@ -62,20 +61,19 @@ public class ExportGenericXpubFragment extends BaseFragment { exPub = convertExtpub(exPub, getAccount(mActivity)); xpubInfo.put("ExtPubKey", exPub); mBinding.qrcode.setData(xpubInfo.toString()); - mBinding.expub.setText(exPub); + } catch (JSONException e) { e.printStackTrace(); } - mBinding.addressType.setText(getString(R.string.master_xpub, - GlobalViewModel.getAddressFormat(mActivity))); + mBinding.done.setOnClickListener(v -> { if (mActivity instanceof SetupVaultActivity) { navigate(R.id.action_to_setupCompleteFragment); } else { - MainActivity activity = (MainActivity) mActivity; - activity.getNavController().popBackStack(R.id.assetFragment, false); + popBackStack(R.id.assetFragment, false); } }); + mBinding.skip.setOnClickListener(v -> popBackStack(R.id.assetFragment,false)); mBinding.exportToSdcard.setOnClickListener(v -> { Storage storage = Storage.createByEnvironment(mActivity); if (storage == null || storage.getExternalDir() == null) { diff --git a/app/src/main/java/com/cobo/cold/ui/fragment/main/BlueWalletBroadcastTxFragment.java b/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtBroadcastTxFragment.java similarity index 64% rename from app/src/main/java/com/cobo/cold/ui/fragment/main/BlueWalletBroadcastTxFragment.java rename to app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtBroadcastTxFragment.java index c4a989e..f47d8de 100644 --- a/app/src/main/java/com/cobo/cold/ui/fragment/main/BlueWalletBroadcastTxFragment.java +++ b/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtBroadcastTxFragment.java @@ -23,24 +23,29 @@ import android.view.View; import androidx.lifecycle.ViewModelProviders; import com.cobo.cold.R; -import com.cobo.cold.databinding.BroadcastBlueTxFragmentBinding; +import com.cobo.cold.databinding.BroadcastPsbtTxFragmentBinding; +import com.cobo.cold.db.entity.TxEntity; import com.cobo.cold.ui.fragment.BaseFragment; import com.cobo.cold.ui.views.qrcode.DynamicQrCodeView; import com.cobo.cold.viewmodel.CoinListViewModel; +import com.cobo.cold.viewmodel.WatchWallet; import org.spongycastle.util.encoders.Base64; import org.spongycastle.util.encoders.Hex; import java.util.Objects; -public class BlueWalletBroadcastTxFragment extends BaseFragment { +import static com.cobo.cold.ui.fragment.main.PsbtTxConfirmFragment.showExportPsbtDialog; + +public class PsbtBroadcastTxFragment extends BaseFragment { public static final String KEY_TXID = "txId"; private View.OnClickListener goHome = v -> popBackStack(R.id.assetFragment,false); + private TxEntity txEntity; @Override protected int setView() { - return R.layout.broadcast_blue_tx_fragment; + return R.layout.broadcast_psbt_tx_fragment; } @Override @@ -50,10 +55,25 @@ public class BlueWalletBroadcastTxFragment extends BaseFragment { + this.txEntity = txEntity; mBinding.setCoinCode(txEntity.getCoinCode()); mBinding.qrcodeLayout.qrcode.setEncodingScheme(DynamicQrCodeView.EncodingScheme.Bc32); mBinding.qrcodeLayout.qrcode.setData(Hex.toHexString(Base64.decode(txEntity.getSignedHex()))); }); + + WatchWallet wallet = WatchWallet.getWatchWallet(mActivity); + + if (wallet.supportSdcard()) { + mBinding.qrcodeLayout.hint.setVisibility(View.GONE); + mBinding.exportToSdcard.setVisibility(View.VISIBLE); + mBinding.exportToSdcard.setOnClickListener(v -> + showExportPsbtDialog(mActivity, txEntity.getTxId(), + txEntity.getSignedHex(), null)); + } else { + mBinding.exportToSdcard.setVisibility(View.GONE); + } + mBinding.scanHint.setText(getString(R.string.use_wallet_to_broadcast, + WatchWallet.getWatchWallet(mActivity).getWalletName(mActivity))); } @@ -61,4 +81,5 @@ public class BlueWalletBroadcastTxFragment extends BaseFragment showBlueWalletInfo()); - mBinding.txDetail.scanHint.setText(R.string.use_blue_to_broadcast); + } else if (watchWallet == WatchWallet.BLUE || watchWallet == WatchWallet.GENERIC) { + if (watchWallet == WatchWallet.BLUE) { + mBinding.txDetail.info.setOnClickListener(v -> showBlueWalletInfo()); + } + mBinding.txDetail.scanHint.setText(mActivity.getString(R.string.use_wallet_to_broadcast, + watchWallet.getWalletName(mActivity))); + if (watchWallet.supportBc32QrCode()) { + mBinding.txDetail.dynamicQrcodeLayout.qrcode + .setEncodingScheme(DynamicQrCodeView.EncodingScheme.Bc32); + mBinding.txDetail.dynamicQrcodeLayout.qrcode + .setData(Hex.toHexString(Base64.decode(txEntity.getSignedHex()))); + } + mBinding.txDetail.exportToSdcardHint.setVisibility(View.GONE); mBinding.txDetail.qrcodeLayout.qrcode.setVisibility(View.GONE); mBinding.txDetail.dynamicQrcodeLayout.qrcode.setVisibility(View.VISIBLE); mBinding.txDetail.broadcastGuide.setVisibility(View.GONE); - mBinding.txDetail.export.setVisibility(View.GONE); - mBinding.txDetail.dynamicQrcodeLayout.qrcode.setEncodingScheme(DynamicQrCodeView.EncodingScheme.Bc32); - mBinding.txDetail.dynamicQrcodeLayout.qrcode.setData(Hex.toHexString(Base64.decode(txEntity.getSignedHex()))); + if (!watchWallet.supportSdcard()) { + mBinding.txDetail.export.setVisibility(View.GONE); + } + if (watchWallet == WatchWallet.GENERIC) { + mBinding.txDetail.dynamicQrcodeLayout.hint.setVisibility(View.GONE); + mBinding.txDetail.info.setVisibility(View.INVISIBLE); + mBinding.txDetail.exportToSdcardHint.setVisibility(View.VISIBLE); + mBinding.txDetail.exportToSdcardHint.setText(R.string.generic_qrcode_hint); + mBinding.txDetail.exportToSdcardHint.setOnClickListener(v -> showExportDialog()); + mBinding.txDetail.export.setVisibility(View.GONE); + + } + } } diff --git a/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtTxConfirmFragment.java b/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtTxConfirmFragment.java index 56eea94..0cf8aa1 100644 --- a/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtTxConfirmFragment.java +++ b/app/src/main/java/com/cobo/cold/ui/fragment/main/PsbtTxConfirmFragment.java @@ -36,7 +36,7 @@ import com.cobo.cold.viewmodel.WatchWallet; import java.io.File; import java.util.Objects; -import static com.cobo.cold.ui.fragment.main.BlueWalletBroadcastTxFragment.KEY_TXID; +import static com.cobo.cold.ui.fragment.main.PsbtBroadcastTxFragment.KEY_TXID; import static com.cobo.cold.viewmodel.GlobalViewModel.exportSuccess; import static com.cobo.cold.viewmodel.GlobalViewModel.hasSdcard; import static com.cobo.cold.viewmodel.GlobalViewModel.showNoSdcardModal; @@ -92,10 +92,11 @@ public class PsbtTxConfirmFragment extends UnsignedTxFragment { } protected void onSignSuccess() { - if (WatchWallet.getWatchWallet(mActivity) == WatchWallet.BLUE) { + WatchWallet wallet = WatchWallet.getWatchWallet(mActivity); + if (wallet == WatchWallet.BLUE || wallet == WatchWallet.GENERIC) { Bundle data = new Bundle(); data.putString(KEY_TXID,viewModel.getTxId()); - navigate(R.id.action_to_blue_wallet_broadcast, data); + navigate(R.id.action_to_psbt_broadcast, data); } else { showExportPsbtDialog(mActivity, viewModel.getTxId(), viewModel.getTxHex(), this::navigateUp); diff --git a/app/src/main/java/com/cobo/cold/ui/fragment/main/TxListFragment.java b/app/src/main/java/com/cobo/cold/ui/fragment/main/TxListFragment.java index 7781958..5a020c8 100644 --- a/app/src/main/java/com/cobo/cold/ui/fragment/main/TxListFragment.java +++ b/app/src/main/java/com/cobo/cold/ui/fragment/main/TxListFragment.java @@ -70,7 +70,8 @@ public class TxListFragment extends BaseFragment { Bundle bundle = new Bundle(); bundle.putString(KEY_TX_ID, tx.getTxId()); if (WASABI_SIGN_ID.equals(tx.getSignId()) - || BLUE_WALLET_SIGN_ID.equals(tx.getSignId())) { + || BLUE_WALLET_SIGN_ID.equals(tx.getSignId()) + || GENERIC_WALLET_SIGN_ID.equals(tx.getSignId())) { navigate(R.id.action_to_psbtSignedTxFragment, bundle); } else if(ELECTRUM_SIGN_ID.equals(tx.getSignId())){ navigate(R.id.action_to_electrumTxFragment, bundle); diff --git a/app/src/main/java/com/cobo/cold/viewmodel/QrScanViewModel.java b/app/src/main/java/com/cobo/cold/viewmodel/QrScanViewModel.java index ed0776a..841cbcf 100644 --- a/app/src/main/java/com/cobo/cold/viewmodel/QrScanViewModel.java +++ b/app/src/main/java/com/cobo/cold/viewmodel/QrScanViewModel.java @@ -88,7 +88,12 @@ public class QrScanViewModel extends AndroidViewModel { e.printStackTrace(); } if (!TextUtils.isEmpty(hex)) { - handleBc32Qrcode(hex); + WatchWallet wallet = WatchWallet.getWatchWallet(getApplication()); + if (wallet.supportBc32QrCode()) { + handleBc32Qrcode(hex); + } else { + throw new UnknowQrCodeException("not support bc32 qrcode in current wallet mode"); + } } } else { diff --git a/app/src/main/java/com/cobo/cold/viewmodel/WatchWallet.java b/app/src/main/java/com/cobo/cold/viewmodel/WatchWallet.java index 48351ab..f498b24 100644 --- a/app/src/main/java/com/cobo/cold/viewmodel/WatchWallet.java +++ b/app/src/main/java/com/cobo/cold/viewmodel/WatchWallet.java @@ -67,4 +67,34 @@ public enum WatchWallet { default:return false; } } + + public boolean supportBc32QrCode() { + switch (this) { + case GENERIC: + case BLUE: + return true; + default:return false; + } + } + + public boolean supportQrCode() { + switch (this) { + case ELECTRUM: + case COBO: + case GENERIC: + case BLUE: + return true; + default:return false; + } + } + + public boolean supportSdcard() { + switch (this) { + case ELECTRUM: + case GENERIC: + case WASABI: + return true; + default:return false; + } + } } \ No newline at end of file diff --git a/app/src/main/res/layout/broadcast_blue_tx_fragment.xml b/app/src/main/res/layout/broadcast_psbt_tx_fragment.xml similarity index 83% rename from app/src/main/res/layout/broadcast_blue_tx_fragment.xml rename to app/src/main/res/layout/broadcast_psbt_tx_fragment.xml index 9b3802b..474220a 100644 --- a/app/src/main/res/layout/broadcast_blue_tx_fragment.xml +++ b/app/src/main/res/layout/broadcast_psbt_tx_fragment.xml @@ -79,11 +79,12 @@ android:paddingHorizontal="16dp"> @@ -94,6 +95,19 @@ android:id="@+id/qrcode_layout" layout="@layout/dynamic_qrcode" /> + +