diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
deleted file mode 100644
index 30aa626c23..0000000000
--- a/.idea/codeStyles/Project.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index d70d548ee7..7d8d06f4cc 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,7 +5,7 @@ apply plugin: 'kotlin-kapt'
static def generateVersionName() {
def gitCommitsCount = "git rev-list HEAD --count".execute().text.trim()
- def gitCurrentBranch = "git rev-parse --abbrev-ref HEAD".execute().text.trim()
+// def gitCurrentBranch = "git rev-parse --abbrev-ref HEAD".execute().text.trim()
return gitCommitsCount.toInteger() + 831// + "\\n" + gitCurrentBranch
}
diff --git a/app/src/main/java/com/tangem/data/network/ServerApiSoChain.java b/app/src/main/java/com/tangem/data/network/ServerApiSoChain.java
index 862af12b63..df8cac1af1 100644
--- a/app/src/main/java/com/tangem/data/network/ServerApiSoChain.java
+++ b/app/src/main/java/com/tangem/data/network/ServerApiSoChain.java
@@ -24,9 +24,7 @@ public class ServerApiSoChain {
return requestsCount <= 0;
}
- private ResponseListener responseListener;
-
- public interface ResponseListener {
+ public interface AddressInfoListener {
void onSuccess(SoChain.Response.AddressBalance response);
void onSuccess(SoChain.Response.TxUnspent response);
@@ -34,8 +32,22 @@ public class ServerApiSoChain {
void onFail(String message);
}
- public void setResponseListener(ResponseListener listener) {
- responseListener = listener;
+ private AddressInfoListener addressInfoListener;
+
+ public void setAddressInfoListener(AddressInfoListener listener) {
+ addressInfoListener = listener;
+ }
+
+ public interface SendTxListener {
+ void onSuccess(SoChain.Response.SendTx response);
+
+ void onFail(String message);
+ }
+
+ private SendTxListener sendTxListener;
+
+ public void setSendTxListener(SendTxListener listener) {
+ sendTxListener = listener;
}
private String getNetwork(Blockchain blockchain) throws Exception {
@@ -62,16 +74,16 @@ public class ServerApiSoChain {
Log.i(TAG, "requestAddressBalance onResponse " + response.code());
if (response.code() == 200) {
requestsCount--;
- responseListener.onSuccess(response.body());
+ addressInfoListener.onSuccess(response.body());
} else {
- responseListener.onFail(String.valueOf(response.code()));
+ addressInfoListener.onFail(String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
- responseListener.onFail(String.valueOf(t.getMessage()));
+ addressInfoListener.onFail(String.valueOf(t.getMessage()));
}
});
}
@@ -87,16 +99,43 @@ public class ServerApiSoChain {
Log.i(TAG, "requestAddressBalance onResponse " + response.code());
if (response.code() == 200) {
requestsCount--;
- responseListener.onSuccess(response.body());
+ addressInfoListener.onSuccess(response.body());
} else {
- responseListener.onFail(String.valueOf(response.code()));
+ addressInfoListener.onFail(String.valueOf(response.code()));
}
}
@Override
public void onFailure(@NonNull Call call, @NonNull Throwable t) {
Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
- responseListener.onFail(String.valueOf(t.getMessage()));
+ addressInfoListener.onFail(String.valueOf(t.getMessage()));
+ }
+ });
+ }
+
+ public void requestSendTransaction(Blockchain blockchain, String txHEX) throws Exception {
+ requestsCount++;
+ SoChainApi api = App.Companion.getNetworkComponent().getRetrofitSoChain().create(SoChainApi.class);
+
+ SoChain.Request.SendTx tx=new SoChain.Request.SendTx();
+ tx.setTx_hex(txHEX);
+ Call call = api.sendTransaction(getNetwork(blockchain), tx);
+ call.enqueue(new Callback() {
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+ Log.i(TAG, "requestAddressBalance onResponse " + response.code());
+ if (response.code() == 200) {
+ requestsCount--;
+ sendTxListener.onSuccess(response.body());
+ } else {
+ sendTxListener.onFail(String.valueOf(response.code()));
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+ Log.e(TAG, "requestAddressBalance onFailure " + t.getMessage());
+ sendTxListener.onFail(String.valueOf(t.getMessage()));
}
});
}
diff --git a/app/src/main/java/com/tangem/data/network/SoChainApi.java b/app/src/main/java/com/tangem/data/network/SoChainApi.java
index b9c956a000..ddb982d09a 100644
--- a/app/src/main/java/com/tangem/data/network/SoChainApi.java
+++ b/app/src/main/java/com/tangem/data/network/SoChainApi.java
@@ -19,5 +19,5 @@ public interface SoChainApi {
@Headers("Content-Type: application/json")
@POST(Server.ApiSoChain.Method.SEND_TRANSACTION)
- Call sendTransaction(@Path("network") String network, @Body SoChain.Request.SendTx body);
+ Call sendTransaction(@Path("network") String network, @Body SoChain.Request.SendTx body);
}
diff --git a/app/src/main/java/com/tangem/data/network/model/SoChain.kt b/app/src/main/java/com/tangem/data/network/model/SoChain.kt
index 2730df7776..cc42d6204a 100644
--- a/app/src/main/java/com/tangem/data/network/model/SoChain.kt
+++ b/app/src/main/java/com/tangem/data/network/model/SoChain.kt
@@ -42,5 +42,15 @@ class SoChain {
var data: Data? = null
}
+
+ class SendTx {
+ class Data {
+ var network: String? = null
+ var txid: String? = null
+ var tx_hex: String? = null
+ }
+ var status: String? = null
+ var data: Data? = null
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/tangem/wallet/btc/BtcEngine.java b/app/src/main/java/com/tangem/wallet/btc/BtcEngine.java
index 73b6871752..6e2ea3aef5 100644
--- a/app/src/main/java/com/tangem/wallet/btc/BtcEngine.java
+++ b/app/src/main/java/com/tangem/wallet/btc/BtcEngine.java
@@ -13,6 +13,7 @@ import com.tangem.data.Blockchain;
import com.tangem.data.local.PendingTransactionsStorage;
import com.tangem.data.network.ElectrumRequest;
import com.tangem.data.network.Server;
+import com.tangem.data.network.ServerApiCommon;
import com.tangem.data.network.ServerApiElectrum;
import com.tangem.data.network.ServerApiSoChain;
import com.tangem.data.network.model.SoChain;
@@ -639,7 +640,7 @@ public class BtcEngine extends CoinEngine {
} else {
final ServerApiSoChain serverApi = new ServerApiSoChain();
- ServerApiSoChain.ResponseListener responseListener = new ServerApiSoChain.ResponseListener() {
+ ServerApiSoChain.AddressInfoListener addressInfoListener = new ServerApiSoChain.AddressInfoListener() {
@Override
public void onSuccess(SoChain.Response.AddressBalance response) {
try {
@@ -738,7 +739,7 @@ public class BtcEngine extends CoinEngine {
};
- serverApi.setResponseListener(responseListener);
+ serverApi.setAddressInfoListener(addressInfoListener);
serverApi.requestAddressBalance(ctx.getBlockchain(), coinData.getWallet());
serverApi.requestUnspentTx(ctx.getBlockchain(), coinData.getWallet());
@@ -888,71 +889,177 @@ public class BtcEngine extends CoinEngine {
coinData.maxFee = null;
coinData.normalFee = null;
- final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
+ if (useElectrum) {
- final ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() {
- @Override
- public void onSuccess(ElectrumRequest electrumRequest) {
- BigDecimal kbFee;
- if (electrumRequest.isMethod(ElectrumRequest.METHOD_GetFee)) {
- try {
- kbFee = new BigDecimal(electrumRequest.getResultString()); //fee per KB
+ final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
- if (kbFee.equals(BigDecimal.ZERO)) {
- serverApiElectrum.requestData(ctx, ElectrumRequest.getFee());
- }
+ final ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() {
+ @Override
+ public void onSuccess(ElectrumRequest electrumRequest) {
+ BigDecimal kbFee;
+ if (electrumRequest.isMethod(ElectrumRequest.METHOD_GetFee)) {
+ try {
+ kbFee = new BigDecimal(electrumRequest.getResultString()); //fee per KB
- BigDecimal minByteFee = kbFee.divide(new BigDecimal(1024)); // per KB -> per byte
- BigDecimal normalByteFee = minByteFee.add(new BigDecimal(0.00000010));
- BigDecimal maxByteFee = minByteFee.add(new BigDecimal(0.00000025));
+ if (kbFee.equals(BigDecimal.ZERO)) {
+ serverApiElectrum.requestData(ctx, ElectrumRequest.getFee());
+ }
- BigDecimal minFee = minByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
- BigDecimal normalFee = normalByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
- BigDecimal maxFee = maxByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
+ BigDecimal minByteFee = kbFee.divide(new BigDecimal(1024)); // per KB -> per byte
+ BigDecimal normalByteFee = minByteFee.add(new BigDecimal(0.00000010));
+ BigDecimal maxByteFee = minByteFee.add(new BigDecimal(0.00000025));
- CoinEngine.Amount minAmount = new CoinEngine.Amount(minFee, ctx.getBlockchain().getCurrency());
- CoinEngine.Amount normalAmount = new CoinEngine.Amount(normalFee, ctx.getBlockchain().getCurrency());
- CoinEngine.Amount maxAmount = new CoinEngine.Amount(maxFee, ctx.getBlockchain().getCurrency());
+ BigDecimal minFee = minByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
+ BigDecimal normalFee = normalByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
+ BigDecimal maxFee = maxByteFee.multiply(new BigDecimal(calcSize)).setScale(8, RoundingMode.DOWN);
- coinData.minFee = minAmount;
- coinData.normalFee = normalAmount;
- coinData.maxFee = maxAmount;
+ CoinEngine.Amount minAmount = new CoinEngine.Amount(minFee, ctx.getBlockchain().getCurrency());
+ CoinEngine.Amount normalAmount = new CoinEngine.Amount(normalFee, ctx.getBlockchain().getCurrency());
+ CoinEngine.Amount maxAmount = new CoinEngine.Amount(maxFee, ctx.getBlockchain().getCurrency());
+
+ coinData.minFee = minAmount;
+ coinData.normalFee = normalAmount;
+ coinData.maxFee = maxAmount;
// if (coinData.minFee != null && coinData.normalFee != null && coinData.maxFee != null) {
- blockchainRequestsCallbacks.onComplete(true);
+ blockchainRequestsCallbacks.onComplete(true);
// } else {
// blockchainRequestsCallbacks.onProgress();
// }
- } catch (JSONException e) {
- e.printStackTrace();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
}
}
- }
- @Override
- public void onFail(ElectrumRequest electrumRequest) {
- ctx.setError(electrumRequest.getError());
- blockchainRequestsCallbacks.onComplete(false);
- }
- };
- serverApiElectrum.setResponseListener(electrumListener);
+ @Override
+ public void onFail(ElectrumRequest electrumRequest) {
+ ctx.setError(electrumRequest.getError());
+ blockchainRequestsCallbacks.onComplete(false);
+ }
+ };
+ serverApiElectrum.setResponseListener(electrumListener);
- serverApiElectrum.requestData(ctx, ElectrumRequest.getFee());
+ serverApiElectrum.requestData(ctx, ElectrumRequest.getFee());
+ } else {
+
+ final ServerApiCommon serverApiCommon = new ServerApiCommon();
+
+ final ServerApiCommon.EstimatedFeeListener estimatedFeeListener = new ServerApiCommon.EstimatedFeeListener() {
+ @Override
+ public void onSuccess(int blockCount, String estimateFeeResponse) {
+ BigDecimal fee = new BigDecimal(estimateFeeResponse); // BTC per 1 kb
+
+ if (fee.equals(BigDecimal.ZERO)) {
+ if (blockchainRequestsCallbacks.allowAdvance()) {
+ serverApiCommon.requestBtcEstimatedFee(blockCount);
+ }
+ return;
+ }
+
+ if (calcSize != 0) {
+ fee = fee.multiply(new BigDecimal(calcSize)).divide(new BigDecimal(1024), BigDecimal.ROUND_DOWN); // per Kb -> per byte
+ } else {
+ if (blockchainRequestsCallbacks.allowAdvance()) {
+ serverApiCommon.requestBtcEstimatedFee(blockCount);
+ }
+ return;
+ }
+
+ fee = fee.setScale(8, RoundingMode.DOWN);
+
+ switch (blockCount) {
+ case ServerApiCommon.ESTIMATE_FEE_MINIMAL:
+ coinData.minFee = new CoinEngine.Amount(fee, getFeeCurrency());
+ break;
+ case ServerApiCommon.ESTIMATE_FEE_NORMAL:
+ coinData.normalFee = new CoinEngine.Amount(fee, getFeeCurrency());
+ break;
+ case ServerApiCommon.ESTIMATE_FEE_PRIORITY:
+ coinData.maxFee = new CoinEngine.Amount(fee, getFeeCurrency());
+ break;
+ }
+
+ if (coinData.minFee != null && coinData.normalFee != null && coinData.maxFee != null) {
+ blockchainRequestsCallbacks.onComplete(true);
+ } else {
+ blockchainRequestsCallbacks.onProgress();
+ }
+ }
+
+ @Override
+ public void onFail(int blockCount, String message) {
+ // TODO - add fail counter to terminate after NNN tries
+ if (blockchainRequestsCallbacks.allowAdvance()) {
+ serverApiCommon.requestBtcEstimatedFee(blockCount);
+ return;
+ }
+ ctx.setError(ctx.getContext().getString(R.string.cannot_calculate_fee_wrong_data_received_from_node));
+ blockchainRequestsCallbacks.onComplete(false);
+ }
+ };
+ serverApiCommon.setBtcEstimatedFeeListener(estimatedFeeListener);
+
+ serverApiCommon.requestBtcEstimatedFee(ServerApiCommon.ESTIMATE_FEE_PRIORITY);
+ serverApiCommon.requestBtcEstimatedFee(ServerApiCommon.ESTIMATE_FEE_NORMAL);
+ serverApiCommon.requestBtcEstimatedFee(ServerApiCommon.ESTIMATE_FEE_MINIMAL);
+
+ }
}
@Override
- public void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) {
- final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
+ public void requestSendTransaction(BlockchainRequestsCallbacks blockchainRequestsCallbacks, byte[] txForSend) throws Exception {
final String txStr = BTCUtils.toHex(txForSend);
+ if (useElectrum) {
+ final ServerApiElectrum serverApiElectrum = new ServerApiElectrum();
- ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() {
- @Override
- public void onSuccess(ElectrumRequest electrumRequest) {
- if (electrumRequest.isMethod(ElectrumRequest.METHOD_SendTransaction)) {
+ ServerApiElectrum.ResponseListener electrumListener = new ServerApiElectrum.ResponseListener() {
+ @Override
+ public void onSuccess(ElectrumRequest electrumRequest) {
+ if (electrumRequest.isMethod(ElectrumRequest.METHOD_SendTransaction)) {
+ try {
+ String resultString = electrumRequest.getResultString();
+ if (resultString == null || resultString.isEmpty()) {
+ ctx.setError("Rejected by node: " + electrumRequest.getError());
+ blockchainRequestsCallbacks.onComplete(false);
+ } else {
+ ctx.setError(null);
+ blockchainRequestsCallbacks.onComplete(true);
+ }
+ } catch (Exception e) {
+ if (e.getMessage() != null) {
+ ctx.setError(e.getMessage());
+ blockchainRequestsCallbacks.onComplete(false);
+ } else {
+ ctx.setError(e.getClass().getName());
+ blockchainRequestsCallbacks.onComplete(false);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void onFail(ElectrumRequest electrumRequest) {
+ ctx.setError(electrumRequest.getError());
+ blockchainRequestsCallbacks.onComplete(false);
+ }
+ };
+ serverApiElectrum.setResponseListener(electrumListener);
+
+
+ serverApiElectrum.requestData(ctx, ElectrumRequest.broadcast(ctx.getCoinData().getWallet(), txStr));
+ } else {
+ final ServerApiSoChain serverApi = new ServerApiSoChain();
+
+ ServerApiSoChain.SendTxListener listener = new ServerApiSoChain.SendTxListener() {
+ @Override
+ public void onSuccess(SoChain.Response.SendTx response) {
try {
- String resultString = electrumRequest.getResultString();
- if (resultString == null || resultString.isEmpty()) {
- ctx.setError("Rejected by node: " + electrumRequest.getError());
+ if (response.getStatus() == null || response.getData() == null) {
+ ctx.setError("Rejected by node: invalid answer received");
+ blockchainRequestsCallbacks.onComplete(false);
+ } else if (response.getStatus().equals("fail") || response.getData().getTxid() == null) {
+ ctx.setError("Rejected by node: " + response.getData());
blockchainRequestsCallbacks.onComplete(false);
} else {
ctx.setError(null);
@@ -968,19 +1075,17 @@ public class BtcEngine extends CoinEngine {
}
}
}
- }
- @Override
- public void onFail(ElectrumRequest electrumRequest) {
- ctx.setError(electrumRequest.getError());
- blockchainRequestsCallbacks.onComplete(false);
- }
- };
- serverApiElectrum.setResponseListener(electrumListener);
-
-
- serverApiElectrum.requestData(ctx, ElectrumRequest.broadcast(ctx.getCoinData().getWallet(), txStr));
+ @Override
+ public void onFail(String message) {
+ ctx.setError(message);
+ blockchainRequestsCallbacks.onComplete(false);
+ }
+ };
+ serverApi.setSendTxListener(listener);
+ serverApi.requestSendTransaction(ctx.getBlockchain(), txStr);
+ }
}
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 07821a2684..c4a30cd5d8 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,11 +1,11 @@
buildscript {
- ext.kotlin_version = '1.3.21'
+ ext.kotlin_version = '1.3.30'
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.3.2'
+ classpath 'com.android.tools.build:gradle:3.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
}
diff --git a/card-android/build.gradle b/card-android/build.gradle
index 6d22133a08..956d0c88fe 100644
--- a/card-android/build.gradle
+++ b/card-android/build.gradle
@@ -29,7 +29,7 @@ dependencies {
implementation project(':card-common')
// implementation 'com.github.TangemCash.card_android-common:card_android-android:0.1.0'
- implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
+ implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.scottyab:rootbeer-lib:0.0.7'
testImplementation 'junit:junit:4.12'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 6fea634781..c494404a7f 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Fri Jan 18 12:06:47 MSK 2019
+#Wed Apr 17 22:33:22 MSK 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
diff --git a/server-android/build.gradle b/server-android/build.gradle
index f79ad5009e..7aaa4af308 100644
--- a/server-android/build.gradle
+++ b/server-android/build.gradle
@@ -29,7 +29,7 @@ dependencies {
implementation project(':card-common')
// implementation 'com.github.TangemCash.card_android-common:card_android-android:0.1.0'
- implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
+ implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'