diff --git a/app/build.gradle b/app/build.gradle
index 83a31948..8897dd60 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -133,7 +133,8 @@ dependencies {
//Jadeticon
implementation 'com.github.WycliffeAssociates:jdenticon-kotlin:-SNAPSHOT'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
-
+ //eNotes
+ implementation 'io.enotes.sdk:eNotes:1.0.0'
implementation project(':MPChartLib')
if (isModule == "true") {
implementation project(':module-eto')
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 319f1ac9..3f957a1a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,11 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.cybexmobile">
+
+
+
@@ -57,6 +62,13 @@
+
+
+
+
+
reply) {
public void run() {
hideLoadDialog();
if (result == 0) {
+ setLoginFrom(false);
Intent returnIntent = new Intent();
returnIntent.putExtra(INTENT_PARAM_LOGIN_IN, true);
returnIntent.putExtra(INTENT_PARAM_NAME, email);
@@ -285,6 +309,49 @@ public void onFailure() {
}
}
+ private void loginByENotes() {
+ // Store values at the time of the login attempt.
+ String email = mUserNameView.getText().toString().trim();
+ String password = mPasswordView.getText().toString().trim();
+ if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password)) {
+ return;
+ }
+ showLoadDialog(true);
+ try {
+ BitsharesWalletWraper.getInstance().get_account_object(email, new MessageCallback>() {
+ @Override
+ public void onMessage(Reply reply) {
+ AccountObject accountObject = reply.result;
+ int result = BitsharesWalletWraper.getInstance().import_account_password(accountObject, email, password);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ hideLoadDialog();
+ setLoginFrom(true);
+ Intent returnIntent = new Intent();
+ returnIntent.putExtra(INTENT_PARAM_LOGIN_IN, true);
+ returnIntent.putExtra(INTENT_PARAM_NAME, email);
+ setResult(Activity.RESULT_OK, returnIntent);
+ EventBus.getDefault().post(new Event.LoginIn(email));
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ sharedPreferences.edit().putBoolean(PREF_IS_LOGIN_IN, true).apply();
+ sharedPreferences.edit().putString(PREF_NAME, email).apply();
+ finish();
+ }
+ });
+
+ }
+
+ @Override
+ public void onFailure() {
+ hideLoadDialog();
+ }
+ });
+ } catch (NetworkStatusException e) {
+ e.printStackTrace();
+ }
+ }
+
@Override
public Loader onCreateLoader(int i, Bundle bundle) {
return new CursorLoader(this,
diff --git a/app/src/main/java/com/cybexmobile/activity/main/BottomNavigationActivity.java b/app/src/main/java/com/cybexmobile/activity/main/BottomNavigationActivity.java
index bcd2e7a8..d4a1cb9a 100644
--- a/app/src/main/java/com/cybexmobile/activity/main/BottomNavigationActivity.java
+++ b/app/src/main/java/com/cybexmobile/activity/main/BottomNavigationActivity.java
@@ -4,8 +4,13 @@
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.net.Uri;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
import android.os.Bundle;
+import android.os.Handler;
+import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.design.widget.BottomNavigationView;
import android.support.v4.app.FragmentManager;
@@ -19,9 +24,13 @@
import com.cybex.basemodule.constant.Constant;
import com.cybex.basemodule.service.WebSocketService;
import com.cybex.eto.fragment.EtoFragment;
+import com.cybex.provider.exception.NetworkStatusException;
+import com.cybex.provider.graphene.chain.AccountObject;
import com.cybex.provider.http.response.AppConfigResponse;
import com.cybex.provider.market.WatchlistData;
import com.cybex.provider.websocket.BitsharesWalletWraper;
+import com.cybex.provider.websocket.MessageCallback;
+import com.cybex.provider.websocket.Reply;
import com.cybex.provider.websocket.apihk.LimitOrderWrapper;
import com.cybexmobile.BuildConfig;
import com.cybexmobile.activity.markets.MarketsActivity;
@@ -37,6 +46,7 @@
import com.cybexmobile.helper.BottomNavigationViewHelper;
import com.cybexmobile.R;
+import org.ethereum.util.ByteUtil;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;
@@ -44,11 +54,17 @@
import java.util.ArrayList;
import java.util.Locale;
+import io.enotes.sdk.repository.card.Command;
+import io.enotes.sdk.repository.card.CommandException;
+import io.enotes.sdk.repository.card.TLVBox;
+import io.enotes.sdk.repository.db.entity.Card;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
+import static com.cybex.basemodule.constant.Constant.PREF_IS_LOGIN_IN;
+import static com.cybex.basemodule.constant.Constant.PREF_NAME;
import static com.cybexmobile.activity.markets.MarketsActivity.RESULT_CODE_BACK;
import static com.cybex.basemodule.constant.Constant.INTENT_PARAM_ACTION;
import static com.cybex.basemodule.constant.Constant.INTENT_PARAM_WATCHLIST;
@@ -104,6 +120,73 @@ protected void onCreate(Bundle savedInstanceState) {
}
}
+ @Override
+ protected void readCardOnSuccess(Card card) {
+ super.readCardOnSuccess(card);
+ if (mBottomNavigationView.getSelectedItemId() != R.id.navigation_exchange) {
+ try {
+ byte[] bytes = ByteUtil.hexStringToBytes(cardManager.transmitApdu(Command.newCmd().setDesc("cybex_account").setCmdStr("00CA0032")));
+ TLVBox tlvBox = TLVBox.parse(bytes, 0, bytes.length);
+ String stringValue = new String(tlvBox.getBytesValue(0x32));
+ setLoginPublicKey(card.getCurrencyPubKey());
+ new Handler().postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ loginByENotes(stringValue, "123456789");
+ }
+ }, 500);
+ } catch (CommandException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ private void loginByENotes(String email, String password) {
+ if (TextUtils.isEmpty(email) || TextUtils.isEmpty(password)) {
+ return;
+ }
+ showLoadDialog(true);
+ try {
+ BitsharesWalletWraper.getInstance().get_account_object(email, new MessageCallback>() {
+ @Override
+ public void onMessage(Reply reply) {
+ AccountObject accountObject = reply.result;
+ int result = BitsharesWalletWraper.getInstance().import_account_password(accountObject, email, password);
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ hideLoadDialog();
+ setLoginFrom(true);
+ EventBus.getDefault().post(new Event.LoginIn(email));
+ SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ sharedPreferences.edit().putBoolean(PREF_IS_LOGIN_IN, true).apply();
+ sharedPreferences.edit().putString(PREF_NAME, email).apply();
+
+ mBottomNavigationView.setSelectedItemId(R.id.navigation_account);
+ }
+ });
+
+ }
+
+ @Override
+ public void onFailure() {
+ hideLoadDialog();
+ }
+ });
+ } catch (NetworkStatusException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void parseIntent() {
+ Intent intent = getIntent();
+ Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
+ if (tag != null) {// from nfc
+ cardManager.parseNfcTag(tag);
+ }
+
+ }
+
@Subscribe(threadMode = ThreadMode.MAIN)
public void onConfigChanged(Event.ConfigChanged event) {
isRecreate = true;
@@ -156,6 +239,7 @@ protected void onDestroy() {
}
LimitOrderWrapper.getInstance().disconnect();
BitsharesWalletWraper.getInstance().cancelLockWalletTime();
+ BaseActivity.cardApp=null;
}
@Override
@@ -170,6 +254,7 @@ protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
//register after recreate that activity
isRecreate = true;
+ parseIntent();
recreate();
}
diff --git a/app/src/main/java/com/cybexmobile/activity/transfer/TransferActivity.java b/app/src/main/java/com/cybexmobile/activity/transfer/TransferActivity.java
index deae2f2d..21327c1d 100644
--- a/app/src/main/java/com/cybexmobile/activity/transfer/TransferActivity.java
+++ b/app/src/main/java/com/cybexmobile/activity/transfer/TransferActivity.java
@@ -82,6 +82,8 @@
import butterknife.OnFocusChange;
import butterknife.OnTextChanged;
import butterknife.Unbinder;
+import io.enotes.sdk.repository.db.entity.Card;
+import io.enotes.sdk.utils.ReaderUtils;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
@@ -166,7 +168,7 @@ public class TransferActivity extends BaseActivity implements
private int mTotalLockTime;
private int mLockTimeUnit = 1;
-
+ private Card mCard;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -832,7 +834,7 @@ private void clearTransferData() {
resetTransferButtonState();
checkIsLockAndLoadTransferFee(ASSET_ID_CYB, false);
}
-
+ private UnlockDialog unlockDialog;
/**
* 检查钱包锁定状态 -> 加载转账手续费
*/
@@ -840,8 +842,8 @@ private void checkIsLockAndLoadTransferFee(String feeAssetId, boolean isLoadFeeT
if (mFromAccountObject == null) {
return;
}
- if (BitsharesWalletWraper.getInstance().is_locked()) {
- CybexDialog.showUnlockWalletDialog(getSupportFragmentManager(), mFromAccountObject,
+ if (BitsharesWalletWraper.getInstance().is_locked() && !isLoginFromENotes()) {
+ unlockDialog = CybexDialog.showUnlockWalletDialog(getSupportFragmentManager(), mFromAccountObject,
mFromAccountObject.name, new UnlockDialog.UnLockDialogClickListener() {
@Override
public void onUnLocked(String password) {
@@ -853,12 +855,19 @@ public void onUnLocked(String password) {
}
}
+ @Override
+ protected void readCardOnSuccess(Card card) {
+ super.readCardOnSuccess(card);
+ mCard = card;
+ if (unlockDialog != null) unlockDialog.dismiss();
+ }
+
/**
* 检查钱包锁定状态 -> 加载转账手续费 -> 转账
*/
private void checkIsLockAndTransfer() {
- if (BitsharesWalletWraper.getInstance().is_locked()) {
- CybexDialog.showUnlockWalletDialog(getSupportFragmentManager(), mFromAccountObject, mFromAccountObject.name, new UnlockDialog.UnLockDialogClickListener() {
+ if (BitsharesWalletWraper.getInstance().is_locked() && !isLoginFromENotes()) {
+ unlockDialog = CybexDialog.showUnlockWalletDialog(getSupportFragmentManager(), mFromAccountObject, mFromAccountObject.name, new UnlockDialog.UnLockDialogClickListener() {
@Override
public void onUnLocked(String password) {
showTransferConfirmationDialog();
@@ -901,6 +910,29 @@ private void toTransfer() {
if (mFromAccountObject == null || mToAccountObject == null || mSelectedAccountBalanceObjectItem == null) {
return;
}
+ if (isLoginFromENotes()) {
+ if (!cardManager.isConnected()) {
+ if (ReaderUtils.supportNfc(this))
+ showToast(this, getString(R.string.error_connect_card));
+ else
+ showToast(this, getString(R.string.error_connect_card_ble));
+ return;
+ }
+ if (!cardManager.isPresent()) {
+ if (ReaderUtils.supportNfc(this))
+ showToast(this, getString(R.string.error_connect_card));
+ else
+ showToast(this, getString(R.string.error_connect_card_ble));
+ return;
+ }
+ if (mCard != null && !mCard.getCurrencyPubKey().equals(getLoginPublicKey())) {
+ showToast(this, getString(R.string.please_right_card));
+ return;
+ }
+ if (BaseActivity.cardApp != null) {
+ mCard = BaseActivity.cardApp;
+ }
+ }
showLoadDialog();
Operations.base_operation transferOperation;
if (mSwLockTime.isChecked() && mSelectedLockTimePublicKey != null && mTotalLockTime != 0) {
@@ -934,8 +966,14 @@ private void toTransfer() {
BitsharesWalletWraper.getInstance().get_dynamic_global_properties(new MessageCallback>() {
@Override
public void onMessage(Reply reply) {
- SignedTransaction signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransaction(
- mFromAccountObject, transferOperation, ID_TRANSER_OPERATION, reply.result);
+ SignedTransaction signedTransaction;
+ if (mCard == null) {
+ signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransaction(
+ mFromAccountObject, transferOperation, ID_TRANSER_OPERATION, reply.result);
+ } else {
+ signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransactionByENotes(cardManager, mCard,
+ mFromAccountObject, transferOperation, ID_TRANSER_OPERATION, reply.result);
+ }
try {
BitsharesWalletWraper.getInstance().broadcast_transaction_with_callback(signedTransaction, mTransferCallback);
} catch (NetworkStatusException e) {
diff --git a/app/src/main/java/com/cybexmobile/fragment/exchange/BuySellFragment.java b/app/src/main/java/com/cybexmobile/fragment/exchange/BuySellFragment.java
index 5f063349..894208b2 100644
--- a/app/src/main/java/com/cybexmobile/fragment/exchange/BuySellFragment.java
+++ b/app/src/main/java/com/cybexmobile/fragment/exchange/BuySellFragment.java
@@ -3,6 +3,7 @@
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -25,7 +26,9 @@
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
+import android.widget.Toast;
+import com.cybex.basemodule.base.BaseActivity;
import com.cybex.basemodule.base.BaseFragment;
import com.cybex.provider.market.WatchlistData;
import com.cybex.provider.websocket.MessageCallback;
@@ -63,6 +66,8 @@
import butterknife.OnTextChanged;
import butterknife.OnTouch;
import butterknife.Unbinder;
+import io.enotes.sdk.core.CardManager;
+import io.enotes.sdk.utils.ReaderUtils;
import static com.cybex.basemodule.constant.Constant.INTENT_PARAM_PRECISION;
import static com.cybex.basemodule.constant.Constant.INTENT_PARAM_SPINNER_POSITION;
@@ -763,11 +768,53 @@ public void onUnLocked(String password) {
});
}
+ protected boolean isLoginFromENotes() {
+ SharedPreferences sharedPreferences = getActivity().getSharedPreferences("enotes", Context.MODE_PRIVATE);
+ return sharedPreferences.getBoolean("from", true);
+ }
+
+ protected String getLoginPublicKey() {
+ SharedPreferences sharedPreferences = getActivity().getSharedPreferences("enotes", Context.MODE_PRIVATE);
+ return sharedPreferences.getString("key", "");
+ }
+
+ protected void showToast(Context context, String text) {
+ Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
+
+ }
+
/**
* 挂单
*/
private void toExchange(){
+ BaseActivity activity = (BaseActivity) getActivity();
try {
+ if (isLoginFromENotes()) {
+
+ CardManager cardManager = activity.cardManager;
+ if (!cardManager.isConnected()) {
+ if (ReaderUtils.supportNfc(activity))
+ showToast(activity, getString(R.string.error_connect_card));
+ else
+ showToast(activity, getString(R.string.error_connect_card_ble));
+ return;
+ }
+ if (!cardManager.isPresent()) {
+ if (ReaderUtils.supportNfc(activity))
+ showToast(activity, getString(R.string.error_connect_card));
+ else
+ showToast(activity, getString(R.string.error_connect_card_ble));
+ return;
+ }
+ if (activity.currentCard != null && !activity.currentCard.getCurrencyPubKey().equals(getLoginPublicKey())) {
+ showToast(activity, getString(R.string.please_right_card));
+ return;
+ }
+ if(BaseActivity.cardApp!=null){
+ activity.currentCard = BaseActivity.cardApp;
+ }
+ }
+
BitsharesWalletWraper.getInstance().get_dynamic_global_properties(new MessageCallback>() {
@Override
public void onMessage(Reply reply) {
@@ -786,8 +833,13 @@ public void onMessage(Reply reply) {
mCurrentAction.equals(ACTION_BUY) ? mWatchlistData.getQuoteAsset().id : mWatchlistData.getBaseAsset().id,
mIsCybBalanceEnough ? mCybExchangeFee.amount : mBaseOrQuoteExchangeFee.amount,
amountSell, amountReceive);
- SignedTransaction signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransaction(
- mFullAccountObject.account, operation, ID_CREATE_LIMIT_ORDER_OPERATION, reply.result);
+ SignedTransaction signedTransaction;
+ if (activity.currentCard == null)
+ signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransaction(
+ mFullAccountObject.account, operation, ID_CREATE_LIMIT_ORDER_OPERATION, reply.result);
+ else
+ signedTransaction = BitsharesWalletWraper.getInstance().getSignedTransactionByENotes(activity.cardManager, activity.currentCard,
+ mFullAccountObject.account, operation, ID_CREATE_LIMIT_ORDER_OPERATION, reply.result);
try {
BitsharesWalletWraper.getInstance().broadcast_transaction_with_callback(signedTransaction, mLimitOrderCreateCallback);
} catch (NetworkStatusException e) {
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
new file mode 100755
index 00000000..6c47df43
--- /dev/null
+++ b/app/src/main/res/values-en/strings.xml
@@ -0,0 +1,9 @@
+
+ CybexDex
+
+
+ Hello blank fragment
+ Please scan your eNotes with the phone.
+ Please connect the bluetooth NFC reader.
+ Please scan the correct card!
+
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
new file mode 100755
index 00000000..e7fc1810
--- /dev/null
+++ b/app/src/main/res/values-zh/strings.xml
@@ -0,0 +1,9 @@
+
+ CybexDex
+
+
+ Hello blank fragment
+ 请将eNotes靠近手机。
+ 请将eNotes靠近蓝牙NFC读卡器。
+ 请放置正确的eNotes!
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0396526f..f7c8c112 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -3,4 +3,8 @@
Hello blank fragment
+ Please scan your eNotes with the phone.
+ Please connect the bluetooth NFC reader.
+ Please scan the correct card!
+
diff --git a/app/src/main/res/xml/nfc_tech_filter.xml b/app/src/main/res/xml/nfc_tech_filter.xml
new file mode 100755
index 00000000..acb29b68
--- /dev/null
+++ b/app/src/main/res/xml/nfc_tech_filter.xml
@@ -0,0 +1,7 @@
+
+
+
+
+ android.nfc.tech.IsoDep
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 32d3d8e8..51a16eda 100644
--- a/build.gradle
+++ b/build.gradle
@@ -37,5 +37,6 @@ allprojects {
google()
jcenter()
maven {url 'https://jitpack.io'}
+ maven { url "https://dl.bintray.com/cryptoenotes/eNotes" }
}
}
\ No newline at end of file
diff --git a/config.gradle b/config.gradle
index 6e3fb8c5..e8dababc 100644
--- a/config.gradle
+++ b/config.gradle
@@ -4,7 +4,7 @@ ext {
android = [
compileSdkVersion : 27,
buildToolsVersion : '28.0.2',
- minSdkVersion : 17,
+ minSdkVersion : 22,
targetSdkVersion : 27,
]
diff --git a/data-provider/build.gradle b/data-provider/build.gradle
index 18f42c15..9ea454a1 100644
--- a/data-provider/build.gradle
+++ b/data-provider/build.gradle
@@ -61,6 +61,7 @@ dependencies {
implementation 'com.github.bilthon:graphenej:0.4.2'
implementation 'com.fasterxml.jackson.core:jackson-databind:2.6.3'
implementation 'com.belerweb:pinyin4j:2.5.0'
+ implementation 'io.enotes.sdk:eNotes:1.0.0'
}
greendao {
diff --git a/data-provider/src/main/java/com/cybex/provider/graphene/chain/SignedTransaction.java b/data-provider/src/main/java/com/cybex/provider/graphene/chain/SignedTransaction.java
index d04f757b..4b0e3afa 100644
--- a/data-provider/src/main/java/com/cybex/provider/graphene/chain/SignedTransaction.java
+++ b/data-provider/src/main/java/com/cybex/provider/graphene/chain/SignedTransaction.java
@@ -4,9 +4,23 @@
import com.cybex.provider.crypto.Sha256Object;
+import org.ethereum.crypto.ECKey;
+import org.ethereum.util.ByteUtil;
+
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
+import io.enotes.sdk.constant.ErrorCode;
+import io.enotes.sdk.core.CardManager;
+import io.enotes.sdk.repository.card.CommandException;
+import io.enotes.sdk.repository.card.Commands;
+import io.enotes.sdk.repository.card.TLVBox;
+import io.enotes.sdk.repository.db.entity.Card;
+import mrd.bitlib.crypto.Signature;
+import mrd.bitlib.crypto.SignedMessage;
+import mrd.bitlib.util.Sha256Hash;
+
public class SignedTransaction extends Transaction {
private final static char[] hexArray = "0123456789abcdef".toCharArray();
transient List SignaturesBuffer = new ArrayList<>();
@@ -18,6 +32,12 @@ public void sign(Types.private_key_type privateKeyType, Sha256Object chain_id) {
signatures.add(bytesToHex(privateKeyType.getPrivateKey().sign_compact(digest, true).data));
}
+ public void signByENotes(CardManager cardManager, Card card, Types.private_key_type privateKeyType, Sha256Object chain_id) {
+ Sha256Object digest = sig_digest(chain_id);
+ SignaturesBuffer.add(sign_compactByENotes(cardManager, card, digest, true));
+ signatures.add(bytesToHex(sign_compactByENotes(cardManager, card, digest, true).data));
+ }
+
public String sign(Types.private_key_type privateKeyType) {
Sha256Object digest = sig_digest();
SignaturesBuffer.add(privateKeyType.getPrivateKey().sign_compact(digest, true));
@@ -26,6 +46,63 @@ public String sign(Types.private_key_type privateKeyType) {
return signatures.get(0);
}
+ public CompactSignature sign_compactByENotes(CardManager cardManager, Card card, Sha256Object digest, boolean require_canonical) {
+ CompactSignature signature = null;
+ try {
+
+
+ while (true) {
+ SignedMessage signedMessage = signHashByENotes(cardManager, card, new Sha256Hash(digest.hash));
+ byte[] byteCompact = signedMessage.bitcoinEncodingOfSignature();
+ signature = new CompactSignature(byteCompact);
+
+ boolean bResult = PublicKey.is_canonical(signature);
+ if (bResult == true) {
+ break;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return signature;
+ }
+
+ public SignedMessage signHashByENotes(CardManager cardManager, Card card, Sha256Hash hashToSign) {
+ TLVBox tlvBox = new TLVBox();
+ tlvBox.putBytesValue(Commands.TLVTag.Transaction_Hash, hashToSign.getBytes());
+
+ try {
+ byte[] bytes = ByteUtil.hexStringToBytes(cardManager.transmitApdu(Commands.signTX(tlvBox.serialize())));
+ TLVBox signatureTLV = TLVBox.parse(bytes, 0, bytes.length);
+ String signature = signatureTLV.getStringValue(Commands.TLVTag.Transaction_signature);
+ if (signature.length() != 128) {
+ throw new CommandException(ErrorCode.INVALID_CARD, "please_right_card");
+ }
+ String r = signature.substring(0, 64);
+ String s = signature.substring(64);
+ ECKey.ECDSASignature signature1 = new ECKey.ECDSASignature(new BigInteger(r, 16), new BigInteger(s, 16)).toCanonicalised();
+ Signature sig = new Signature(signature1.r,signature1.s);
+
+ // Now we have to work backwards to figure out the recId needed to recover the signature.
+ mrd.bitlib.crypto.PublicKey targetPubKey = new mrd.bitlib.crypto.PublicKey(card.getBitCoinECKey().getPubKeyPoint().getEncoded(true));
+ boolean compressed = targetPubKey.isCompressed();
+ int recId = -1;
+ for (int i = 0; i < 4; i++) {
+
+ mrd.bitlib.crypto.PublicKey k = SignedMessage.recoverFromSignature(i, sig, hashToSign, compressed);
+ if (k != null && targetPubKey.equals(k)) {
+ recId = i;
+ break;
+ }
+ }
+ return SignedMessage.from(sig, targetPubKey, recId);
+ } catch (CommandException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
private String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for ( int j = 0; j < bytes.length; j++ ) {
diff --git a/data-provider/src/main/java/com/cybex/provider/websocket/BitsharesWalletWraper.java b/data-provider/src/main/java/com/cybex/provider/websocket/BitsharesWalletWraper.java
index c0ed521e..abb2e33c 100644
--- a/data-provider/src/main/java/com/cybex/provider/websocket/BitsharesWalletWraper.java
+++ b/data-provider/src/main/java/com/cybex/provider/websocket/BitsharesWalletWraper.java
@@ -37,6 +37,8 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
+import io.enotes.sdk.core.CardManager;
+import io.enotes.sdk.repository.db.entity.Card;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@@ -442,6 +444,11 @@ public SignedTransaction getSignedTransaction(AccountObject accountObject, Opera
return mWalletApi.getSignedTransaction(accountObject, operation, operationId, dynamicGlobalPropertyObject);
}
+ public SignedTransaction getSignedTransactionByENotes(CardManager cardManager, Card card, AccountObject accountObject, Operations.base_operation operation, int operationId, DynamicGlobalPropertyObject dynamicGlobalPropertyObject) {
+
+ return mWalletApi.getSignedTransactionByENotes(cardManager, card, accountObject, operation, operationId, dynamicGlobalPropertyObject);
+ }
+
public String getChatMessageSignature(AccountObject accountObject, String message){
return mWalletApi.getChatMessageSignature(accountObject, message);
}
diff --git a/data-provider/src/main/java/com/cybex/provider/websocket/WalletApi.java b/data-provider/src/main/java/com/cybex/provider/websocket/WalletApi.java
index 01872f99..cf9ddedc 100644
--- a/data-provider/src/main/java/com/cybex/provider/websocket/WalletApi.java
+++ b/data-provider/src/main/java/com/cybex/provider/websocket/WalletApi.java
@@ -61,6 +61,9 @@
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicInteger;
+import io.enotes.sdk.core.CardManager;
+import io.enotes.sdk.repository.db.entity.Card;
+
public class WalletApi {
class wallet_object {
@@ -829,6 +832,34 @@ public SignedTransaction getSignedTransaction(AccountObject accountObject, Opera
return signedTransaction;
}
+ public SignedTransaction getSignedTransactionByENotes(CardManager cardManager, Card card, AccountObject accountObject, Operations.base_operation operation, int operationId, DynamicGlobalPropertyObject dynamicGlobalPropertyObject) {
+ SignedTransaction signedTransaction = new SignedTransaction();
+ Operations.operation_type operationType = new Operations.operation_type();
+ operationType.nOperationType = operationId;
+ operationType.operationContent = operation;
+ signedTransaction.operationTypes = new ArrayList<>();
+ signedTransaction.operationTypes.add(operationType);
+ signedTransaction.operations = new ArrayList<>();
+ List