Updated on 2026-08-14
This commit is contained in:
parent
5dd2ef6776
commit
ef75cfed25
10 changed files with 626 additions and 208 deletions
|
|
@ -0,0 +1,25 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
import com.tangem.data.network.model.BlockcypherBody;
|
||||
import com.tangem.data.network.model.BlockcypherResponse;
|
||||
import com.tangem.data.network.model.BlockcypherFee;
|
||||
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.Query;
|
||||
|
||||
public interface BlockcypherApi {
|
||||
@GET(Server.ApiBlockcypher.Method.MAIN)
|
||||
Call<BlockcypherFee> blockcypherMain();
|
||||
|
||||
@GET(Server.ApiBlockcypher.Method.ADDRESS)
|
||||
Call<BlockcypherResponse> blockcypherAddress(@Path("address") String address);
|
||||
|
||||
@Headers("Content-Type: application/json")
|
||||
@POST(Server.ApiBlockcypher.Method.PUSH)
|
||||
Call<BlockcypherResponse> blockcypherPush(@Body BlockcypherBody blockcypherBody, @Query("token") String token);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package com.tangem.data.network
|
||||
|
||||
enum class BlockcypherToken(val token: String) {
|
||||
T_001("aa8184b0e0894b88a5688e01b3dc1e82"),
|
||||
T_002("56c4ca23c6484c8f8864c32fde4def8d"),
|
||||
T_003("66a8a37c5e9d4d2c9bb191acfe7f93aa")
|
||||
}
|
||||
|
|
@ -55,4 +55,26 @@ public class Server {
|
|||
static final String N_6 = URL_ESTIMATEFEE + "n/6";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ApiBinance {
|
||||
public static final String URL_BINANCE = ServerURL.API_BINANCE;
|
||||
static final String API_V1 = "api/v1/";
|
||||
|
||||
public static class Method {
|
||||
static final String ACCOUNT = URL_BINANCE + API_V1 + "account";
|
||||
static final String FEES = URL_BINANCE + API_V1 + "fees";
|
||||
static final String BROADCAST = URL_BINANCE + API_V1 + "broadcast";
|
||||
}
|
||||
}
|
||||
|
||||
public static class ApiBlockcypher {
|
||||
public static final String URL_BLOCKCYPHER = ServerURL.API_BLOCKCYPHER;
|
||||
static final String V1_BTC_MAIN = "v1/btc/main";
|
||||
|
||||
public static class Method {
|
||||
static final String MAIN = URL_BLOCKCYPHER + V1_BTC_MAIN;
|
||||
static final String ADDRESS = MAIN + "/addrs/{address}?unspentOnly=true&includeScript=true";
|
||||
static final String PUSH = MAIN + "/txs/push";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.App;
|
||||
import com.tangem.data.network.model.BlockcypherBody;
|
||||
import com.tangem.data.network.model.BlockcypherFee;
|
||||
import com.tangem.data.network.model.BlockcypherResponse;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
||||
public class ServerApiBlockcypher {
|
||||
private static String TAG = ServerApiRipple.class.getSimpleName();
|
||||
|
||||
public static final String BLOCKCYPHER_ADDRESS = "blockcypher_address";
|
||||
public static final String BLOCKCYPHER_FEE = "blockcypher_fee";
|
||||
public static final String BLOCKCYPHER_SEND = "blockcypher_send";
|
||||
|
||||
private int requestsCount = 0;
|
||||
|
||||
public boolean isRequestsSequenceCompleted() {
|
||||
Log.i(TAG, String.format("isRequestsSequenceCompleted: %s (%d requests left)", String.valueOf(requestsCount <= 0), requestsCount));
|
||||
return requestsCount <= 0;
|
||||
}
|
||||
|
||||
private ResponseListener responseListener;
|
||||
|
||||
public interface ResponseListener {
|
||||
void onSuccess(String method, BlockcypherResponse blockcypherResponse);
|
||||
|
||||
void onSuccess(String method, BlockcypherFee blockcypherFee);
|
||||
|
||||
void onFail(String method, String message);
|
||||
}
|
||||
|
||||
public void setResponseListener(ResponseListener listener) {
|
||||
responseListener = listener;
|
||||
}
|
||||
|
||||
public void requestData(String method, String wallet, String tx) {
|
||||
requestsCount++;
|
||||
BlockcypherApi blockcypherApi = App.Companion.getNetworkComponent().getRetrofitBlockcypher().create(BlockcypherApi.class);
|
||||
|
||||
switch (method) {
|
||||
case BLOCKCYPHER_ADDRESS:
|
||||
Call<BlockcypherResponse> addressCall = blockcypherApi.blockcypherAddress(wallet);
|
||||
addressCall.enqueue(new Callback<BlockcypherResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<BlockcypherResponse> call, @NonNull Response<BlockcypherResponse> response) {
|
||||
if (response.code() == 200) {
|
||||
requestsCount--;
|
||||
responseListener.onSuccess(method, response.body());
|
||||
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
} else {
|
||||
responseListener.onFail(method, String.valueOf(response.code()));
|
||||
Log.e(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<BlockcypherResponse> call, @NonNull Throwable t) {
|
||||
responseListener.onFail(method, String.valueOf(t.getMessage()));
|
||||
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case BLOCKCYPHER_FEE:
|
||||
Call<BlockcypherFee> feeCall = blockcypherApi.blockcypherMain();
|
||||
feeCall.enqueue(new Callback<BlockcypherFee>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<BlockcypherFee> call, @NonNull Response<BlockcypherFee> response) {
|
||||
if (response.code() == 200) {
|
||||
requestsCount--;
|
||||
responseListener.onSuccess(method, response.body());
|
||||
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
} else {
|
||||
responseListener.onFail(method, String.valueOf(response.code()));
|
||||
Log.e(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<BlockcypherFee> call, @NonNull Throwable t) {
|
||||
responseListener.onFail(method, String.valueOf(t.getMessage()));
|
||||
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case BLOCKCYPHER_SEND:
|
||||
BlockcypherToken blockcypherToken = BlockcypherToken.values()[new Random().nextInt(BlockcypherToken.values().length)];
|
||||
|
||||
Call<BlockcypherResponse> sendCall = blockcypherApi.blockcypherPush(new BlockcypherBody(tx), blockcypherToken.getToken());
|
||||
sendCall.enqueue(new Callback<BlockcypherResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<BlockcypherResponse> call, @NonNull Response<BlockcypherResponse> response) {
|
||||
if (response.code() == 201) {
|
||||
requestsCount--;
|
||||
responseListener.onSuccess(method, response.body());
|
||||
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
} else {
|
||||
responseListener.onFail(method, String.valueOf(response.code()));
|
||||
Log.e(TAG, "requestData " + method + " onResponse " + response.code());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<BlockcypherResponse> call, @NonNull Throwable t) {
|
||||
responseListener.onFail(method, String.valueOf(t.getMessage()));
|
||||
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
responseListener.onFail(method, "undeclared method");
|
||||
Log.e(TAG, "requestData " + method + " onFailure - undeclared method");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,4 +7,6 @@ class ServerURL {
|
|||
static final String API_ESTIMATEFEE = "https://estimatefee.com/";
|
||||
static final String API_UPDATE_VERSION = "https://raw.githubusercontent.com/";
|
||||
static final String API_ROOTSTOCK = "https://public-node.rsk.co/";
|
||||
static final String API_BINANCE = "https://testnet-dex.binance.org/";
|
||||
static final String API_BLOCKCYPHER = "https://api.blockcypher.com/";
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.data.network.model;
|
||||
|
||||
public class BlockcypherBody {
|
||||
private String tx;
|
||||
|
||||
public BlockcypherBody(String tx) {
|
||||
this.tx = tx;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
package com.tangem.data.network.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
data class BlockcypherResponse(
|
||||
@SerializedName("address")
|
||||
var address: String? = null,
|
||||
|
||||
@SerializedName("balance")
|
||||
var balance: Long? = null,
|
||||
|
||||
@SerializedName("unconfirmed_balance")
|
||||
var unconfirmed_balance: Long? = null,
|
||||
|
||||
@SerializedName("txrefs")
|
||||
var txrefs: List<BlockcypherTxref>? = null
|
||||
)
|
||||
|
||||
data class BlockcypherTxref(
|
||||
@SerializedName("tx_hash")
|
||||
var tx_hash: String? = null,
|
||||
|
||||
@SerializedName("tx_output_n")
|
||||
var tx_output_n: Int? = null,
|
||||
|
||||
@SerializedName("value")
|
||||
var value: Long? = null,
|
||||
|
||||
@SerializedName("confirmations")
|
||||
var confirmations: Long? = null,
|
||||
|
||||
@SerializedName("script")
|
||||
var script: String? = null
|
||||
)
|
||||
|
||||
data class BlockcypherFee(
|
||||
@SerializedName("low_fee_per_kb")
|
||||
var low_fee_per_kb: Long? = null,
|
||||
|
||||
@SerializedName("medium_fee_per_kb")
|
||||
var medium_fee_per_kb: Long? = null,
|
||||
|
||||
@SerializedName("high_fee_per_kb")
|
||||
var high_fee_per_kb: Long? = null
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue