Updated on 2026-08-14

This commit is contained in:
Tangem 2019-05-07 17:52:42 +03:00
parent e11275cb49
commit e1df0d9e76
6 changed files with 39 additions and 69 deletions

View file

@ -118,4 +118,5 @@ dependencies {
implementation 'org.apache.commons:commons-lang3:3.6' implementation 'org.apache.commons:commons-lang3:3.6'
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.8' implementation 'com.fasterxml.jackson.datatype:jackson-datatype-joda:2.9.8'
implementation 'joda-time:joda-time:2.10.1' implementation 'joda-time:joda-time:2.10.1'
testImplementation 'junit:junit:4.12'
} }

View file

@ -57,6 +57,11 @@ public class ServerApiBinance {
} }
} }
if (!binanceData.isBalanceReceived()) {
binanceData.setBalanceReceived(true);
binanceData.setBalance("0");
}
binanceData.setAccountNumber(account.getAccountNumber()); binanceData.setAccountNumber(account.getAccountNumber());
binanceData.setSequence(account.getSequence()); binanceData.setSequence(account.getSequence());
} }

View file

@ -1,17 +1,12 @@
package com.tangem.wallet.binance; package com.tangem.wallet.binance;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.StrictMode;
import android.text.InputFilter; import android.text.InputFilter;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.ripple.crypto.ecdsa.ECDSASignature;
import com.tangem.card_common.data.TangemCard; import com.tangem.card_common.data.TangemCard;
import com.tangem.card_common.reader.CardCrypto;
import com.tangem.card_common.reader.CardProtocol; import com.tangem.card_common.reader.CardProtocol;
import com.tangem.card_common.tasks.SignTask; import com.tangem.card_common.tasks.SignTask;
import com.tangem.card_common.util.Util; import com.tangem.card_common.util.Util;
@ -28,12 +23,8 @@ import com.tangem.wallet.CoinEngine;
import com.tangem.wallet.R; import com.tangem.wallet.R;
import com.tangem.wallet.TangemContext; import com.tangem.wallet.TangemContext;
import com.tangem.wallet.binance.client.BinanceDexApiClientFactory; import com.tangem.wallet.binance.client.BinanceDexApiClientFactory;
import com.tangem.wallet.binance.client.BinanceDexApiClientGenerator;
import com.tangem.wallet.binance.client.BinanceDexApiRestClient; import com.tangem.wallet.binance.client.BinanceDexApiRestClient;
import com.tangem.wallet.binance.client.BinanceDexEnvironment; import com.tangem.wallet.binance.client.BinanceDexEnvironment;
import com.tangem.wallet.binance.client.domain.Account;
import com.tangem.wallet.binance.client.domain.Balance;
import com.tangem.wallet.binance.client.domain.TransactionMetadata;
import com.tangem.wallet.binance.client.domain.broadcast.TransactionOption; import com.tangem.wallet.binance.client.domain.broadcast.TransactionOption;
import com.tangem.wallet.binance.client.domain.broadcast.Transfer; import com.tangem.wallet.binance.client.domain.broadcast.Transfer;
import com.tangem.wallet.binance.client.encoding.Bech32; import com.tangem.wallet.binance.client.encoding.Bech32;
@ -42,16 +33,16 @@ import com.tangem.wallet.binance.client.encoding.message.MessageType;
import com.tangem.wallet.binance.client.encoding.message.TransactionRequestAssemblerExtSign; import com.tangem.wallet.binance.client.encoding.message.TransactionRequestAssemblerExtSign;
import com.tangem.wallet.binance.client.encoding.message.TransferMessage; import com.tangem.wallet.binance.client.encoding.message.TransferMessage;
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Utils; import org.bitcoinj.core.Utils;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.math.BigInteger; import java.math.BigInteger;
import java.math.RoundingMode; import java.math.RoundingMode;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import okhttp3.RequestBody;
import retrofit2.Call; import retrofit2.Call;
import retrofit2.Callback; import retrofit2.Callback;
import retrofit2.Response; import retrofit2.Response;
@ -63,7 +54,7 @@ public class BinanceEngine extends CoinEngine {
private static final String TAG = BinanceEngine.class.getSimpleName(); private static final String TAG = BinanceEngine.class.getSimpleName();
public BinanceData coinData = null; public BinanceData coinData = null;
BinanceDexApiRestClient client = null; private BinanceDexApiRestClient client = null;
public BinanceEngine(TangemContext context) throws Exception { public BinanceEngine(TangemContext context) throws Exception {
super(context); super(context);
@ -198,7 +189,7 @@ public class BinanceEngine extends CoinEngine {
public Uri getShareWalletUri() { public Uri getShareWalletUri() {
return Uri.parse(ctx.getCoinData().getWallet()); return Uri.parse(ctx.getCoinData().getWallet());
} //TODO:check }
@Override @Override
public InputFilter[] getAmountInputFilters() { public InputFilter[] getAmountInputFilters() {
@ -208,10 +199,7 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public boolean checkNewTransactionAmount(Amount amount) { public boolean checkNewTransactionAmount(Amount amount) {
if (coinData == null) return false; if (coinData == null) return false;
if (amount.compareTo(coinData.getBalance()) > 0) { return amount.compareTo(coinData.getBalance()) <= 0;
return false;
}
return true;
} }
@Override @Override
@ -320,7 +308,6 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public InternalAmount convertToInternalAmount(Amount amount) { public InternalAmount convertToInternalAmount(Amount amount) {
;
return new InternalAmount(amount, getBalanceCurrency()); return new InternalAmount(amount, getBalanceCurrency());
} }
@ -334,8 +321,7 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public byte[] convertToByteArray(InternalAmount internalAmount) { public byte[] convertToByteArray(InternalAmount internalAmount) {
byte[] bytes = Util.longToByteArray(internalAmount.longValueExact()); return Util.longToByteArray(internalAmount.longValueExact());
return bytes;
} }
@Override @Override
@ -391,27 +377,6 @@ public class BinanceEngine extends CoinEngine {
TransferMessage msgBean = txAssembler.createTransferMessage(transfer); TransferMessage msgBean = txAssembler.createTransferMessage(transfer);
byte[] msg = txAssembler.encodeTransferMessage(msgBean); byte[] msg = txAssembler.encodeTransferMessage(msgBean);
byte[] dataForSign = txAssembler.prepareForSign(msgBean); byte[] dataForSign = txAssembler.prepareForSign(msgBean);
// byte[] dataForSign = Util.fromHexString("7b226163636f756e745f6e756d626572223a2231222c22636861696e5f6964223a22626e62636861696e2d31303030222c226d656d6f223a22222c226d736773223a5b7b226964223a22423635363144434331303431333030353941374330384634384336343631304331463646393036342d3130222c226f7264657274797065223a322c227072696365223a3130303030303030302c227175616e74697479223a313230303030303030302c2273656e646572223a22626e63316b6574706d6e71736779637174786e7570723667636572707073306b6c797279687a36667a6c222c2273696465223a312c2273796d626f6c223a224254432d3543345f424e42222c2274696d65696e666f726365223a317d5d2c2273657175656e6365223a2239227d");
//
// byte[] privateKey = Util.fromHexString("30c5e838578a29e3e9273edddd753d6c9b38aca2446dd84bdfe2e5988b0da0a1");
//
// byte[] signFromCard = CardCrypto.Signature(privateKey, dataForSign);
//
// int size = signFromCard.length / 2;
// BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, size));
// BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, size, size * 2));
// s = CryptoUtil.toCanonicalised(s);
//// ECKey.ECDSASignature sig = new ECKey.ECDSASignature(r, s);
//// byte[] sigDer = sig.encodeToDER();
//// if (!ECDSASignature.isStrictlyCanonical(sigDer)) {
//// throw new IllegalStateException("Signature is not strictly canonical");
//// }
// byte[] resultSig = new byte[64];
// System.arraycopy(Utils.bigIntegerToBytes(r, 32), 0, resultSig, 0, 32);
// System.arraycopy(Utils.bigIntegerToBytes(s, 32), 0, resultSig, 32, 32);
//
// String test = Util.byteArrayToHexString(resultSig);
// int x = 1;
return new SignTask.TransactionToSign() { return new SignTask.TransactionToSign() {
@ -421,9 +386,10 @@ public class BinanceEngine extends CoinEngine {
} }
@Override @Override
public byte[][] getHashesToSign() { public byte[][] getHashesToSign() throws NoSuchAlgorithmException {
byte[][] hashForSign = new byte[1][]; byte[][] hashForSign = new byte[1][];
hashForSign[0] = CryptoUtil.doubleSha256(dataForSign); MessageDigest digest = MessageDigest.getInstance("SHA-256");
hashForSign[0] = digest.digest(dataForSign);
return hashForSign; return hashForSign;
} }
@ -434,7 +400,7 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public String getHashAlgToSign() { public String getHashAlgToSign() {
return "sha-256x2"; return "sha-256";
} }
@Override @Override
@ -444,21 +410,17 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public byte[] onSignCompleted(byte[] signFromCard) throws Exception { public byte[] onSignCompleted(byte[] signFromCard) throws Exception {
// int size = signFromCard.length / 2; int size = signFromCard.length / 2;
// BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, size)); BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, size));
// BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, size, size * 2)); BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, size, size * 2));
//// s = CryptoUtil.toCanonicalised(s); s = CryptoUtil.toCanonicalised(s);
//// ECKey.ECDSASignature sig = new ECKey.ECDSASignature(r, s);
//// byte[] sigDer = sig.encodeToDER(); byte[] resultSig = new byte[64];
//// if (!ECDSASignature.isStrictlyCanonical(sigDer)) { System.arraycopy(Utils.bigIntegerToBytes(r, 32), 0, resultSig, 0, 32);
//// throw new IllegalStateException("Signature is not strictly canonical"); System.arraycopy(Utils.bigIntegerToBytes(s, 32), 0, resultSig, 32, 32);
//// }
// byte[] resultSig = new byte[64];
// System.arraycopy(Utils.bigIntegerToBytes(r, 32), 0, resultSig, 0, 32);
// System.arraycopy(Utils.bigIntegerToBytes(s, 32), 0, resultSig, 32, 32);
// TransactionRequestAssembler.buildTransfer as reference // TransactionRequestAssembler.buildTransfer as reference
byte[] signature = txAssembler.encodeSignature(signFromCard); byte[] signature = txAssembler.encodeSignature(resultSig);
byte[] txForSend = txAssembler.encodeStdTx(msg, signature); byte[] txForSend = txAssembler.encodeStdTx(msg, signature);
notifyOnNeedSendTransaction(txForSend); notifyOnNeedSendTransaction(txForSend);
@ -570,7 +532,7 @@ public class BinanceEngine extends CoinEngine {
@Override @Override
public void onFail() { public void onFail() {
ctx.setError("Transaction send error"); ctx.setError("Broadcast error");
blockchainRequestsCallbacks.onComplete(false); blockchainRequestsCallbacks.onComplete(false);
} }
}; };
@ -579,12 +541,16 @@ public class BinanceEngine extends CoinEngine {
serverApiBinance.sendTransaction(txForSend, client); serverApiBinance.sendTransaction(txForSend, client);
} catch (Exception e) { } catch (Exception e) {
Log.e(TAG, "Transaction send error"); Log.e(TAG, e.getMessage());
ctx.setError("Transaction send error"); ctx.setError(e.getMessage());
blockchainRequestsCallbacks.onComplete(false); blockchainRequestsCallbacks.onComplete(false);
} }
} }
public int pendingTransactionTimeoutInSeconds() {
return 9;
}
public boolean allowSelectFeeLevel() { public boolean allowSelectFeeLevel() {
return false; return false;
} }

View file

@ -38,7 +38,7 @@ public class TransactionRequestAssemblerExtSign {
this.options = options; this.options = options;
} }
public static long doubleToLong(String d) { private static long doubleToLong(String d) {
BigDecimal encodeValue = new BigDecimal(d).multiply(MULTIPLY_FACTOR); BigDecimal encodeValue = new BigDecimal(d).multiply(MULTIPLY_FACTOR);
if (encodeValue.compareTo(MAX_NUMBER) > 0) { if (encodeValue.compareTo(MAX_NUMBER) > 0) {
throw new IllegalArgumentException(d + " is too large."); throw new IllegalArgumentException(d + " is too large.");
@ -48,11 +48,11 @@ public class TransactionRequestAssemblerExtSign {
} }
public byte[] prepareForSign(BinanceDexTransactionMessage msg) public byte[] prepareForSign(BinanceDexTransactionMessage msg)
throws JsonProcessingException, NoSuchAlgorithmException { throws JsonProcessingException {
SignData sd = new SignData(); SignData sd = new SignData();
sd.setChainId(binanceData.getChainId()); sd.setChainId(binanceData.getChainId());
sd.setAccountNumber(String.valueOf(binanceData.getAccountNumber())); sd.setAccountNumber(String.valueOf(binanceData.getAccountNumber()));
sd.setSequence(String.valueOf(binanceData.getAccountNumber())); sd.setSequence(String.valueOf(binanceData.getSequence()));
sd.setMsgs(new BinanceDexTransactionMessage[]{msg}); sd.setMsgs(new BinanceDexTransactionMessage[]{msg});
sd.setMemo(options.getMemo()); sd.setMemo(options.getMemo());
@ -150,7 +150,7 @@ public class TransactionRequestAssemblerExtSign {
} }
public byte[] buildTransfer(Transfer transfer) public byte[] buildTransfer(Transfer transfer)
throws IOException, NoSuchAlgorithmException { throws IOException {
TransferMessage msgBean = createTransferMessage(transfer); TransferMessage msgBean = createTransferMessage(transfer);
byte[] msg = encodeTransferMessage(msgBean); byte[] msg = encodeTransferMessage(msgBean);
return prepareForSign(msgBean); return prepareForSign(msgBean);

View file

@ -198,10 +198,8 @@ public class BinanceDexApiRestClientImpl implements BinanceDexApiRestClient {
return broadcast(requestBody, sync, wallet); return broadcast(requestBody, sync, wallet);
} }
public TransactionRequestAssemblerExtSign prepareTransfer(Transfer transfer, BinanceData binanceData, byte[] pubKeyFroSign, TransactionOption options, boolean sync) public TransactionRequestAssemblerExtSign prepareTransfer(Transfer transfer, BinanceData binanceData, byte[] pubKeyForSign, TransactionOption options, boolean sync) {
throws IOException, NoSuchAlgorithmException { return new TransactionRequestAssemblerExtSign(binanceData, pubKeyForSign, options);
TransactionRequestAssemblerExtSign assembler = new TransactionRequestAssemblerExtSign(binanceData, pubKeyFroSign, options);
return assembler;
// RequestBody requestBody = assembler.buildTransfer(transfer); // RequestBody requestBody = assembler.buildTransfer(transfer);
// return broadcast(requestBody, sync, wallet); // return broadcast(requestBody, sync, wallet);
} }

View file

@ -1,8 +1,8 @@
package com.tangem.wallet package com.tangem.wallet
import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import org.junit.Assert.*
/** /**
* Example local unit test, which will execute on the development machine (host). * Example local unit test, which will execute on the development machine (host).