Updated on 2026-08-14

This commit is contained in:
Tangem 2019-06-13 17:23:45 +03:00
commit bd8d84a85a
680 changed files with 51751 additions and 6799 deletions

View file

@ -1,29 +1,41 @@
package com.tangem.data;
import com.tangem.tangemcard.R;
import com.tangem.card_android.R;
/**
* Created by dvol on 06.08.2017.
*/
public enum Blockchain {
Unknown("", "", R.drawable.ic_logo_unknown, ""),
Bitcoin("BTC", "BTC", R.drawable.ic_logo_bitcoin, "Bitcoin"),
BitcoinTestNet("BTC/test", "BTC", R.drawable.ic_logo_bitcoin_testnet, "Bitcoin Testnet"),
Ethereum("ETH", "ETH", R.drawable.ic_logo_ethereum, "Ethereum"),
EthereumTestNet("ETH/test", "ETH", R.drawable.ic_logo_ethereum_testnet, "Ethereum Testnet"),
Token("Token", "ERC20", R.drawable.ic_logo_bat_token, "Ethereum"),
BitcoinCash("BCH", "BCH", R.drawable.ic_logo_bitcoin_cash, "Bitcoin Cash"),
Litecoin("LTC", "LTC", R.drawable.ic_logo_bitcoin, "Litecoin"),
Stellar("XLM", "XLM", R.drawable.ic_logo_stellar, "Stellar Lumens"),
StellarTestNet("XLM/test", "XLM", R.drawable.ic_logo_stellar, "Stellar Lumens");
Blockchain(String ID, String currency, int imageResource, String officialName) {
Unknown("", "", 1.0, R.drawable.ic_logo_unknown, ""),
Bitcoin("BTC", "BTC", 100000000.0, R.drawable.ic_logo_bitcoin, "Bitcoin"),
BitcoinTestNet("BTC/test", "BTC", 100000000.0, R.drawable.ic_logo_bitcoin_testnet, "Bitcoin Testnet"),
Ethereum("ETH", "ETH", 1.0, R.drawable.ic_logo_ethereum, "Ethereum"),
EthereumTestNet("ETH/test", "ETH", 1.0, R.drawable.ic_logo_ethereum_testnet, "Ethereum Testnet"),
Token("Token", "ETH", 1.0, R.drawable.ic_logo_bat_token, "Ethereum"),
NftToken("NftToken", "", 1.0, R.drawable.tangem2, "Ethereum"),
BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.ic_logo_bitcoin_cash, "Bitcoin Cash"),
Litecoin("LTC", "LTC", 100000000.0, R.drawable.tangem2, "Litecoin"),
Rootstock("RSK", "RBTC", 1.0, R.drawable.tangem2, "RSK"),
RootstockToken("RskToken", "RBTC", 1.0, R.drawable.tangem2, "RSK"),
Cardano("CARDANO", "ADA", 1000000.0, R.drawable.tangem2, "Cardano"),
Ripple ("XRP", "XRP", 1000000.0, R.drawable.tangem2, "XRP"),
Binance("BINANCE", "BNB", 100000000.0, R.drawable.tangem2, "Binance"),
BinanceTestNet("BINANCE/test", "BNB", 100000000.0, R.drawable.tangem2, "Binance Testnet"),
Matic("MATIC", "MTX", 1.0, R.drawable.tangem2, "Matic"),
MaticTestNet("MATIC/test", "MTX", 1.0, R.drawable.tangem2, "Matic Testnet");
Stellar("XLM", "XLM", R.drawable.ic_logo_stellar, "Stellar"),
StellarTestNet("XLM/test", "XLM", R.drawable.ic_logo_stellar, "Stellar Testnet");
Blockchain(String ID, String currency, double multiplier, int imageResource, String officialName) {
mID = ID;
mCurrency = currency;
// mMultiplier = multiplier;
mImageResource = imageResource;
mOfficialName = officialName;
}
private String mID, mOfficialName;
//private double mMultiplier;
private String mCurrency;
private int mImageResource;
@ -35,6 +47,10 @@ public enum Blockchain {
return mOfficialName;
}
// public double getMultiplier() {
// return mMultiplier;
// }
public String getCurrency() {
return mCurrency;
}
@ -78,7 +94,6 @@ public enum Blockchain {
return resourceId;
}
//TODO - ???
public static int getLogoImageResource(String blockchainID, String symbolName) {
switch (blockchainID) {
case "BTC":

View file

@ -20,11 +20,7 @@ import java.util.Objects;
public class LogFileProvider extends ContentProvider {
private static final String CLASS_NAME = "LogFileProvider";
// The authority is the symbolic name for the provider class
// public static final String AUTHORITY = "com.tangem.LogFileProvider";
// public static final String AUTHORITY = "com.tangem.LogFileProvider";
private static final String TAG = LogFileProvider.class.getSimpleName() + "-oF";
// UriMatcher used to match against incoming requests
private UriMatcher uriMatcher;
@ -43,15 +39,11 @@ public class LogFileProvider extends ContentProvider {
}
@Override
public ParcelFileDescriptor openFile(Uri uri, String mode)
throws FileNotFoundException {
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
String LOG_TAG = CLASS_NAME + "-oF";
Log.v(TAG, "Called with uri: '" + uri + "'." + uri.getLastPathSegment());
Log.v(LOG_TAG,
"Called with uri: '" + uri + "'." + uri.getLastPathSegment());
// Check incoming Uri against the matcher
// check incoming Uri against the matcher
switch (uriMatcher.match(uri)) {
// If it returns 1 - then it matches the Uri defined in onCreate
@ -60,7 +52,7 @@ public class LogFileProvider extends ContentProvider {
// The desired file name is specified by the last segment of the
// path
// E.g.
// 'content://it.my.app.LogFileProvider/Test.txt'
// 'content://it.my.app.LogFileProvider/Test1.txt'
// Take this and build the path to the file
String fileLocation = getContext().getCacheDir() + File.separator
+ uri.getLastPathSegment();
@ -73,9 +65,8 @@ public class LogFileProvider extends ContentProvider {
// Otherwise unrecognised Uri
default:
Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: "
+ uri.toString());
Log.v(TAG, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: " + uri.toString());
}
}

View file

@ -3,7 +3,7 @@ package com.tangem.data;
import android.content.Context;
import android.util.Log;
import com.tangem.tangemcard.util.Util;
import com.tangem.card_common.util.Util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@ -226,7 +226,7 @@ public class Logger {
//
// verifyStoragePermissions(activity);
// initLogFile(activity.getApplicationContext());
// t.start();
// t.init();
// } catch (Exception e) {
// e.printStackTrace();
// }
@ -268,7 +268,7 @@ public class Logger {
// //Checks if the app has permission to write to device storage
// //If the app does not has permission then the user will be prompted to grant permissions
// public static void verifyStoragePermissions(Activity activity) {
// // Check if we have write permission
// // check if we have write permission
// int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
//
// if (permission != PackageManager.PERMISSION_GRANTED) {

View file

@ -0,0 +1,44 @@
package com.tangem.data.dp
import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import com.orhanobut.hawk.Hawk
import com.tangem.Constant
class PrefsManager {
companion object {
const val PREF_NAME = "tangem_access"
@SuppressLint("StaticFieldLeak")
private var instance: PrefsManager? = null
fun getInstance(): PrefsManager {
if (instance == null) {
instance = PrefsManager()
}
return instance as PrefsManager
}
}
private lateinit var context: Context
private lateinit var preferences: SharedPreferences
fun init(context: Context) {
this.context = context
preferences = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE)
Hawk.init(context).build()
}
val lastWalletAddress: String
get() = Hawk.get(Constant.PREF_LAST_WALLET_ADDRESS, "")
fun saveLastWalletAddress(value: String) {
Hawk.put(Constant.PREF_LAST_WALLET_ADDRESS, value)
}
fun clearLastWalletAddress() {
Hawk.delete(Constant.PREF_LAST_WALLET_ADDRESS)
}
}

View file

@ -3,7 +3,7 @@ package com.tangem.data.fingerprint;
import android.os.AsyncTask;
import android.widget.Toast;
import com.tangem.presentation.activity.PinSaveActivity;
import com.tangem.ui.activity.PinSaveActivity;
import com.tangem.wallet.R;
import java.lang.ref.WeakReference;

View file

@ -9,8 +9,9 @@ import android.security.keystore.KeyPermanentlyInvalidatedException;
import android.security.keystore.KeyProperties;
import com.tangem.Constant;
import com.tangem.tangemcard.android.data.PINStorage;
import com.tangem.presentation.activity.PinRequestActivity;
import com.tangem.card_android.android.data.PINStorage;
import com.tangem.ui.activity.PinRequestActivity;
import com.tangem.util.LOG;
import java.io.IOException;
import java.lang.ref.WeakReference;
@ -26,6 +27,8 @@ import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
public static final String TAG = StartFingerprintReaderTask.class.getSimpleName();
private WeakReference<PinRequestActivity> reference;
private KeyStore keyStore;
@ -64,16 +67,14 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
@Override
protected void onPostExecute(final Boolean success) {
PinRequestActivity pinRequestActivity = reference.get();
onCancelled();
if (!success) {
pinRequestActivity.doLog("Authentication failed!");
LOG.i(TAG, "Authentication failed!");
} else {
fingerprintHelper.startAuth(fingerprintManager, cryptoObject);
pinRequestActivity.doLog("Authenticate using fingerprint!");
LOG.i(TAG, "Authenticate using fingerprint!");
}
}
@ -85,9 +86,7 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
}
private boolean getKeyStore() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Getting keystore...");
LOG.i(TAG, "Getting keystore...");
try {
keyStore = KeyStore.getInstance(Constant.KEYSTORE);
keyStore.load(null); // Create empty keystore
@ -101,9 +100,7 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
@TargetApi(Build.VERSION_CODES.M)
public boolean createNewKey(boolean forceCreate) {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Creating new key...");
LOG.i(TAG, "Creating new key...");
try {
if (forceCreate)
keyStore.deleteEntry(Constant.KEY_ALIAS);
@ -120,9 +117,9 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
);
generator.generateKey();
pinRequestActivity.doLog("Key created.");
LOG.i(TAG, "Key created.");
} else
pinRequestActivity.doLog("Key exists.");
LOG.i(TAG, "Key exists.");
return true;
} catch (Exception e) {
@ -133,9 +130,7 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
}
private boolean getCipher() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Getting cipher...");
LOG.i(TAG, "Getting cipher...");
try {
cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7);
return true;
@ -150,7 +145,7 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
private boolean initCipher(int mode) {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Initializing cipher...");
LOG.i(TAG, "Initializing cipher...");
try {
keyStore.load(null);
SecretKey keyspec = (SecretKey) keyStore.getKey(Constant.KEY_ALIAS, null);
@ -181,9 +176,7 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
@TargetApi(Build.VERSION_CODES.M)
private boolean initCryptObject() {
PinRequestActivity pinRequestActivity = reference.get();
pinRequestActivity.doLog("Initializing crypt object...");
LOG.i(TAG, "Initializing crypt object...");
try {
cryptoObject = new FingerprintManager.CryptoObject(cipher);
return true;
@ -193,5 +186,4 @@ public class StartFingerprintReaderTask extends AsyncTask<Void, Void, Boolean> {
return false;
}
}

View file

@ -0,0 +1,106 @@
package com.tangem.data.local
import android.content.Context
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.tangem.card_common.data.TangemCard
import java.io.File
import java.util.*
import kotlin.collections.HashMap
class PendingTransactionsStorage
(
val context: Context
) {
private lateinit var cardTransactions: MutableMap<String, CardTransactionsInfo>
private val transactionsFile: File = File(context.filesDir, "transactions.json")
private var cacheDir: File? = null
init {
cacheDir = File(context.filesDir, "artworks")
if (!cacheDir!!.exists())
cacheDir!!.mkdirs()
if (transactionsFile.exists()) {
try {
transactionsFile.bufferedReader().use { cardTransactions = Gson().fromJson(it, object : TypeToken<HashMap<String, CardTransactionsInfo>>() {}.type) }
} catch (e: Exception) {
e.printStackTrace()
cardTransactions = HashMap()
}
} else {
cardTransactions = HashMap()
}
}
private fun clearExpired()
{
for(cardId in cardTransactions.keys) {
cardTransactions[cardId]!!.transactions.removeAll { it.isExpired() }
}
cardTransactions.entries.removeAll { it.value.isEmpty() }
}
fun save() {
clearExpired()
val sTransactions = Gson().toJson(cardTransactions)
transactionsFile.bufferedWriter().use { it.write(sTransactions) }
}
fun putTransaction(card: TangemCard, txId: String, expireTimeoutInSeconds: Int) {
val sendDate=Date()
val calendar=Calendar.getInstance()
calendar.time=sendDate
calendar.add(Calendar.SECOND, expireTimeoutInSeconds)
val expireDate=calendar.time
putTransaction(card.cidDescription, txId, sendDate, expireDate)
}
private fun putTransaction(cardId: String, txId: String, sendDate: Date, expireDate: Date) {
val transactionInfo = TransactionInfo(
txId, sendDate, expireDate
)
if (cardTransactions[cardId] == null) {
cardTransactions[cardId] = CardTransactionsInfo(arrayListOf())
}
cardTransactions[cardId]?.transactions?.add(transactionInfo)
save()
}
fun getTransactions(card: TangemCard): CardTransactionsInfo? {
clearExpired()
return cardTransactions[card.cidDescription]
}
fun hasTransactions(card: TangemCard): Boolean {
val cardTransactionsInfo=getTransactions(card)
if( cardTransactionsInfo!=null ) return cardTransactionsInfo.transactions.count()>0
return false
}
fun removeTransaction(card: TangemCard, txId: String)
{
cardTransactions[card.cidDescription]?.transactions?.removeAll { it.tx==txId }
save()
}
data class TransactionInfo(
val tx: String,
val sendDate: Date,
val expireDate: Date
) {
fun isExpired(): Boolean {
return Date().after(expireDate)
}
}
data class CardTransactionsInfo(
var transactions: MutableList<TransactionInfo>
) {
fun isEmpty(): Boolean {
return transactions.count()==0
}
}
}

View file

@ -0,0 +1,30 @@
package com.tangem.data.network;
import com.tangem.data.network.model.AdaliteBody;
import com.tangem.data.network.model.AdaliteResponse;
import com.tangem.data.network.model.AdaliteResponseUtxo;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.POST;
import retrofit2.http.Path;
public interface AdaliteApi {
@GET(ServerApiAdalite.ADALITE_ADDRESS)
Call<AdaliteResponse> adaliteAddress(@Path("address") String address);
@Headers("Content-Type: application/json")
@POST(ServerApiAdalite.ADALITE_UNSPENT_OUTPUTS)
Call<AdaliteResponseUtxo> adaliteUnspent(@Body String address);
// @GET(ServerApiAdalite.ADALITE_TRANSACTION)
// Call<AdaliteResponse> adaliteTransaction(@Path("txId") String txId);
@Headers("Content-Type: application/json")
@POST(ServerApiAdalite.ADALITE_SEND)
Call<List> adaliteSend(@Body AdaliteBody adaliteBody);
}

View file

@ -0,0 +1,13 @@
package com.tangem.data.network;
import com.tangem.data.network.model.BinanceFees;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
public interface BinanceApi {
@GET("fees")
Call<List<BinanceFees>> binanceFees();
}

View file

@ -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(@Path("blockchain") String blockchain);
@GET(Server.ApiBlockcypher.Method.ADDRESS)
Call<BlockcypherResponse> blockcypherAddress(@Path("blockchain") String blockchain, @Path("address") String address);
@Headers("Content-Type: application/json")
@POST(Server.ApiBlockcypher.Method.PUSH)
Call<BlockcypherResponse> blockcypherPush(@Path("blockchain") String blockchain, @Body BlockcypherBody blockcypherBody, @Query("token") String token);
}

View file

@ -0,0 +1,7 @@
package com.tangem.data.network
enum class BlockcypherToken(val token: String) {
T_001("aa8184b0e0894b88a5688e01b3dc1e82"),
T_002("56c4ca23c6484c8f8864c32fde4def8d"),
T_003("66a8a37c5e9d4d2c9bb191acfe7f93aa")
}

View file

@ -2,12 +2,14 @@ package com.tangem.data.network;
import com.tangem.data.network.model.RateInfoResponse;
import java.util.List;
import io.reactivex.Observable;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query;
public interface CoinmarketApi {
@GET(Server.ApiCoinmarket.Method.V1_TICKER_CONVERT)
Observable<List<RateInfoResponse>> getRateInfoList();
@Headers("X-CMC_PRO_API_KEY: f6622117-c043-47a0-8975-9d673ce484de")
@GET(Server.ApiCoinmarket.Method.PRICE_CONVERSION)
Observable<RateInfoResponse> getRateInfo(@Query("amount") int amount, @Query("symbol") String cryptoId);
}

View file

@ -11,7 +11,7 @@ import com.google.gson.annotations.SerializedName;
import com.google.gson.internal.LinkedTreeMap;
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.tangem.tangemcard.util.Util;
import com.tangem.card_common.util.Util;
import com.tangem.wallet.R;
import java.io.IOException;

View file

@ -0,0 +1,32 @@
package com.tangem.data.network;
import com.tangem.data.network.model.InsightBody;
import com.tangem.data.network.model.InsightResponse;
import java.util.List;
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 InsightApi {
@GET(ServerApiInsight.INSIGHT_ADDRESS)
Call<InsightResponse> insightAddress(@Path("address") String address);
@GET(ServerApiInsight.INSIGHT_UNSPENT_OUTPUTS)
Call<List<InsightResponse>> insightUnspent(@Path("address") String address);
@GET(ServerApiInsight.INSIGHT_TRANSACTION)
Call<InsightResponse> insightTransaction(@Path("txId") String txId);
@GET(ServerApiInsight.INSIGHT_FEE)
Call<InsightResponse> insightFee();
@Headers("Content-Type: application/json")
@POST(ServerApiInsight.INSIGHT_SEND)
Call<InsightResponse> insightSend(@Body InsightBody body );
}

View file

@ -6,7 +6,7 @@ import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.tangem.tangemcard.util.Util;
import com.tangem.card_common.util.Util;
import com.tangem.wallet.R;
import org.spongycastle.util.encoders.Base64;

View file

@ -0,0 +1,15 @@
package com.tangem.data.network;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface MaticApi {
@Headers("Content-Type: application/json")
@POST(Server.ApiMaticTesnet.Method.MAIN)
Call<InfuraResponse> matic(@Body InfuraBody body);
}

View file

@ -0,0 +1,15 @@
package com.tangem.data.network;
import com.tangem.data.network.model.RippleBody;
import com.tangem.data.network.model.RippleResponse;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface RippleApi {
@Headers("Content-Type: application/json")
@POST("./")
Call<RippleResponse> ripple(@Body RippleBody body);
}

View file

@ -0,0 +1,15 @@
package com.tangem.data.network;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.Headers;
import retrofit2.http.POST;
public interface RootstockApi {
@Headers("Content-Type: application/json")
@POST(Server.ApiRootstock.Method.MAIN)
Call<InfuraResponse> rootstock(@Body InfuraBody body);
}

View file

@ -17,7 +17,7 @@ public class Server {
public static final String URL_COINMARKET = ServerURL.API_COINMARKETCAP;
public static class Method {
static final String V1_TICKER_CONVERT = URL_COINMARKET + "v1/ticker/?convert=USD&lmit=10";
static final String PRICE_CONVERSION = URL_COINMARKET + "v1/tools/price-conversion";
}
}
@ -28,7 +28,29 @@ public class Server {
public static final String URL_INFURA = ServerURL.API_INFURA;
public static class Method {
static final String MAIN = URL_INFURA + "613a0b14833145968b1f656240c7d245";
static final String MAIN = URL_INFURA + "v3/613a0b14833145968b1f656240c7d245";
}
}
/**
* https://public-node.rsk.co/
*/
public static class ApiRootstock {
public static final String URL_ROOTSTOCK = ServerURL.API_ROOTSTOCK;
public static class Method {
static final String MAIN = URL_ROOTSTOCK;
}
}
/**
* https://testnet2.matic.network
*/
public static class ApiMaticTesnet {
public static final String URL_MATIC_TESTNET = ServerURL.API_MATIC_TESTNET ;
public static class Method {
static final String MAIN = URL_MATIC_TESTNET;
}
}
@ -45,4 +67,42 @@ public class Server {
}
}
/**
* https://dex.binance.org/
*/
public static class ApiBinance {
public static final String URL_BINANCE = ServerURL.API_BINANCE;
public static class Method {
public static final String API_V1 = URL_BINANCE + "api/v1/";
}
}
/**
* https://testnet-dex.binance.org/
*/
public static class ApiBinanceTestnet {
public static final String URL_BINANCE_TESTNET = ServerURL.API_BINANCE_TESTNET;
public static class Method {
public static final String API_V1 = URL_BINANCE_TESTNET + "api/v1/";
}
}
/**
* https://api.blockcypher.com/
*/
public static class ApiBlockcypher {
public static final String URL_BLOCKCYPHER = ServerURL.API_BLOCKCYPHER;
static final String V1_MAIN = "v1/{blockchain}/main";
public static class Method {
static final String MAIN = URL_BLOCKCYPHER + V1_MAIN;
static final String ADDRESS = MAIN + "/addrs/{address}?unspentOnly=true&includeScript=true";
static final String PUSH = MAIN + "/txs/push";
}
}
}

View file

@ -0,0 +1,144 @@
package com.tangem.data.network;
import android.util.Log;
import com.tangem.data.network.model.AdaliteBody;
import com.tangem.data.network.model.AdaliteResponse;
import com.tangem.data.network.model.AdaliteResponseUtxo;
import java.util.List;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
public class ServerApiAdalite {
private static String TAG = ServerApiAdalite.class.getSimpleName();
public static final String ADALITE_ADDRESS = "/api/addresses/summary/{address}";
public static final String ADALITE_UNSPENT_OUTPUTS = "/api/bulk/addresses/utxo";
// public static final String ADALITE_TRANSACTION = "/api/txs/raw/{txId}}";
public static final String ADALITE_SEND = "/api/v2/txs/signed";
private int requestsCount = 0;
public static String lastNode;
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, AdaliteResponse adaliteResponse);
void onSuccess(String method, AdaliteResponseUtxo adaliteResponseUtxo);
void onSuccess(String method, List listResponse);
void onFail(String method, String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void requestData(String method, String wallet, String tx) {
requestsCount++;
String adaliteURL = "https://explorer2.adalite.io"; //TODO: make random selection
this.lastNode = adaliteURL; //TODO: show node instead of URL
Retrofit retrofitAdalite = new Retrofit.Builder()
.baseUrl(adaliteURL)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
AdaliteApi adaliteApi = retrofitAdalite.create(AdaliteApi.class);
switch (method) {
case ADALITE_ADDRESS:
Call<AdaliteResponse> addressCall = adaliteApi.adaliteAddress(wallet);
addressCall.enqueue(new Callback<AdaliteResponse>() {
@Override
public void onResponse(@NonNull Call<AdaliteResponse> call, @NonNull Response<AdaliteResponse> 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<AdaliteResponse> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
break;
case ADALITE_UNSPENT_OUTPUTS:
Call<AdaliteResponseUtxo> outputsCall = adaliteApi.adaliteUnspent("[\"" + wallet + "\"]");
outputsCall.enqueue(new Callback<AdaliteResponseUtxo>() {
@Override
public void onResponse(@NonNull Call<AdaliteResponseUtxo> call, @NonNull Response<AdaliteResponseUtxo> 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<AdaliteResponseUtxo> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
break;
case ADALITE_SEND:
Call<List> sendCall = adaliteApi.adaliteSend(new AdaliteBody(tx));
sendCall.enqueue(new Callback<List>() {
@Override
public void onResponse(@NonNull Call<List> call, @NonNull Response<List> 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<List> 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;
}
}
}

View file

@ -0,0 +1,126 @@
package com.tangem.data.network;
import android.util.Log;
import com.tangem.wallet.TangemContext;
import com.tangem.wallet.Transaction;
import com.tangem.wallet.binance.BinanceData;
import com.tangem.wallet.binance.client.BinanceDexApiRestClient;
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.encoding.message.TransactionRequestAssemblerExtSign;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DefaultObserver;
import io.reactivex.schedulers.Schedulers;
import okhttp3.RequestBody;
public class ServerApiBinance {
private static String TAG = ServerApiBinance.class.getSimpleName();
private ResponseListener responseListener;
public interface ResponseListener {
void onSuccess();
void onFail();
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void getBalance(TangemContext ctx, BinanceDexApiRestClient client) {
Log.i(TAG, "new getBalance request");
Observable<Account> balanceObservable = Observable.just(new Account())
.map(account -> client.getAccount(ctx.getCoinData().getWallet()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
balanceObservable.subscribe(new DefaultObserver<Account>() {
@Override
public void onNext(Account account) {
Log.i(TAG, "getBalance onNext");
// account = client.getAccount(ctx.getCoinData().getWallet());
BinanceData binanceData = (BinanceData) ctx.getCoinData();
for (Balance balance : account.getBalances()) {
if (balance.getSymbol().equals("BNB")) {
binanceData.setBalanceReceived(true);
binanceData.setBalance(balance.getFree());
break;
}
}
if (!binanceData.isBalanceReceived()) {
binanceData.setBalanceReceived(true);
binanceData.setBalance("0");
}
binanceData.setAccountNumber(account.getAccountNumber());
binanceData.setSequence(account.getSequence());
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "getBalance onError" + e.getMessage());
if (e.getMessage().contains("code=404")) {
((BinanceData)ctx.getCoinData()).setError404(true);
responseListener.onFail();
} else {
e.printStackTrace();
ctx.setError(e.getMessage());
responseListener.onFail();
}
}
@Override
public void onComplete() {
Log.i(TAG, "getBalance onComplete");
responseListener.onSuccess();
}
});
}
public void sendTransaction (byte[] txForSend, BinanceDexApiRestClient client) {
Log.i(TAG, "new sendTransaction request");
RequestBody requestBody = TransactionRequestAssemblerExtSign.createRequestBody(txForSend);
Observable<List<TransactionMetadata>> sendObservable = Observable.just(new ArrayList<>())
.map(metadatas -> client.broadcastNoWallet(requestBody, true))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
sendObservable.subscribe(new DefaultObserver<List<TransactionMetadata>>() {
@Override
public void onNext(List<TransactionMetadata> metadatas ) {
// RequestBody requestBody = TransactionRequestAssemblerExtSign.createRequestBody(txForSend);
// List<TransactionMetadata> metadatas = client.broadcastNoWallet(requestBody, true);
if (!metadatas.isEmpty() && metadatas.get(0).isOk()) {
responseListener.onSuccess();
} else {
Log.e(TAG, "Transaction send error");
responseListener.onFail();
}
}
@Override
public void onError(Throwable e) {
Log.e(TAG, "sendTransaction onError" + e.getMessage());
e.printStackTrace();
responseListener.onFail();
}
@Override
public void onComplete() {
Log.i(TAG, "sendTransaction onComplete");
}
});
}
}

View file

@ -0,0 +1,128 @@
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 blockchainID, String method, String wallet, String tx) {
requestsCount++;
String blockchain = blockchainID.toLowerCase();
BlockcypherApi blockcypherApi = App.Companion.getNetworkComponent().getRetrofitBlockcypher().create(BlockcypherApi.class);
switch (method) {
case BLOCKCYPHER_ADDRESS:
Call<BlockcypherResponse> addressCall = blockcypherApi.blockcypherAddress(blockchain, 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(blockchain);
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(blockchain, 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;
}
}
}

View file

@ -1,7 +1,7 @@
package com.tangem.data.network;
import android.annotation.SuppressLint;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import android.util.Log;
import com.tangem.App;
@ -24,19 +24,19 @@ public class ServerApiCommon {
public static final int ESTIMATE_FEE_PRIORITY = 2;
public static final int ESTIMATE_FEE_NORMAL = 3;
public static final int ESTIMATE_FEE_MINIMAL = 6;
private EstimateFeeListener estimateFeeListener;
private EstimatedFeeListener estimatedFeeListener;
public interface EstimateFeeListener {
public interface EstimatedFeeListener {
void onSuccess(int blockCount, String estimateFeeResponse);
void onFail(int blockCount, String message);
}
public void setEstimateFee(EstimateFeeListener listener) {
estimateFeeListener = listener;
public void setBtcEstimatedFeeListener(EstimatedFeeListener listener) {
estimatedFeeListener = listener;
}
public void estimateFee(int blockCount) {
EstimatefeeApi estimatefeeApi = App.getNetworkComponent().getRetrofitEstimatefee().create(EstimatefeeApi.class);
public void requestBtcEstimatedFee(int blockCount) {
EstimatefeeApi estimatefeeApi = App.Companion.getNetworkComponent().getRetrofitEstimatefee().create(EstimatefeeApi.class);
Call<String> call;
switch (blockCount) {
@ -60,17 +60,17 @@ public class ServerApiCommon {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
if (response.code() == 200) {
estimateFeeListener.onSuccess(blockCount, response.body());
Log.i(TAG, "estimateFee onResponse " + response.code() + " " + response.body());
estimatedFeeListener.onSuccess(blockCount, response.body());
Log.i(TAG, "requestBtcEstimatedFee onResponse " + response.code() + " " + response.body());
} else
estimateFeeListener.onFail(blockCount, response.body());
Log.e(TAG, "estimateFee onResponse " + response.code());
estimatedFeeListener.onFail(blockCount, response.body());
Log.e(TAG, "requestBtcEstimatedFee onResponse " + response.code());
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
estimateFeeListener.onFail(blockCount, t.getMessage());
Log.e(TAG, "estimateFee onFailure " + t.getMessage());
estimatedFeeListener.onFail(blockCount, t.getMessage());
Log.e(TAG, "requestBtcEstimatedFee onFailure " + t.getMessage());
}
});
}
@ -79,33 +79,51 @@ public class ServerApiCommon {
* HTTP
* Used in Crypto-currency course
*/
private RateInfoDataListener rateInfoDataListener;
private RateInfoListener rateInfoListener;
public interface RateInfoDataListener {
public interface RateInfoListener {
void onSuccess(RateInfoResponse rateInfoResponse);
void onFail(String message);
}
public void setRateInfoData(RateInfoDataListener listener) {
rateInfoDataListener = listener;
public void setRateInfoListener(RateInfoListener listener) {
rateInfoListener = listener;
}
@SuppressLint("CheckResult")
public void rateInfoData(String cryptoId) {
CoinmarketApi coinmarketApi = App.getNetworkComponent().getRetrofitCoinmarketcap().create(CoinmarketApi.class);
public void requestRateInfo(String cryptoId) {
CoinmarketApi coinmarketApi = App.Companion.getNetworkComponent().getRetrofitCoinmarketcap().create(CoinmarketApi.class);
coinmarketApi.getRateInfoList()
// Call<RateInfoResponse> call = coinmarketApi.getRateInfo(1, cryptoId);
//
// call.enqueue(new Callback<RateInfoResponse>() {
// @Override
// public void onResponse(@NonNull Call<RateInfoResponse> call, @NonNull Response<RateInfoResponse> response) {
// if (response.code() == 200) {
// rateInfoListener.onSuccess(response.body());
// Log.i(TAG, "coinmarketcap onResponse " + response.code());
// } else {
// rateInfoListener.onFail("Rate info error:" + String.valueOf(response.code()));
// Log.e(TAG, "coinmarketcap onResponse " + response.code());
// }
// }
//
// @Override
// public void onFailure(@NonNull Call<RateInfoResponse> call, @NonNull Throwable t) {
// rateInfoListener.onFail(String.valueOf(t.getMessage()));
// Log.e(TAG, "coinmarketcap onFailure " + t.getMessage());
// }
// });
coinmarketApi.getRateInfo(1, cryptoId)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(rateInfoModelList -> {
if (!rateInfoModelList.isEmpty()) {
for (RateInfoResponse rateInfoMode : rateInfoModelList) {
if (rateInfoMode.getId().equals(cryptoId)) {
rateInfoDataListener.onSuccess(rateInfoMode);
Log.i(TAG, "rateInfoData " + cryptoId + " onResponse " + "200");
}
}
} else
Log.e(TAG, "rateInfoData " + cryptoId + " onResponse " + "Empty");
.subscribe(rateInfoResponse -> {
if (rateInfoResponse.getData().getQuote().getUsd().getPrice() != null) {
rateInfoListener.onSuccess(rateInfoResponse);
Log.i(TAG, "coinmarketcap onResponse " + 200);
} else {
rateInfoListener.onFail("Rate info error: wrong response");
}
},
// handle error
Throwable::printStackTrace);
@ -126,7 +144,7 @@ public class ServerApiCommon {
}
public void requestLastVersion() {
UpdateVersionApi updateVersionApi = App.getNetworkComponent().getRetrofitGithubusercontent().create(UpdateVersionApi.class);
UpdateVersionApi updateVersionApi = App.Companion.getNetworkComponent().getRetrofitGitHubUserContent().create(UpdateVersionApi.class);
Call<ResponseBody> call = updateVersionApi.getLastVersion();
call.enqueue(new Callback<ResponseBody>() {

View file

@ -3,13 +3,12 @@ package com.tangem.data.network;
import android.util.Log;
import com.tangem.App;
import com.tangem.domain.wallet.TangemContext;
import com.tangem.wallet.TangemContext;
import com.tangem.data.Blockchain;
import com.tangem.domain.wallet.bch.BitcoinCashNode;
import com.tangem.domain.wallet.btc.BitcoinNode;
import com.tangem.domain.wallet.btc.BitcoinNodeTestNet;
import com.tangem.domain.wallet.ltc.LitecoinNode;
import com.tangem.tangemcard.reader.CardProtocol;
import com.tangem.wallet.bch.BitcoinCashNode;
import com.tangem.wallet.btc.BitcoinNode;
import com.tangem.wallet.btc.BitcoinNodeTestNet;
import com.tangem.wallet.ltc.LitecoinNode;
import com.tangem.wallet.R;
import java.io.BufferedReader;
@ -24,7 +23,6 @@ import java.net.InetSocketAddress;
import java.net.Socket;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
@ -47,22 +45,23 @@ import io.reactivex.schedulers.Schedulers;
/**
* Request processor for Electrum Api
* Every request live cycle:
* 1. In application create request and call {@link ServerApiElectrum}.electrumRequestData(..)
* 1. In application create request and call {@link ServerApiElectrum}.requestData(..)
* 2. Try send every request for max 4 times,
* 3. If all 4 times fail call DefaultObserver<ElectrumRequest>.onError (defined in .electrumRequestData(..)) and than
* {@link ElectrumRequestDataListener}.onFail(...) callback
* 3. If all 4 times fail call DefaultObserver<ElectrumRequest>.onError (defined in .requestData(..)) and than
* {@link ResponseListener}.onFail(...) callback
* Error can be acquired with {@link ElectrumRequest}.getError() method
* 4. If request network communication finished successfully then call DefaultObserver<ElectrumRequest>.onComplete (defined in .electrumRequestData) and than
* {@link ElectrumRequestDataListener}.onSuccess(...) callback
* 4. If request network communication finished successfully then call DefaultObserver<ElectrumRequest>.onComplete (defined in .requestData) and than
* {@link ResponseListener}.onSuccess(...) callback
*/
public class ServerApiElectrum {
public static final String ERROR_STARTS_WITH_CODE_32601 = "{\"code\":-32601,";
private static String TAG = ServerApiElectrum.class.getSimpleName();
/**
* TCP, SSL
* Used in BTC, BCH
*/
private ElectrumRequestDataListener electrumRequestDataListener;
private ResponseListener responseListener;
private String host;
private int port;
@ -76,7 +75,7 @@ public class ServerApiElectrum {
/**
* Interface for notification every request result
*/
public interface ElectrumRequestDataListener {
public interface ResponseListener {
/**
* Notify that request processing was successful
@ -94,8 +93,8 @@ public class ServerApiElectrum {
* Set notificaion listener
* @param listener
*/
public void setElectrumRequestData(ElectrumRequestDataListener listener) {
electrumRequestDataListener = listener;
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
@ -104,7 +103,7 @@ public class ServerApiElectrum {
* @param ctx
* @param electrumRequest
*/
public void electrumRequestData(TangemContext ctx, ElectrumRequest electrumRequest) {
public void requestData(TangemContext ctx, ElectrumRequest electrumRequest) {
requestsCount++;
Log.i(TAG, String.format("New request[%d]: %s", requestsCount,electrumRequest.getMethod()));
Observable<ElectrumRequest> checkElectrumDataObserver = Observable.just(electrumRequest)
@ -129,20 +128,20 @@ public class ServerApiElectrum {
@Override
public void onNext(ElectrumRequest v) {
if (electrumRequest.answerData != null) {
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onNext != null");
Log.i(TAG, "requestData " + electrumRequest.getMethod() + " onNext != null");
} else {
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onNext == null");
Log.e(TAG, "requestData " + electrumRequest.getMethod() + " onNext == null");
}
}
@Override
public void onError(Throwable e) {
requestsCount--;
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onError " + e.getMessage());
Log.e(TAG, "requestData " + electrumRequest.getMethod() + " onError " + e.getMessage());
Log.e(TAG, String.format("%d requests left in processing",requestsCount));
electrumRequest.setError(ctx.getString(R.string.cannot_obtain_data_from_blockchain));
//setErrorOccurred(e.getMessage());//;
electrumRequestDataListener.onFail(electrumRequest);
responseListener.onFail(electrumRequest);
}
/**
@ -152,16 +151,16 @@ public class ServerApiElectrum {
public void onComplete() {
requestsCount--;
if (electrumRequest.answerData != null) {
Log.i(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onComplete, answerData!=null");
Log.i(TAG, "requestData " + electrumRequest.getMethod() + " onComplete, answerData!=null");
} else {
Log.e(TAG, "electrumRequestData " + electrumRequest.getMethod() + " onComplete, answerData==null");
Log.e(TAG, "requestData " + electrumRequest.getMethod() + " onComplete, answerData==null");
}
Log.e(TAG, String.format("%d requests left in processing",requestsCount));
if (electrumRequest.answerData != null && electrumRequest.getError()==null) {
electrumRequestDataListener.onSuccess(electrumRequest);
responseListener.onSuccess(electrumRequest);
} else {
// if( error==null || error.isEmpty() ) setErrorOccurred(ctx.getString(R.string.cannot_obtain_data_from_blockchain));
electrumRequestDataListener.onFail(electrumRequest);
responseListener.onFail(electrumRequest);
}
}
@ -231,7 +230,7 @@ public class ServerApiElectrum {
private void doElectrumRequestTcp(ElectrumRequest electrumRequest, String host, int port) {
try {
Socket socket = App.getNetworkComponent().getSocket();
Socket socket = App.Companion.getNetworkComponent().getSocket();
socket.setSoTimeout(3000);
Log.i(TAG, "Start process "+electrumRequest.getMethod()+" @ "+host + ":" + port);
socket.connect(new InetSocketAddress(InetAddress.getByName(host), port));
@ -250,15 +249,21 @@ public class ServerApiElectrum {
electrumRequest.port = port;
if (electrumRequest.answerData != null) {
Log.i(TAG, ">> " + electrumRequest.answerData);
if( (electrumRequest.getError()!=null && electrumRequest.getError().startsWith(ERROR_STARTS_WITH_CODE_32601)) )
{
// method unknown error???
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain));
electrumRequest.answerData=null;
}
} else {
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
Log.i(TAG, ">> <NULL>");
}
} catch (ConnectException e) {
//e.printStackTrace();
//electrumRequestDataListener.onFail(e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
//responseListener.onFail(e.getMessage());
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
} finally {
Log.i(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " socket.close");
@ -269,13 +274,13 @@ public class ServerApiElectrum {
{
e.printStackTrace();
Log.e(TAG,"Can't close socket");
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
}
}
} catch (IOException e) {
//e.printStackTrace();
//electrumRequestDataListener.onFail(e.getMessage());
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
//responseListener.onFail(e.getMessage());
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
Log.e(TAG, "doElectrumRequestTcp " + electrumRequest.getMethod() + " IOException " + e.getMessage());
}
}
@ -312,14 +317,16 @@ public class ServerApiElectrum {
// install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
SSLSocket sslSocket;
Socket sslSocket = new Socket();
List<ElectrumRequest> result = new ArrayList<>();
Collections.addAll(result, electrumRequest);
try {
Log.i(TAG, host + " " + port);
sslSocket = (SSLSocket) sf.createSocket(host, port);
sslSocket.connect(new InetSocketAddress(host,port), 3000);
sslSocket.setSoTimeout(3000);
sslSocket = sf.createSocket(sslSocket, host, port, true);
try {
OutputStream os = sslSocket.getOutputStream();
OutputStreamWriter out = new OutputStreamWriter(os, "UTF-8");
@ -333,14 +340,20 @@ public class ServerApiElectrum {
electrumRequest.answerData = in.readLine();
if (electrumRequest.answerData != null) {
Log.i(TAG, ">> " + electrumRequest.answerData);
if( (electrumRequest.getError()!=null && electrumRequest.getError().startsWith(ERROR_STARTS_WITH_CODE_32601)) )
{
// method unknown error???
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain));
electrumRequest.answerData=null;
}
} else {
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_answer));
Log.i(TAG, ">> <NULL>");
}
} catch (ConnectException e) {
e.printStackTrace();
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_no_connection));
Log.e(TAG, "doElectrumRequestSsl " + electrumRequest.getMethod() + " ConnectException " + e.getMessage());
} finally {
Log.i(TAG, "doElectrumRequestSsl " + electrumRequest.getMethod() + " socket.close");
@ -349,7 +362,7 @@ public class ServerApiElectrum {
}
catch (Exception e)
{
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
e.printStackTrace();
Log.e(TAG, "Can't close ssl socket");
}
@ -357,11 +370,11 @@ public class ServerApiElectrum {
} catch (IOException e) {
e.printStackTrace();
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain_communication_error));
Log.e(TAG, "doElectrumRequestSsl " + electrumRequest.getMethod() + " IOException " + e.getMessage());
}
} catch (NoSuchAlgorithmException | KeyManagementException e) {
electrumRequest.setError(App.getInstance().getString(R.string.cannot_obtain_data_from_blockchain));
electrumRequest.setError(App.Companion.getInstance().getString(R.string.cannot_obtain_data_from_blockchain));
Log.e(TAG, e.getMessage());
}
}

View file

@ -1,6 +1,6 @@
package com.tangem.data.network;
import android.support.annotation.NonNull;
import androidx.annotation.NonNull;
import android.util.Log;
import com.tangem.App;
@ -38,21 +38,21 @@ public class ServerApiInfura {
return requestsCount <= 0;
}
private InfuraBodyListener infuraBodyListener;
private ResponseListener responseListener;
public interface InfuraBodyListener {
public interface ResponseListener {
void onSuccess(String method, InfuraResponse infuraResponse);
void onFail(String method, String message);
}
public void setInfuraResponse(InfuraBodyListener listener) {
infuraBodyListener = listener;
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void infura(String method, int id, String wallet, String contract, String tx) {
public void requestData(String method, int id, String wallet, String contract, String tx) {
requestsCount++;
InfuraApi infuraApi = App.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class);
InfuraApi infuraApi = App.Companion.getNetworkComponent().getRetrofitInfura().create(InfuraApi.class);
InfuraBody infuraBody;
switch (method) {
@ -86,18 +86,18 @@ public class ServerApiInfura {
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> response) {
if (response.code() == 200) {
requestsCount--;
infuraBodyListener.onSuccess(method, response.body());
Log.i(TAG, "infura " + method + " onResponse " + response.code());
responseListener.onSuccess(method, response.body());
Log.i(TAG, "requestData " + method + " onResponse " + response.code());
} else {
infuraBodyListener.onFail(method, String.valueOf(response.code()));
Log.e(TAG, "infura " + method + " onResponse " + response.code());
responseListener.onFail(method, String.valueOf(response.code()));
Log.e(TAG, "requestData " + method + " onResponse " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<InfuraResponse> call, @NonNull Throwable t) {
infuraBodyListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "infura " + method + " onFailure " + t.getMessage());
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
}

View file

@ -0,0 +1,129 @@
package com.tangem.data.network;
import android.util.Log;
import com.tangem.data.network.model.InsightBody;
import com.tangem.data.network.model.InsightResponse;
import java.util.List;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ServerApiInsight {
private static String TAG = ServerApiInsight.class.getSimpleName();
public static final String INSIGHT_ADDRESS = "/addr/{address}";
public static final String INSIGHT_UNSPENT_OUTPUTS = "/addr/{address}/utxo";
public static final String INSIGHT_TRANSACTION = "/rawtx/{txId}";
public static final String INSIGHT_FEE = "/utils/estimatefee?nbBlocks=2,3,6";
public static final String INSIGHT_SEND = "/tx/send";
private int requestsCount = 0;
public static String lastNode;
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, InsightResponse insightResponse);
void onSuccess(String method, List<InsightResponse> utxoList);
void onFail(String method, String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void requestData(String method, String wallet, String tx) {
requestsCount++;
String insightURL = "http://130.185.109.17:3001/insigth-api"; //TODO: make random selection
this.lastNode = insightURL; //TODO: show node instead of URL
Retrofit retrofitInsight = new Retrofit.Builder()
.baseUrl(insightURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// InsightApi insightApi = App.getNetworkComponent().getRetrofitInsight(insightURL).create(InsightApi.class);
InsightApi insightApi = retrofitInsight.create(InsightApi.class);
if (method.equals(INSIGHT_UNSPENT_OUTPUTS)) {
Call<List<InsightResponse>> call = insightApi.insightUnspent(wallet);
call.enqueue(new Callback<List<InsightResponse>>() {
@Override
public void onResponse(@NonNull Call<List<InsightResponse>> call, @NonNull Response<List<InsightResponse>> 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<List<InsightResponse>> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
} else {
Call<InsightResponse> call;
switch (method) {
case INSIGHT_ADDRESS:
call = insightApi.insightAddress(wallet);
break;
case INSIGHT_TRANSACTION:
call = insightApi.insightTransaction(tx);
break;
case INSIGHT_FEE:
call = insightApi.insightFee();
break;
case INSIGHT_SEND:
call = insightApi.insightSend(new InsightBody(tx));
break;
default:
call = insightApi.insightAddress(wallet);
break;
}
call.enqueue(new Callback<InsightResponse>() {
@Override
public void onResponse(@NonNull Call<InsightResponse> call, @NonNull Response<InsightResponse> 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<InsightResponse> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
}
}
}

View file

@ -0,0 +1,105 @@
package com.tangem.data.network;
import androidx.annotation.NonNull;
import android.util.Log;
import com.tangem.App;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ServerApiMatic {
private static String TAG = ServerApiMatic.class.getSimpleName();
/**
* HTTP
* Infura
* <p>
* eth_getBalance
* eth_getTransactionCount
* eth_call
* eth_sendRawTransaction
* eth_gasPrice
*/
public static final String MATIC_ETH_GET_BALANCE = "eth_getBalance";
public static final String MATIC_ETH_GET_TRANSACTION_COUNT = "eth_getTransactionCount";
public static final String MATIC_ETH_GET_PENDING_COUNT = "eth_getPendingCount";
public static final String MATIC_ETH_CALL = "eth_call";
public static final String MATIC_ETH_SEND_RAW_TRANSACTION = "eth_sendRawTransaction";
public static final String MATIC_ETH_GAS_PRICE = "eth_gasPrice";
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, InfuraResponse infuraResponse);
void onFail(String method, String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void requestData(String method, int id, String wallet, String contract, String tx) {
requestsCount++;
MaticApi maticApi = App.Companion.getNetworkComponent().getRetrofitMaticTesnet().create(MaticApi.class);
InfuraBody infuraBody;
switch (method) {
case MATIC_ETH_GET_BALANCE:
case MATIC_ETH_GET_TRANSACTION_COUNT:
infuraBody = new InfuraBody(method, new String[]{wallet, "latest"}, id);
break;
case MATIC_ETH_GET_PENDING_COUNT:
infuraBody = new InfuraBody(MATIC_ETH_GET_TRANSACTION_COUNT, new String[]{wallet, "pending"}, id);
break;
case MATIC_ETH_CALL:
String address = wallet.substring(2);
infuraBody = new InfuraBody(method, new Object[]{new InfuraBody.EthCallParams("0x70a08231000000000000000000000000" + address, contract), "latest"}, id);
break;
case MATIC_ETH_SEND_RAW_TRANSACTION:
infuraBody = new InfuraBody(method, new String[]{tx}, id);
break;
case MATIC_ETH_GAS_PRICE:
infuraBody = new InfuraBody(method, id);
break;
default:
infuraBody = new InfuraBody();
}
Call<InfuraResponse> call = maticApi.matic(infuraBody);
call.enqueue(new Callback<InfuraResponse>() {
@Override
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> 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<InfuraResponse> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
}
}

View file

@ -0,0 +1,117 @@
package com.tangem.data.network;
import android.util.Log;
import com.tangem.data.network.model.RippleBody;
import com.tangem.data.network.model.RippleResponse;
import java.util.HashMap;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ServerApiRipple {
private static String TAG = ServerApiRipple.class.getSimpleName();
public static final String RIPPLE_ACCOUNT_INFO = "account_info";
public static final String RIPPLE_ACCOUNT_UNCONFIRMED = "account_unconfirmed";
public static final String RIPPLE_SUBMIT = "submit";
public static final String RIPPLE_FEE = "fee";
public static final String RIPPLE_SERVER_STATE = "server_state";
private int requestsCount = 0;
public static String lastNode;
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, RippleResponse rippleResponse);
void onFail(String method, String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void requestData(String method, String wallet, String tx) {
requestsCount++;
String rippleURL = "https://s1.ripple.com:51234"; //TODO: make random selection
lastNode = rippleURL; //TODO: show node instead of URL
Retrofit retrofitRipple = new Retrofit.Builder()
.baseUrl(rippleURL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RippleApi rippleApi = retrofitRipple.create(RippleApi.class);
RippleBody rippleBody;
HashMap<String, String> paramsMap;
switch (method) {
case RIPPLE_ACCOUNT_INFO:
paramsMap = new HashMap<>();
paramsMap.put("account", wallet);
paramsMap.put("ledger_index", "validated");
rippleBody = new RippleBody(method, paramsMap);
break;
case RIPPLE_ACCOUNT_UNCONFIRMED:
paramsMap = new HashMap<>();
paramsMap.put("account", wallet);
paramsMap.put("ledger_index", "current");
// paramsMap.put("queue", "true"); TODO: make queue check if needed
rippleBody = new RippleBody(RIPPLE_ACCOUNT_INFO, paramsMap);
break;
case RIPPLE_SERVER_STATE:
rippleBody = new RippleBody(method, new HashMap<>());
break;
case RIPPLE_FEE:
rippleBody = new RippleBody(method, new HashMap<>());
break;
case RIPPLE_SUBMIT:
paramsMap = new HashMap<>();
paramsMap.put("tx_blob", tx);
rippleBody = new RippleBody(method, paramsMap);
break;
default:
rippleBody = new RippleBody();
}
Call<RippleResponse> call = rippleApi.ripple(rippleBody);
call.enqueue(new Callback<RippleResponse>() {
@Override
public void onResponse(@NonNull Call<RippleResponse> call, @NonNull Response<RippleResponse> 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<RippleResponse> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
}
}

View file

@ -0,0 +1,105 @@
package com.tangem.data.network;
import androidx.annotation.NonNull;
import android.util.Log;
import com.tangem.App;
import com.tangem.data.network.model.InfuraBody;
import com.tangem.data.network.model.InfuraResponse;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class ServerApiRootstock {
private static String TAG = ServerApiRootstock.class.getSimpleName();
/**
* HTTP
* Rootstock
* <p>
* eth_getBalance
* eth_getTransactionCount
* eth_call
* eth_sendRawTransaction
* eth_gasPrice
*/
public static final String ROOTSTOCK_ETH_GET_BALANCE = "eth_getBalance";
public static final String ROOTSTOCK_ETH_GET_TRANSACTION_COUNT = "eth_getTransactionCount";
public static final String ROOTSTOCK_ETH_GET_PENDING_COUNT = "eth_getPendingCount";
public static final String ROOTSTOCK_ETH_CALL = "eth_call";
public static final String ROOTSTOCK_ETH_SEND_RAW_TRANSACTION = "eth_sendRawTransaction";
public static final String ROOTSTOCK_ETH_GAS_PRICE = "eth_gasPrice";
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, InfuraResponse infuraResponse);
void onFail(String method, String message);
}
public void setResponseListener(ResponseListener listener) {
responseListener = listener;
}
public void requestData(String method, int id, String wallet, String contract, String tx) {
requestsCount++;
RootstockApi rootstockApi = App.Companion.getNetworkComponent().getRetrofitRootstock().create(RootstockApi.class);
InfuraBody infuraBody;
switch (method) {
case ROOTSTOCK_ETH_GET_BALANCE:
case ROOTSTOCK_ETH_GET_TRANSACTION_COUNT:
infuraBody = new InfuraBody(method, new String[]{wallet, "latest"}, id);
break;
case ROOTSTOCK_ETH_GET_PENDING_COUNT:
infuraBody = new InfuraBody(ROOTSTOCK_ETH_GET_TRANSACTION_COUNT, new String[]{wallet, "pending"}, id);
break;
case ROOTSTOCK_ETH_CALL:
String address = wallet.substring(2);
infuraBody = new InfuraBody(method, new Object[]{new InfuraBody.EthCallParams("0x70a08231000000000000000000000000" + address, contract), "latest"}, id);
break;
case ROOTSTOCK_ETH_SEND_RAW_TRANSACTION:
infuraBody = new InfuraBody(method, new String[]{tx}, id);
break;
case ROOTSTOCK_ETH_GAS_PRICE:
infuraBody = new InfuraBody(method, id);
break;
default:
infuraBody = new InfuraBody();
}
Call<InfuraResponse> call = rootstockApi.rootstock(infuraBody);
call.enqueue(new Callback<InfuraResponse>() {
@Override
public void onResponse(@NonNull Call<InfuraResponse> call, @NonNull Response<InfuraResponse> 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<InfuraResponse> call, @NonNull Throwable t) {
responseListener.onFail(method, String.valueOf(t.getMessage()));
Log.e(TAG, "requestData " + method + " onFailure " + t.getMessage());
}
});
}
}

View file

@ -2,9 +2,14 @@ package com.tangem.data.network;
class ServerURL {
static final String API_TANGEM = "https://verify.tangem.com/";
static final String API_COINMARKETCAP = "https://api.coinmarketcap.com/";
static final String API_INFURA = "https://mainnet.infura.io/v3/";
static final String API_COINMARKETCAP = "https://pro-api.coinmarketcap.com/";
static final String API_INFURA = "https://mainnet.infura.io/";
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_BLOCKCYPHER = "https://api.blockcypher.com/";
static final String API_BINANCE = "https://dex.binance.org/";
static final String API_BINANCE_TESTNET = "https://testnet-dex.binance.org/";
static final String API_MATIC_TESTNET = "https://testnet2.matic.network";
static final String API_STELLAR = "https://horizon-testnet.stellar.org";
}

View file

@ -0,0 +1,9 @@
package com.tangem.data.network.model;
public class AdaliteBody {
private String signedTx;
public AdaliteBody(String signedTx) {
this.signedTx = signedTx;
}
}

View file

@ -0,0 +1,45 @@
package com.tangem.data.network.model
import com.google.gson.annotations.SerializedName
data class AdaliteResponse(
@SerializedName("Right")
var right: AdaliteAddressData? = null
)
data class AdaliteResponseUtxo(
@SerializedName("Right")
var right: List<AdaliteUtxoData>
)
data class AdaliteAddressData(
@SerializedName("caAddress")
var caAddress: String? = null,
@SerializedName("caBalance")
var caBalance: AdaliteCoins? = null,
@SerializedName("caTxList")
var caTxList: List<AdaliteTxData>
)
data class AdaliteCoins(
@SerializedName("getCoin")
var getCoin: Long? = null
)
data class AdaliteUtxoData(
@SerializedName("cuId")
var cuId: String? = null,
@SerializedName("cuOutIndex")
var cuOutIndex: Int? = null,
@SerializedName("cuCoins")
var cuCoins: AdaliteCoins? = null
)
data class AdaliteTxData(
@SerializedName("ctbId")
var ctbId: String? = null
)

View file

@ -0,0 +1,16 @@
package com.tangem.data.network.model
import com.google.gson.annotations.SerializedName
data class BinanceFees(
@SerializedName("fixed_fee_params")
var fixed_fee_params: BinanceFixedFee? = null
)
data class BinanceFixedFee(
@SerializedName("msg_type")
var msg_type: String? = null,
@SerializedName("fee")
var fee: Int? = null
)

View file

@ -0,0 +1,9 @@
package com.tangem.data.network.model;
public class BlockcypherBody {
private String tx;
public BlockcypherBody(String tx) {
this.tx = tx;
}
}

View file

@ -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
)

View file

@ -4,6 +4,7 @@ public class InfuraBody {
private String method;
private Object[] params;
private int id;
private String jsonrpc = "2.0";
public InfuraBody() {
}

View file

@ -10,8 +10,8 @@ data class InfuraResponse(
var id: Int? = null,
@SerializedName("result")
var result: String = "",
var result: String? = null,
@SerializedName("error")
var error: String = ""
var error: Object
)

View file

@ -0,0 +1,9 @@
package com.tangem.data.network.model;
public class InsightBody {
private String rawtx;
public InsightBody(String rawtx){
this.rawtx = rawtx;
}
}

View file

@ -0,0 +1,38 @@
package com.tangem.data.network.model
import com.google.gson.annotations.SerializedName
data class InsightResponse(
@SerializedName("balanceSat")
var balanceSat: Long? = null,
@SerializedName("unconfirmedBalanceSat")
var unconfirmedBalanceSat: Long? = null,
@SerializedName("addrStr")
var addrStr: String = "",
@SerializedName("txid")
var txid: String = "",
@SerializedName("satoshis")
var satoshis: Long? = null,
@SerializedName("height")
var height: Int? = null,
@SerializedName("2")
var fee2: String = "",
@SerializedName("3")
var fee3: String = "",
@SerializedName("6")
var fee6: String = "",
@SerializedName("rawtx")
var rawtx: String = "",
@SerializedName("error")
var error: String = ""
)

View file

@ -1,76 +1,23 @@
package com.tangem.data.network.model
import android.os.Parcelable
import com.google.gson.annotations.SerializedName
import kotlinx.android.parcel.Parcelize
@Parcelize
data class RateInfoResponse(
@SerializedName(ID)
var id: String = "",
@SerializedName("data")
var data: RateData? = null
)
@SerializedName(NAME)
var name: String = "",
data class RateData(
@SerializedName("quote")
var quote: Quote? = null
)
@SerializedName(SYMBOL)
var symbol: String = "",
data class Quote(
@SerializedName("USD")
var usd: CurrencyRate? = null
)
@SerializedName(RANK)
var rank: String = "",
@SerializedName(PRICE_USD)
var priceUsd: String = "",
@SerializedName(PRICE_BTC)
var priceBtc: String = "",
@SerializedName(VOLUME_USD_24H)
var volumeUsd24h: String = "",
@SerializedName(MARKET_CAP_USD)
var marketCapUsd: String = "",
@SerializedName(AVAILABLE_SUPPLY)
var availableSupply: String = "",
@SerializedName(TOTAL_SUPPLY)
var totalSupply: String = "",
@SerializedName(MAX_SUPPLY)
var maxSupply: String = "",
@SerializedName(PERCENT_CHANGE_1H)
var percentChange1h: String = "",
@SerializedName(PERCENT_CHANGE_24H)
var percentChange24h: String = "",
@SerializedName(PERCENT_CHANGE_7H)
var percentChange7h: String = "",
@SerializedName(LAST_UPDATED)
var lastUpdated: String = ""
) : Parcelable {
companion object {
val TAG: String = RateInfoResponse::class.java.simpleName
const val ID = "id"
const val NAME = "name"
const val SYMBOL = "symbol"
const val RANK = "rank"
const val PRICE_USD = "price_usd"
const val PRICE_BTC = "price_btc"
const val VOLUME_USD_24H = "24h_volume_usd"
const val MARKET_CAP_USD = "market_cap_usd"
const val AVAILABLE_SUPPLY = "available_supply"
const val TOTAL_SUPPLY = "total_supply"
const val MAX_SUPPLY = "max_supply"
const val PERCENT_CHANGE_1H = "percent_change_1h"
const val PERCENT_CHANGE_24H = "percent_change_24h"
const val PERCENT_CHANGE_7H = "percent_change_7d"
const val LAST_UPDATED = "last_updated"
}
}
data class CurrencyRate(
@SerializedName("price")
var price: Float? = null
)

View file

@ -0,0 +1,24 @@
package com.tangem.data.network.model;
import java.util.ArrayList;
import java.util.HashMap;
public class RippleBody {
private String method;
private ArrayList<HashMap<String,String>> params;
public RippleBody() {
}
//for RIPPLE_FEE
public RippleBody(String method) {
this.method = method;
}
public RippleBody(String method, HashMap<String,String> paramsMap) {
this.method = method;
ArrayList<HashMap<String, String>> paramsList = new ArrayList<>();
paramsList.add(paramsMap);
this.params = paramsList;
}
}

View file

@ -0,0 +1,78 @@
package com.tangem.data.network.model
import com.google.gson.annotations.SerializedName
data class RippleResponse(
@SerializedName("result")
var result: RippleResult? = null
)
data class RippleResult(
@SerializedName("account_data")
var account_data: RippleAccountData? = null,
@SerializedName("validated")
var validated: Boolean? = null,
//for RIPPLE_FEE
@SerializedName("drops")
var drops: RippleFeeDrops? = null,
//for RIPPLE_SUBMIT
@SerializedName("engine_result_code")
var engine_result_code: Int? = null,
//for RIPPLE_SUBMIT
@SerializedName ("engine_result_message")
var engine_result_message: String? = null,
//for RIPPLE_SUBMIT
@SerializedName("error")
var error: String? = null,
//for RIPPLE_SUBMIT
@SerializedName("error_exception")
var error_exception: String? = null,
//for RIPPLE_SERVER_STATE
@SerializedName("state")
var state: RippleState? = null,
//for "Account not found error"
@SerializedName("error_code")
var error_code: Int? = null
)
data class RippleAccountData(
@SerializedName("Account")
var account: String? = null,
@SerializedName("Balance")
var balance: String? = null,
@SerializedName("Sequence")
var sequence: Long? = null
)
data class RippleFeeDrops(
//enough to put tx to queue
@SerializedName("minimum_fee")
var minimum_fee: String? = null,
//enough to put tx to current ledger
@SerializedName("open_ledger_fee")
var open_ledger_fee: String? = null,
@SerializedName("median_fee")
var median_fee: String? = null
)
data class RippleState(
@SerializedName("validated_ledger")
var validated_ledger: RippleLedger? = null
)
data class RippleLedger(
@SerializedName("reserve_base")
var reserve_base: Long? = null
)