Updated on 2026-08-14
This commit is contained in:
parent
22d155e526
commit
b1134eb19e
17 changed files with 3029 additions and 7 deletions
327
app/src/main/java/com/tangem/data/network/Cryptonit.java
Normal file
327
app/src/main/java/com/tangem/data/network/Cryptonit.java
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.internal.LinkedTreeMap;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.HttpException;
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
//import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.http.Body;
|
||||
import retrofit2.http.Header;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.Multipart;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Part;
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Used in Cryptonit service
|
||||
*/
|
||||
public class Cryptonit {
|
||||
private static final String SERVER_URL = "https://www.cryptonit.net:443/gateway/";
|
||||
|
||||
private static class Method {
|
||||
public static final String AUTHENTICATE = SERVER_URL + "public/authenticate";
|
||||
public static final String BALANCE = SERVER_URL + "private/balance";
|
||||
public static final String WITHDRAW_COINS = SERVER_URL + "private/withdrawCoins";
|
||||
}
|
||||
|
||||
public static class Model {
|
||||
|
||||
static class Authenticate
|
||||
{
|
||||
public static class Request
|
||||
{
|
||||
public String username;
|
||||
public String password;
|
||||
}
|
||||
public static class Response
|
||||
{
|
||||
boolean success;
|
||||
String[] missing_authenticators;
|
||||
public Object[] infos;
|
||||
public Object[] warnings;
|
||||
public Object[] errors;
|
||||
AuthenticationResult results;
|
||||
}
|
||||
|
||||
static class AuthenticationResult {
|
||||
// token (string): authentication token,
|
||||
// nick (string),
|
||||
// stayLoggedIn (boolean),
|
||||
// integer lastLogin (integer): JavaScript time OR NEVER for first login,
|
||||
// preferredLanguage (string) = ['en' or 'de']
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Balance {
|
||||
static class Request {
|
||||
String[] currencies;
|
||||
}
|
||||
public static class Response {
|
||||
public boolean success;
|
||||
public Object[] infos;
|
||||
public Object[] warnings;
|
||||
public Object[] errors;
|
||||
public BalanceResult[] results;
|
||||
|
||||
public static class BalanceResult {
|
||||
public String currency;
|
||||
public double balance;
|
||||
public String receiveAddress; //the current address to receive funds for this account, if available,
|
||||
public boolean fiat; // Is this a FIAT currency? If false, this is a CRYPTO currency.,
|
||||
public Object[] unprocessedTransactions; // (array, optional): list of unprocessed transactions, if pass field withTransactions
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class WithdrawCoins {
|
||||
public static class Request {
|
||||
public String currency;
|
||||
public Double amount;
|
||||
String toAddress;
|
||||
Double includeMinerFee;
|
||||
String password;
|
||||
}
|
||||
public static class Response {
|
||||
public Boolean success;
|
||||
public String[] missing_authenticators;
|
||||
public Object[] infos;
|
||||
public Object[] warnings;
|
||||
public Object[] errors;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Api {
|
||||
@Headers("Content-Type: application/json")
|
||||
@POST(Method.AUTHENTICATE)
|
||||
Call<Model.Authenticate.Response> authenticate(@Body Model.Authenticate.Request request);
|
||||
|
||||
@Headers("Content-Type: application/json")
|
||||
@POST(Method.BALANCE)
|
||||
Observable<Model.Balance.Response> getBalance(@Header("Auth-Token") String authToken, @Body Model.Balance.Request request);
|
||||
|
||||
@Headers("Content-Type: application/json")
|
||||
@POST(Method.WITHDRAW_COINS)
|
||||
Observable<Model.WithdrawCoins.Response> withdrawCoins(@Header("Auth-Token") String authToken, @Body Model.WithdrawCoins.Request request);
|
||||
}
|
||||
|
||||
private Api api = null;
|
||||
private BalanceListener balanceListener;
|
||||
private WithdrawalListener withdrawalListener;
|
||||
private ErrorListener errorListener;
|
||||
private Context context;
|
||||
private String authToken;
|
||||
|
||||
public Cryptonit(Context context) {
|
||||
this.context = context;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
username = sp.getString(context.getResources().getString(R.string.key_cryptonit_username), "");
|
||||
password = sp.getString(context.getResources().getString(R.string.key_cryptonit_password), "");
|
||||
fee = sp.getString(context.getResources().getString(R.string.key_cryptonit_fee), "0.0");
|
||||
}
|
||||
|
||||
public String username;
|
||||
public String password;
|
||||
private String fee;
|
||||
|
||||
public String getFee() {
|
||||
return fee;
|
||||
}
|
||||
|
||||
public void setFee(String value)
|
||||
{
|
||||
fee=value;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
sp.edit()
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_fee), fee)
|
||||
.apply();
|
||||
}
|
||||
|
||||
public Boolean haveAccountInfo() {
|
||||
return !username.isEmpty() && !password.isEmpty();
|
||||
}
|
||||
|
||||
public void saveAccountInfo() {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
sp.edit()
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_username), username)
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_password), password)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
||||
public interface BalanceListener {
|
||||
void onBalanceData(Model.Balance.Response response);
|
||||
}
|
||||
|
||||
public interface WithdrawalListener {
|
||||
void onWithdrawalComplete(Model.WithdrawCoins.Response response);
|
||||
}
|
||||
|
||||
public interface ErrorListener {
|
||||
void onError(Throwable throwable);
|
||||
}
|
||||
|
||||
public void setBalanceListener(BalanceListener listener) {
|
||||
balanceListener = listener;
|
||||
}
|
||||
|
||||
public void setWithdrawalListener(WithdrawalListener listener) {
|
||||
withdrawalListener = listener;
|
||||
}
|
||||
|
||||
public void setErrorListener(ErrorListener listener) {
|
||||
errorListener = listener;
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestBalance(String currency) {
|
||||
|
||||
initApi();
|
||||
|
||||
// Log.e("CRYPTONIT2", "username: " + username);
|
||||
// Log.e("CRYPTONIT2", "password: " + password);
|
||||
// Log.e("CRYPTONIT2", "auth-token: " + authToken);
|
||||
|
||||
Model.Balance.Request request=new Model.Balance.Request();
|
||||
request.currencies=new String[] {currency};
|
||||
api.getBalance(authToken, request)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(balanceModel -> balanceListener.onBalanceData(balanceModel),
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestWithdrawCoins(String currency, Double amount, String address) {
|
||||
|
||||
initApi();
|
||||
|
||||
// Log.e("CRYPTONIT2", "username: " + username);
|
||||
// Log.e("CRYPTONIT2", "password: " + password);
|
||||
// Log.e("CRYPTONIT2", "auth-token: " + authToken);
|
||||
|
||||
Model.WithdrawCoins.Request request=new Model.WithdrawCoins.Request();
|
||||
request.currency=currency;
|
||||
request.amount=amount;
|
||||
request.toAddress=address;
|
||||
request.includeMinerFee=Double.parseDouble(fee);
|
||||
request.password=password;
|
||||
|
||||
api.withdrawCoins(authToken, request)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
if (response.success != null && response.success)
|
||||
withdrawalListener.onWithdrawalComplete(response);
|
||||
else {
|
||||
errorListener.onError(new Exception(((LinkedTreeMap) response.errors[0]).entrySet().toArray()[0].toString()));
|
||||
}
|
||||
},
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
private void FireError(Throwable e) throws IOException {
|
||||
if (e.getClass() == HttpException.class && ((HttpException) e).code() == 500) {
|
||||
JsonObject jsonObject = new JsonParser().parse(((HttpException) e).response().errorBody().string()).getAsJsonObject();
|
||||
errorListener.onError(new Exception(e.getMessage() + ": " + jsonObject.get("errors").getAsString()));
|
||||
// if (jsonObject.get("reason").getAsString().equals("Invalid nonce")) nonce += 1000;
|
||||
} else {
|
||||
errorListener.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initApi() {
|
||||
|
||||
if (api != null) return;
|
||||
|
||||
// HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
// logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient httpClient = new OkHttpClient.Builder().
|
||||
// addInterceptor(logging).
|
||||
addInterceptor(new AuthorizationInterceptor()).build();
|
||||
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl(SERVER_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.client(httpClient)
|
||||
.build();
|
||||
|
||||
api = retrofit.create(Api.class);
|
||||
}
|
||||
|
||||
public class AuthorizationInterceptor implements Interceptor {
|
||||
|
||||
AuthorizationInterceptor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request mainRequest=chain.request();
|
||||
|
||||
if( !mainRequest.url().toString().endsWith("authenticate")&& authToken==null )
|
||||
{
|
||||
Model.Authenticate.Request authRequest=new Model.Authenticate.Request();
|
||||
authRequest.username=username;
|
||||
authRequest.password=password;
|
||||
retrofit2.Response<Model.Authenticate.Response> authResponse=api.authenticate(authRequest).execute();
|
||||
if( authResponse.isSuccessful() && authResponse.body().success)
|
||||
{
|
||||
String newToken = authResponse.headers().get("auth-token");
|
||||
if (newToken != null) {
|
||||
authToken = newToken;
|
||||
}
|
||||
}else{
|
||||
throw new IOException("Authentication error: "+authResponse.message());
|
||||
}
|
||||
}
|
||||
|
||||
if( authToken!=null ) {
|
||||
mainRequest = mainRequest.newBuilder().addHeader("auth-token", authToken).build();
|
||||
}
|
||||
Response mainResponse = chain.proceed(mainRequest);
|
||||
if (!mainResponse.isSuccessful()) {
|
||||
authToken=null;
|
||||
}
|
||||
return mainResponse;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,283 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
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.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.MediaType;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.RequestBody;
|
||||
//import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.http.Headers;
|
||||
import retrofit2.http.Multipart;
|
||||
import retrofit2.http.POST;
|
||||
import retrofit2.http.Part;
|
||||
import retrofit2.http.Path;
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Used in Cryptonit_OtherAPI service
|
||||
*/
|
||||
public class Cryptonit_OtherAPI {
|
||||
private static final String SERVER_URL = "https://api.cryptonit.net/api/";
|
||||
|
||||
private static class Method {
|
||||
public static final String BALANCE = SERVER_URL + "balance/{cryptoCurrency}%2F{fiatCurrency}";
|
||||
public static final String CRYPTO_WITHDRAWAL = SERVER_URL + "crypto_withdrawal/";
|
||||
}
|
||||
|
||||
public static class Response {
|
||||
public static class Balance{
|
||||
@SerializedName("btc_balance")
|
||||
public String btc_balance;
|
||||
@SerializedName("eur_balance")
|
||||
public String eur_balance;
|
||||
@SerializedName("eth_balance")
|
||||
public String eth_balance;
|
||||
@SerializedName("etn_balance")
|
||||
public String etn_balance;
|
||||
@SerializedName("btc_reserved")
|
||||
public String btc_reserved;
|
||||
@SerializedName("eur_reserved")
|
||||
public String eur_reserved;
|
||||
@SerializedName("eth_reserved")
|
||||
public String eth_reserved;
|
||||
@SerializedName("etn_reserved")
|
||||
public String etn_reserved;
|
||||
@SerializedName("btc_available")
|
||||
public String btc_available;
|
||||
@SerializedName("eur_available")
|
||||
public String eur_available;
|
||||
@SerializedName("eth_available")
|
||||
public String eth_available;
|
||||
@SerializedName("etn_available")
|
||||
public String etn_available;
|
||||
@SerializedName("btceur_fee")
|
||||
public String btceur_fee;
|
||||
@SerializedName("etheur_fee")
|
||||
public String etheur_fee;
|
||||
@SerializedName("etnbtc_fee")
|
||||
public String etnbtc_fee;
|
||||
@SerializedName("fee")
|
||||
public String fee;
|
||||
}
|
||||
|
||||
public static class CryptoWithdrawal {
|
||||
@SerializedName("success")
|
||||
public Boolean success;
|
||||
@SerializedName("status")
|
||||
public String status;
|
||||
@SerializedName("reason")
|
||||
public Object reason;
|
||||
}
|
||||
}
|
||||
|
||||
public interface Api {
|
||||
@Multipart
|
||||
@Headers("accept: multipart/form-data")
|
||||
@POST(Method.BALANCE)
|
||||
Observable<Response.Balance> getBalance(
|
||||
@Path("cryptoCurrency") String cryptoCurrency, @Path("fiatCurrency") String fiatCurrency,
|
||||
@Part(value = "key") RequestBody key, @Part("signature") RequestBody signature, @Part("nonce") RequestBody nonce);
|
||||
|
||||
@Multipart
|
||||
@Headers("accept: multipart/form-data")
|
||||
@POST(Method.CRYPTO_WITHDRAWAL)
|
||||
Observable<Response.CryptoWithdrawal> cryptoWithdrawal(
|
||||
@Part(value = "currency") RequestBody currency, @Part("amount") RequestBody amount, @Part("address") RequestBody address,
|
||||
@Part(value = "key") RequestBody key, @Part("signature") RequestBody signature, @Part("nonce") RequestBody nonce);
|
||||
}
|
||||
|
||||
private Api api = null;
|
||||
private BalanceListener balanceListener;
|
||||
private WithdrawalListener withdrawalListener;
|
||||
private ErrorListener errorListener;
|
||||
private Context context;
|
||||
|
||||
public Cryptonit_OtherAPI(Context context) {
|
||||
this.context = context;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
key = sp.getString(context.getResources().getString(R.string.key_cryptonit_key), "");
|
||||
userId = sp.getString(context.getResources().getString(R.string.key_cryptonit_user_id), "");
|
||||
secret = sp.getString(context.getResources().getString(R.string.key_cryptonit_secret), "");
|
||||
nonce = sp.getInt(context.getResources().getString(R.string.key_cryptonit_nonce), 0);
|
||||
}
|
||||
|
||||
public String key;
|
||||
public String userId;
|
||||
public String secret;
|
||||
private Integer nonce;
|
||||
|
||||
public String getSecretDescription() {
|
||||
if (secret == null || secret.isEmpty()) return "";
|
||||
return secret.substring(0, 3) + "..." + secret.substring(secret.length() - 3, secret.length());
|
||||
}
|
||||
|
||||
public Boolean havaAccountInfo() {
|
||||
return (!userId.isEmpty() && !key.isEmpty() && !secret.isEmpty());
|
||||
}
|
||||
|
||||
public void saveAccountInfo() {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
nonce = 1;
|
||||
sp.edit()
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_key), key)
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_user_id), userId)
|
||||
.putString(context.getResources().getString(R.string.key_cryptonit_secret), secret)
|
||||
.putInt(context.getResources().getString(R.string.key_cryptonit_nonce), nonce)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
||||
private void incNonce() {
|
||||
nonce++;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
sp.edit().putInt(context.getResources().getString(R.string.key_cryptonit_nonce), nonce).apply();
|
||||
}
|
||||
|
||||
public interface BalanceListener {
|
||||
void onBalanceData(Response.Balance response);
|
||||
}
|
||||
|
||||
public interface WithdrawalListener {
|
||||
void onWithdrawalComplete(Response.CryptoWithdrawal response);
|
||||
}
|
||||
|
||||
public interface ErrorListener {
|
||||
void onError(Throwable throwable);
|
||||
}
|
||||
|
||||
public void setBalanceListener(BalanceListener listener) {
|
||||
balanceListener = listener;
|
||||
}
|
||||
|
||||
public void setWithdrawalListener(WithdrawalListener listener) {
|
||||
withdrawalListener = listener;
|
||||
}
|
||||
|
||||
public void setErrorListener(ErrorListener listener) {
|
||||
errorListener = listener;
|
||||
}
|
||||
|
||||
private String calcSignature() throws Exception {
|
||||
incNonce();
|
||||
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
|
||||
SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256");
|
||||
sha256_HMAC.init(secret_key);
|
||||
|
||||
String data = nonce.toString() + userId + key;
|
||||
return Util.bytesToHex(sha256_HMAC.doFinal(data.getBytes("UTF-8")));
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestBalance(String cryptoCurrency, String fiatCurrency) throws Exception {
|
||||
|
||||
initApi();
|
||||
|
||||
String signature = calcSignature();
|
||||
|
||||
Log.e("CRYPTONIT", "user: " + userId);
|
||||
Log.e("CRYPTONIT", "key: " + key);
|
||||
Log.e("CRYPTONIT", "secret: " + secret);
|
||||
Log.e("CRYPTONIT", "nonce: " + nonce);
|
||||
Log.e("CRYPTONIT", "signature: " + signature);
|
||||
|
||||
api.getBalance(cryptoCurrency, fiatCurrency,
|
||||
RequestBody.create(MediaType.parse("text/plain"), key),
|
||||
RequestBody.create(MediaType.parse("text/plain"), signature),
|
||||
RequestBody.create(MediaType.parse("text/plain"), nonce.toString()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(balanceModel -> balanceListener.onBalanceData(balanceModel),
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestCryptoWithdrawal(String currency, String amount, String address) throws Exception {
|
||||
|
||||
initApi();
|
||||
|
||||
String signature = calcSignature();
|
||||
|
||||
Log.e("CRYPTONIT", "user: " + userId);
|
||||
Log.e("CRYPTONIT", "key: " + key);
|
||||
Log.e("CRYPTONIT", "secret: " + secret);
|
||||
Log.e("CRYPTONIT", "nonce: " + nonce);
|
||||
Log.e("CRYPTONIT", "signature: " + signature);
|
||||
|
||||
api.cryptoWithdrawal(
|
||||
RequestBody.create(MediaType.parse("text/plain"), currency),
|
||||
RequestBody.create(MediaType.parse("text/plain"), amount),
|
||||
RequestBody.create(MediaType.parse("text/plain"), address),
|
||||
RequestBody.create(MediaType.parse("text/plain"), key),
|
||||
RequestBody.create(MediaType.parse("text/plain"), signature),
|
||||
RequestBody.create(MediaType.parse("text/plain"), nonce.toString()))
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> {
|
||||
if (response.success != null && response.success)
|
||||
withdrawalListener.onWithdrawalComplete(response);
|
||||
else {
|
||||
LinkedTreeMap reason = (LinkedTreeMap) response.reason;
|
||||
errorListener.onError(new Exception(reason.entrySet().toArray()[0].toString()));
|
||||
}
|
||||
},
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
private void FireError(Throwable e) throws IOException {
|
||||
if (e.getClass() == HttpException.class && ((HttpException) e).code() == 500) {
|
||||
JsonObject jsonObject = new JsonParser().parse(((HttpException) e).response().errorBody().string()).getAsJsonObject();
|
||||
errorListener.onError(new Exception(e.getMessage() + ": " + jsonObject.get("reason").getAsString()));
|
||||
if (jsonObject.get("reason").getAsString().equals("Invalid nonce")) nonce += 1000;
|
||||
} else {
|
||||
errorListener.onError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void initApi() {
|
||||
|
||||
if (api != null) return;
|
||||
|
||||
// HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
// logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient httpClient = new OkHttpClient.Builder().
|
||||
// addInterceptor(logging).
|
||||
build();
|
||||
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl(SERVER_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.client(httpClient)
|
||||
.build();
|
||||
|
||||
api = retrofit.create(Api.class);
|
||||
}
|
||||
}
|
||||
358
app/src/main/java/com/tangem/data/network/Kraken.java
Normal file
358
app/src/main/java/com/tangem/data/network/Kraken.java
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
|
||||
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import com.tangem.util.Util;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import org.spongycastle.util.encoders.Base64;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.RequestBody;
|
||||
import okhttp3.Response;
|
||||
//import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import okio.Buffer;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import retrofit2.http.Field;
|
||||
import retrofit2.http.FormUrlEncoded;
|
||||
import retrofit2.http.POST;
|
||||
|
||||
/**
|
||||
* HTTP
|
||||
* Used in Kraken service
|
||||
*/
|
||||
public class Kraken {
|
||||
private static final String SERVER_URL = "https://api.kraken.com";
|
||||
|
||||
private static class Method {
|
||||
public static final String BALANCE = SERVER_URL + "/0/private/Balance";
|
||||
public static final String WITHDRAW_INFO = SERVER_URL + "/0/private/WithdrawInfo";
|
||||
public static final String WITHDRAW = SERVER_URL + "/0/private/Withdraw";
|
||||
}
|
||||
|
||||
public static class Model {
|
||||
|
||||
public static class Balance {
|
||||
public static class Response {
|
||||
public String[] error;
|
||||
public Result result;
|
||||
|
||||
public static class Result {
|
||||
public String XXBT;
|
||||
public String XETH;
|
||||
public String BCH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class WithdrawInfo {
|
||||
public static class Response {
|
||||
public String[] error;
|
||||
public Result result;
|
||||
|
||||
public static class Result {
|
||||
public String fee;
|
||||
public String amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Withdraw {
|
||||
public static class Response {
|
||||
public String[] error;
|
||||
public Result result;
|
||||
|
||||
public static class Result {
|
||||
public String refid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface Api {
|
||||
@FormUrlEncoded
|
||||
@POST(Method.BALANCE)
|
||||
Observable<Model.Balance.Response> getBalance(@Field("nonce") String nonce);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST(Method.WITHDRAW_INFO)
|
||||
Observable<Model.WithdrawInfo.Response> WithdrawInfo(@Field("nonce") String nonce, @Field("asset") String asset, @Field("key") String key, @Field("amount") String amount);
|
||||
|
||||
@FormUrlEncoded
|
||||
@POST(Method.WITHDRAW)
|
||||
Observable<Model.Withdraw.Response> Withdraw(@Field("nonce") String nonce, @Field("asset") String asset, @Field("key") String key, @Field("amount") String amount);
|
||||
}
|
||||
|
||||
private Api api = null;
|
||||
private BalanceListener balanceListener;
|
||||
private WithdrawalListener withdrawalListener;
|
||||
private WithdrawalInfoListener withdrawalInfoListener;
|
||||
private ErrorListener errorListener;
|
||||
private Context context;
|
||||
|
||||
public Kraken(Context context) {
|
||||
this.context = context;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
key = sp.getString(context.getResources().getString(R.string.key_kraken_key), "");
|
||||
secret = sp.getString(context.getResources().getString(R.string.key_kraken_secret), "");
|
||||
nonce = sp.getInt(context.getResources().getString(R.string.key_kraken_nonce), 0);
|
||||
}
|
||||
|
||||
public String key;
|
||||
public String secret;
|
||||
private Integer nonce;
|
||||
|
||||
public String getSecretDescription() {
|
||||
if (secret == null || secret.isEmpty()) return "";
|
||||
return secret.substring(0, 3) + "..." + secret.substring(secret.length() - 3, secret.length());
|
||||
}
|
||||
|
||||
public Boolean haveAccountInfo() {
|
||||
return (!key.isEmpty() && !secret.isEmpty());
|
||||
}
|
||||
|
||||
public void saveAccountInfo() {
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
sp.edit()
|
||||
.putString(context.getResources().getString(R.string.key_kraken_key), key)
|
||||
.putString(context.getResources().getString(R.string.key_kraken_secret), secret)
|
||||
.putInt(context.getResources().getString(R.string.key_kraken_nonce), nonce)
|
||||
.apply();
|
||||
|
||||
}
|
||||
|
||||
private void incNonce() {
|
||||
nonce++;
|
||||
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
sp.edit().putInt(context.getResources().getString(R.string.key_kraken_nonce), nonce).apply();
|
||||
}
|
||||
|
||||
public interface BalanceListener {
|
||||
void onBalanceData(Model.Balance.Response response);
|
||||
}
|
||||
|
||||
public interface WithdrawalInfoListener {
|
||||
void onWithdrawalInfoComplete(Model.WithdrawInfo.Response response);
|
||||
}
|
||||
|
||||
public interface WithdrawalListener {
|
||||
void onWithdrawalComplete(Model.Withdraw.Response response);
|
||||
}
|
||||
|
||||
public interface ErrorListener {
|
||||
void onError(Throwable throwable);
|
||||
}
|
||||
|
||||
public void setBalanceListener(BalanceListener listener) {
|
||||
balanceListener = listener;
|
||||
}
|
||||
|
||||
public void setWithdrawalListener(WithdrawalListener listener) {
|
||||
withdrawalListener = listener;
|
||||
}
|
||||
|
||||
public void setWithdrawalInfoListener(WithdrawalInfoListener listener) {
|
||||
withdrawalInfoListener = listener;
|
||||
}
|
||||
|
||||
public void setErrorListener(ErrorListener listener) {
|
||||
errorListener = listener;
|
||||
}
|
||||
|
||||
|
||||
private static final String HMAC_SHA512 = "HmacSHA512";
|
||||
|
||||
|
||||
private String bodyToString(final RequestBody request){
|
||||
try {
|
||||
final RequestBody copy = request;
|
||||
final Buffer buffer = new Buffer();
|
||||
if(copy != null)
|
||||
copy.writeTo(buffer);
|
||||
else
|
||||
return "";
|
||||
return buffer.readUtf8();
|
||||
}
|
||||
catch (final IOException e) {
|
||||
return "did not work";
|
||||
}
|
||||
}
|
||||
|
||||
private String calcSignature(String url, RequestBody requestBody) throws NoSuchAlgorithmException, InvalidKeyException, IOException {
|
||||
|
||||
String postData=bodyToString(requestBody);
|
||||
|
||||
// create SHA-256 hash of the nonce and the POST data
|
||||
|
||||
String s=nonce+postData;
|
||||
byte[] sha256 = Util.calculateSHA256(s);
|
||||
|
||||
// set the API method and retrieve the path
|
||||
byte[] path = url.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// decode the API secret, it's the HMAC key
|
||||
byte[] hmacKey = Base64.decode(secret);
|
||||
|
||||
// create the HMAC message from the path and the previous hash
|
||||
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
|
||||
outputStream.write(path);
|
||||
outputStream.write(sha256);
|
||||
byte[] hmacMessage = outputStream.toByteArray();//concatArrays(path, sha256);
|
||||
|
||||
Mac mac = Mac.getInstance(HMAC_SHA512);
|
||||
mac.init(new SecretKeySpec(hmacKey, HMAC_SHA512));
|
||||
byte[] hmacSignature=mac.doFinal(hmacMessage);
|
||||
|
||||
byte[] b64Signature = Base64.encode(hmacSignature);
|
||||
|
||||
return new String(b64Signature, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestBalance() throws Exception {
|
||||
|
||||
initApi();
|
||||
|
||||
Log.e("kraken", "key: " + key);
|
||||
Log.e("kraken", "secret: " + secret);
|
||||
Log.e("kraken", "nonce: " + nonce);
|
||||
|
||||
api.getBalance(nonce.toString())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> balanceListener.onBalanceData(response),
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestWithdrawInfo(String currency, String amount, String withdrawKey) throws Exception {
|
||||
|
||||
initApi();
|
||||
|
||||
// Log.e("kraken", "key: " + key);
|
||||
// Log.e("kraken", "secret: " + secret);
|
||||
// Log.e("kraken", "nonce: " + nonce);
|
||||
|
||||
String asset=CurrencyToAsset(currency);
|
||||
|
||||
// withdrawKey = "test";
|
||||
api.WithdrawInfo(nonce.toString(), asset, withdrawKey, amount)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> withdrawalInfoListener.onWithdrawalInfoComplete(response),
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
private static String CurrencyToAsset(String currency) throws Exception {
|
||||
switch (currency)
|
||||
{
|
||||
case "BTC": return "XXBT";
|
||||
case "BCH": return "BCH";
|
||||
case "ETH": return "XETH";
|
||||
default:
|
||||
throw new Exception("Unsupported currency!");
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
public void requestWithdraw(String currency, String amount, String withdrawKey) throws Exception {
|
||||
initApi();
|
||||
|
||||
// Log.e("kraken", "key: " + key);
|
||||
// Log.e("kraken", "secret: " + secret);
|
||||
// Log.e("kraken", "nonce: " + nonce);
|
||||
|
||||
String asset=CurrencyToAsset(currency);
|
||||
|
||||
// withdrawKey = "test";
|
||||
api.Withdraw(nonce.toString(), asset, withdrawKey, amount)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(response -> withdrawalListener.onWithdrawalComplete(response),
|
||||
// handle error
|
||||
this::FireError
|
||||
);
|
||||
}
|
||||
|
||||
private void FireError(Throwable e) throws IOException {
|
||||
// if (e.getClass() == HttpException.class && ((HttpException) e).code() == 500) {
|
||||
// JsonObject jsonObject = new JsonParser().parse(((HttpException) e).response().errorBody().string()).getAsJsonObject();
|
||||
// errorListener.onError(new Exception(e.getMessage() + ": " + jsonObject.get("reason").getAsString()));
|
||||
// if (jsonObject.get("reason").getAsString().equals("Invalid nonce")) nonce += 1000;
|
||||
// } else {
|
||||
errorListener.onError(e);
|
||||
// }
|
||||
}
|
||||
|
||||
private void initApi() {
|
||||
|
||||
if (api != null) return;
|
||||
|
||||
// HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
|
||||
// logging.setLevel(HttpLoggingInterceptor.Level.BODY);
|
||||
|
||||
OkHttpClient httpClient = new OkHttpClient.Builder().
|
||||
addInterceptor(new AuthorizationInterceptor()).
|
||||
// addInterceptor(logging).
|
||||
build();
|
||||
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl(SERVER_URL)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||
.client(httpClient)
|
||||
.build();
|
||||
|
||||
api = retrofit.create(Api.class);
|
||||
}
|
||||
|
||||
public class AuthorizationInterceptor implements Interceptor {
|
||||
|
||||
AuthorizationInterceptor() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Request mainRequest=chain.request();
|
||||
|
||||
try {
|
||||
mainRequest = mainRequest.newBuilder().
|
||||
addHeader("API-Key", key).
|
||||
addHeader("API-Sign", calcSignature(mainRequest.url().toString().substring(SERVER_URL.length()), mainRequest.body())).
|
||||
build();
|
||||
incNonce();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new IOException("Can't calculate signature: "+e.getMessage());
|
||||
}
|
||||
|
||||
return chain.proceed(mainRequest);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
package com.tangem.presentation.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.nfc.NfcAdapter
|
||||
import android.nfc.Tag
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.text.InputFilter
|
||||
import android.view.View
|
||||
import com.tangem.data.network.Cryptonit_OtherAPI
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.util.DecimalDigitsInputFilter
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_prepare_cryptonit_other_api_withdrawal.*
|
||||
import java.io.IOException
|
||||
|
||||
class PrepareCryptonitOtherAPIWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
||||
|
||||
companion object {
|
||||
val TAG: String = PrepareCryptonitOtherAPIWithdrawalActivity::class.java.simpleName
|
||||
|
||||
private const val REQUEST_CODE_SCAN_QR_KEY = 1
|
||||
private const val REQUEST_CODE_SCAN_QR_SECRET = 2
|
||||
private const val REQUEST_CODE_SCAN_QR_USER_ID = 3
|
||||
}
|
||||
|
||||
private var useCurrencyX1000: Boolean = false
|
||||
private var card: TangemCard? = null
|
||||
private var nfcManager: NfcManager? = null
|
||||
private var cryptonit: Cryptonit_OtherAPI? = null
|
||||
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_prepare_cryptonit_other_api_withdrawal)
|
||||
|
||||
MainActivity.commonInit(applicationContext)
|
||||
|
||||
nfcManager = NfcManager(this, this)
|
||||
|
||||
card = TangemCard(intent.getStringExtra("UID"))
|
||||
card!!.loadFromBundle(intent.extras!!.getBundle("Card"))
|
||||
|
||||
cryptonit = Cryptonit_OtherAPI(this)
|
||||
|
||||
tvKey.text = cryptonit!!.key
|
||||
tvUserID.text = cryptonit!!.userId
|
||||
tvSecret.text = cryptonit!!.secretDescription
|
||||
|
||||
tvCardID.text = card!!.cidDescription
|
||||
tvWallet.text = card!!.wallet
|
||||
val engine = CoinEngineFactory.create(card!!.blockchain)
|
||||
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Ethereum, Blockchain.EthereumTestNet -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
|
||||
}
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinTestNet, Blockchain.BitcoinCash, Blockchain.BitcoinCashTestNet -> {
|
||||
tvCurrency.text = "m" + card!!.blockchain.currency
|
||||
useCurrencyX1000 = true
|
||||
}
|
||||
else -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
}
|
||||
}
|
||||
|
||||
etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination))
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Bitcoin ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(5))
|
||||
Blockchain.BitcoinCash ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(8))
|
||||
Blockchain.Ethereum ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(18))
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
// set listeners
|
||||
btnLoad.setOnClickListener {
|
||||
|
||||
try {
|
||||
val strAmount: String = etAmount.text.toString().replace(",", ".")
|
||||
// if (!engine.checkAmount(card, strAmount))
|
||||
// etAmount.error = getString(R.string.unknown_amount_format)
|
||||
var dblAmount: Double = strAmount.toDouble()
|
||||
if (useCurrencyX1000) dblAmount /= 1000.0
|
||||
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal)
|
||||
|
||||
cryptonit!!.requestCryptoWithdrawal(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
||||
//Toast.makeText(this, strAmount, Toast.LENGTH_LONG).show()
|
||||
// val balance = engine.getBalanceLong(card)!! / (card!!.blockchain.multiplier / 1000.0)
|
||||
// if (etAmount.text.toString().replace(",", ".").toDouble() > balance) {
|
||||
// etAmount.error = getString(R.string.not_enough_funds_on_your_account)
|
||||
// return@setOnClickListener
|
||||
// }
|
||||
|
||||
}
|
||||
ivCameraKey.setOnClickListener {
|
||||
val intent = Intent(baseContext, QrScanActivity::class.java)
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR_KEY)
|
||||
}
|
||||
ivCameraSecret.setOnClickListener {
|
||||
val intent = Intent(baseContext, QrScanActivity::class.java)
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR_SECRET)
|
||||
}
|
||||
ivCameraUserId.setOnClickListener {
|
||||
val intent = Intent(baseContext, QrScanActivity::class.java)
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR_USER_ID)
|
||||
}
|
||||
|
||||
ivRefreshBalance.setOnClickListener { doRequestBalance() }
|
||||
|
||||
cryptonit!!.setBalanceListener { response ->
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Ethereum, Blockchain.EthereumTestNet -> {
|
||||
tvBalance.text = response.eth_available
|
||||
}
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinTestNet, Blockchain.BitcoinCash, Blockchain.BitcoinCashTestNet -> {
|
||||
tvBalance.text = response.btc_available
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
tvBalanceCurrency.text = card!!.blockchain.currency
|
||||
tvBalance.setTextColor(Color.BLACK)
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
btnLoad.isActivated = true
|
||||
}
|
||||
cryptonit!!.setErrorListener { throwable ->
|
||||
throwable.printStackTrace()
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = throwable.message
|
||||
}
|
||||
cryptonit!!.setWithdrawalListener { response ->
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
if (response.success != null && response.success!!) finish()
|
||||
else {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = response.reason!!.toString()
|
||||
}
|
||||
}
|
||||
btnLoad.isActivated = false
|
||||
doRequestBalance()
|
||||
}
|
||||
|
||||
private fun doRequestBalance() {
|
||||
if (cryptonit!!.havaAccountInfo()) {
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_balance)
|
||||
tvError.visibility = View.INVISIBLE
|
||||
cryptonit!!.requestBalance(card!!.blockchain.currency, "USD")
|
||||
} else {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = getString(R.string.cryptonit_not_enough_account_data)
|
||||
}
|
||||
}
|
||||
|
||||
// private fun EditText.afterTextChanged(afterTextChanged: (String) -> Unit) {
|
||||
// this.addTextChangedListener(object : TextWatcher {
|
||||
// override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
// }
|
||||
//
|
||||
// override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||
// }
|
||||
//
|
||||
// override fun afterTextChanged(editable: Editable?) {
|
||||
// afterTextChanged.invoke(editable.toString())
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
nfcManager!!.onResume()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
nfcManager!!.onPause()
|
||||
}
|
||||
|
||||
public override fun onStop() {
|
||||
super.onStop()
|
||||
nfcManager!!.onStop()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if( resultCode == Activity.RESULT_OK && data != null && data.extras!!.containsKey("QRCode") ) {
|
||||
when(requestCode) {
|
||||
REQUEST_CODE_SCAN_QR_KEY -> {
|
||||
cryptonit!!.key = data.getStringExtra("QRCode")
|
||||
tvKey!!.text = cryptonit!!.key
|
||||
}
|
||||
REQUEST_CODE_SCAN_QR_SECRET -> {
|
||||
cryptonit!!.secret = data.getStringExtra("QRCode")
|
||||
tvSecret!!.text = cryptonit!!.secretDescription
|
||||
}
|
||||
REQUEST_CODE_SCAN_QR_USER_ID -> {
|
||||
cryptonit!!.userId = data.getStringExtra("QRCode")
|
||||
tvUserID!!.text = cryptonit!!.userId
|
||||
}
|
||||
}
|
||||
cryptonit!!.saveAccountInfo()
|
||||
doRequestBalance()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTagDiscovered(tag: Tag) {
|
||||
try {
|
||||
// Log.w(javaClass.name, "Ignore discovered tag!")
|
||||
nfcManager!!.ignoreTag(tag)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
package com.tangem.presentation.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Color
|
||||
import android.nfc.NfcAdapter
|
||||
import android.nfc.Tag
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.text.InputFilter
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.network.Cryptonit
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.util.DecimalDigitsInputFilter
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_prepare_cryptonit_withdrawal.*
|
||||
import java.io.IOException
|
||||
|
||||
class PrepareCryptonitWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
||||
|
||||
companion object {
|
||||
val TAG: String = PrepareCryptonitWithdrawalActivity::class.java.simpleName
|
||||
}
|
||||
|
||||
private var useCurrencyX1000: Boolean = false
|
||||
private var card: TangemCard? = null
|
||||
private var nfcManager: NfcManager? = null
|
||||
private var cryptonit: Cryptonit? = null
|
||||
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_prepare_cryptonit_withdrawal)
|
||||
|
||||
MainActivity.commonInit(applicationContext)
|
||||
|
||||
nfcManager = NfcManager(this, this)
|
||||
|
||||
card = TangemCard(intent.getStringExtra("UID"))
|
||||
card!!.loadFromBundle(intent.extras!!.getBundle("Card"))
|
||||
|
||||
cryptonit = Cryptonit(this)
|
||||
|
||||
etUsername.setText(cryptonit!!.username)
|
||||
etPassword.setText(cryptonit!!.password)
|
||||
etFee.setText(cryptonit!!.fee)
|
||||
|
||||
tvCardID.text = card!!.cidDescription
|
||||
tvWallet.text = card!!.wallet
|
||||
val engine = CoinEngineFactory.create(card!!.blockchain)
|
||||
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Ethereum -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
|
||||
}
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinCash -> {
|
||||
tvCurrency.text = "m" + card!!.blockchain.currency
|
||||
useCurrencyX1000 = true
|
||||
}
|
||||
else -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
}
|
||||
}
|
||||
tvFeeCurrency.text = tvCurrency.text
|
||||
|
||||
etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination))
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Bitcoin -> {
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(5))
|
||||
etFee.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(5))
|
||||
}
|
||||
Blockchain.BitcoinCash -> {
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(8))
|
||||
etFee.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(8))
|
||||
}
|
||||
Blockchain.Ethereum -> {
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(18))
|
||||
etFee.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(18))
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
// set listeners
|
||||
btnLoad.setOnClickListener {
|
||||
|
||||
try {
|
||||
val strAmount: String = etAmount.text.toString().replace(",", ".")
|
||||
val strFee: String = etFee.text.toString().replace(",", ".")
|
||||
var dblAmount: Double = strAmount.toDouble()
|
||||
var dblFee: Double = strFee.toDouble()
|
||||
if (useCurrencyX1000){
|
||||
dblAmount /= 1000.0
|
||||
dblFee /= 1000.0
|
||||
}
|
||||
cryptonit!!.fee=strFee
|
||||
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_withdrawal)
|
||||
|
||||
cryptonit!!.requestWithdrawCoins(card!!.blockchain.currency, dblAmount, card!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
}
|
||||
|
||||
ivRefreshBalance.setOnClickListener {
|
||||
cryptonit!!.username=etUsername.text.toString()
|
||||
cryptonit!!.password=etPassword.text.toString()
|
||||
cryptonit!!.saveAccountInfo()
|
||||
doRequestBalance()
|
||||
}
|
||||
|
||||
cryptonit!!.setBalanceListener { response ->
|
||||
tvBalance.text = response.results[0].balance.toString()
|
||||
tvBalanceCurrency.text = response.results[0].currency // card!!.blockchain.currency
|
||||
tvBalance.setTextColor(Color.BLACK)
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
btnLoad.visibility = View.VISIBLE
|
||||
}
|
||||
cryptonit!!.setErrorListener { throwable ->
|
||||
throwable.printStackTrace()
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = throwable.message
|
||||
}
|
||||
cryptonit!!.setWithdrawalListener { response ->
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
if (response.success != null && response.success!!){
|
||||
Toast.makeText(this,"Withdrawal successful!", Toast.LENGTH_LONG).show();
|
||||
finish()
|
||||
}
|
||||
else {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = response.errors.toString()
|
||||
}
|
||||
}
|
||||
btnLoad.visibility = View.INVISIBLE
|
||||
doRequestBalance()
|
||||
}
|
||||
|
||||
private fun doRequestBalance() {
|
||||
if (cryptonit!!.haveAccountInfo()) {
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.cryptonit_request_balance)
|
||||
tvError.visibility = View.INVISIBLE
|
||||
cryptonit!!.requestBalance(card!!.blockchain.currency)
|
||||
} else {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = getString(R.string.cryptonit_not_enough_account_data)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
nfcManager!!.onResume()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
nfcManager!!.onPause()
|
||||
}
|
||||
|
||||
public override fun onStop() {
|
||||
super.onStop()
|
||||
nfcManager!!.onStop()
|
||||
}
|
||||
|
||||
override fun onTagDiscovered(tag: Tag) {
|
||||
try {
|
||||
nfcManager!!.ignoreTag(tag)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,286 @@
|
|||
package com.tangem.presentation.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.nfc.NfcAdapter
|
||||
import android.nfc.Tag
|
||||
import android.os.Bundle
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.text.InputFilter
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import com.tangem.data.network.Kraken
|
||||
import com.tangem.domain.cardReader.NfcManager
|
||||
import com.tangem.domain.wallet.Blockchain
|
||||
import com.tangem.domain.wallet.CoinEngineFactory
|
||||
import com.tangem.domain.wallet.TangemCard
|
||||
import com.tangem.util.DecimalDigitsInputFilter
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.activity_prepare_kraken_withdrawal.*
|
||||
import java.io.IOException
|
||||
import java.math.BigDecimal
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
|
||||
class PrepareKrakenWithdrawalActivity : AppCompatActivity(), NfcAdapter.ReaderCallback {
|
||||
|
||||
companion object {
|
||||
val TAG: String = PrepareKrakenWithdrawalActivity::class.java.simpleName
|
||||
|
||||
private const val REQUEST_CODE_SCAN_QR = 1
|
||||
}
|
||||
|
||||
private var useCurrencyX1000: Boolean = false
|
||||
private var card: TangemCard? = null
|
||||
private var nfcManager: NfcManager? = null
|
||||
private var kraken: Kraken? = null
|
||||
private var fee: BigDecimal? = null
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_prepare_kraken_withdrawal)
|
||||
|
||||
MainActivity.commonInit(applicationContext)
|
||||
|
||||
nfcManager = NfcManager(this, this)
|
||||
|
||||
card = TangemCard(intent.getStringExtra("UID"))
|
||||
card!!.loadFromBundle(intent.extras!!.getBundle("Card"))
|
||||
|
||||
kraken = Kraken(this)
|
||||
|
||||
tvKey.text = kraken!!.key
|
||||
tvSecret.text = kraken!!.secretDescription
|
||||
|
||||
tvCardID.text = card!!.cidDescription
|
||||
tvWallet.text = card!!.wallet
|
||||
val engine = CoinEngineFactory.create(card!!.blockchain)
|
||||
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Ethereum, Blockchain.EthereumTestNet -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
|
||||
}
|
||||
Blockchain.Bitcoin, Blockchain.BitcoinTestNet, Blockchain.BitcoinCash, Blockchain.BitcoinCashTestNet -> {
|
||||
tvCurrency.text = "m" + card!!.blockchain.currency
|
||||
useCurrencyX1000 = true
|
||||
}
|
||||
else -> {
|
||||
tvCurrency.text = engine.getBalanceCurrency(card)
|
||||
useCurrencyX1000 = false
|
||||
}
|
||||
}
|
||||
|
||||
etAmount.setText(engine.convertByteArrayToAmount(card!!, card!!.denomination))
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Bitcoin ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(5))
|
||||
Blockchain.BitcoinCash ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(8))
|
||||
Blockchain.Ethereum ->
|
||||
etAmount.filters = arrayOf<InputFilter>(DecimalDigitsInputFilter(18))
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
// set listeners
|
||||
btnLoad.setOnClickListener {
|
||||
|
||||
try {
|
||||
val strAmount: String = etAmount.text.toString().replace(",", ".")
|
||||
|
||||
var dblAmount: Double = strAmount.toDouble()
|
||||
if (useCurrencyX1000) dblAmount /= 1000.0
|
||||
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.kraken_request_withdrawal)
|
||||
|
||||
kraken!!.requestWithdrawInfo(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
|
||||
}
|
||||
ivCamera.setOnClickListener {
|
||||
val intent = Intent(baseContext, QrScanActivity::class.java)
|
||||
startActivityForResult(intent, REQUEST_CODE_SCAN_QR)
|
||||
}
|
||||
|
||||
ivRefreshBalance.setOnClickListener { doRequestBalance() }
|
||||
|
||||
kraken!!.setBalanceListener { response ->
|
||||
if (response.error != null && response.error.isNotEmpty()) {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = Arrays.toString(response.error)
|
||||
} else {
|
||||
when (card!!.blockchain) {
|
||||
Blockchain.Ethereum -> {
|
||||
tvBalance.text = response.result.XETH.trimEnd('0')
|
||||
}
|
||||
Blockchain.Bitcoin -> {
|
||||
tvBalance.text = response.result.XXBT.trimEnd('0')
|
||||
}
|
||||
Blockchain.BitcoinCash -> {
|
||||
tvBalance.text = response.result.BCH.trimEnd('0')
|
||||
}
|
||||
else -> {
|
||||
tvBalance.text = "???"
|
||||
}
|
||||
}
|
||||
tvBalanceCurrency.text = card!!.blockchain.currency
|
||||
tvBalance.setTextColor(Color.BLACK)
|
||||
btnLoad.visibility = View.VISIBLE
|
||||
}
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
}
|
||||
kraken!!.setErrorListener { throwable ->
|
||||
throwable.printStackTrace()
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = throwable.message
|
||||
}
|
||||
kraken!!.setWithdrawalListener { response ->
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
if (response.error != null && response.error.isNotEmpty()) {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = Arrays.toString(response.error)
|
||||
} else {
|
||||
Toast.makeText(this,"Withdrawal successful!", Toast.LENGTH_LONG).show()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
kraken!!.setWithdrawalInfoListener { response ->
|
||||
rlProgressBar.visibility = View.INVISIBLE
|
||||
if (response.error != null && response.error.isNotEmpty()) {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = Arrays.toString(response.error)
|
||||
} else {
|
||||
fee = BigDecimal(response.result.fee)
|
||||
showConfirmDialog()
|
||||
}
|
||||
}
|
||||
btnLoad.visibility = View.INVISIBLE
|
||||
doRequestBalance()
|
||||
}
|
||||
|
||||
// Method to show an alert dialog with yes, no and cancel button
|
||||
private fun showConfirmDialog() {
|
||||
// Late initialize an alert dialog object
|
||||
lateinit var dialog: AlertDialog
|
||||
|
||||
|
||||
// Initialize a new instance of alert dialog builder object
|
||||
val builder = AlertDialog.Builder(this)
|
||||
|
||||
// Set a title for alert dialog
|
||||
builder.setTitle("Please confirm withdraw")
|
||||
|
||||
// Set a message for alert dialog
|
||||
builder.setMessage(String.format("Continue with fee %s %s?", fee!!.toString().trimEnd('0'),card!!.blockchain.currency))
|
||||
|
||||
// On click listener for dialog buttons
|
||||
val dialogClickListener = DialogInterface.OnClickListener { _, which ->
|
||||
when (which) {
|
||||
DialogInterface.BUTTON_POSITIVE -> {
|
||||
try {
|
||||
val strAmount: String = etAmount.text.toString().replace(",", ".")
|
||||
|
||||
var dblAmount: Double = strAmount.toDouble()
|
||||
if (useCurrencyX1000) dblAmount /= 1000.0
|
||||
|
||||
dblAmount+=fee!!.toDouble()
|
||||
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.kraken_request_withdrawal)
|
||||
|
||||
//Toast.makeText(this, String.format("Withdraw %s!",dblAmount.toString()), Toast.LENGTH_LONG).show()
|
||||
kraken!!.requestWithdraw(card!!.blockchain.currency, dblAmount.toString(), card!!.wallet)
|
||||
} catch (e: Exception) {
|
||||
etAmount.error = getString(R.string.unknown_amount_format)
|
||||
}
|
||||
}
|
||||
DialogInterface.BUTTON_NEGATIVE -> {
|
||||
Toast.makeText(this, "Operation canceled!", Toast.LENGTH_LONG).show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the alert dialog positive/yes button
|
||||
builder.setPositiveButton("YES", dialogClickListener)
|
||||
|
||||
// Set the alert dialog negative/no button
|
||||
builder.setNegativeButton("NO", dialogClickListener)
|
||||
|
||||
|
||||
// Initialize the AlertDialog using builder object
|
||||
dialog = builder.create()
|
||||
|
||||
// Finally, display the alert dialog
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
private fun doRequestBalance() {
|
||||
if (kraken!!.haveAccountInfo()) {
|
||||
rlProgressBar.visibility = View.VISIBLE
|
||||
tvProgressDescription.text = getString(R.string.kraken_request_balance)
|
||||
tvError.visibility = View.INVISIBLE
|
||||
kraken!!.requestBalance()
|
||||
} else {
|
||||
tvError.visibility = View.VISIBLE
|
||||
tvError.text = getString(R.string.kraken_not_enough_account_data)
|
||||
}
|
||||
}
|
||||
|
||||
public override fun onResume() {
|
||||
super.onResume()
|
||||
nfcManager!!.onResume()
|
||||
}
|
||||
|
||||
public override fun onPause() {
|
||||
super.onPause()
|
||||
nfcManager!!.onPause()
|
||||
}
|
||||
|
||||
public override fun onStop() {
|
||||
super.onStop()
|
||||
nfcManager!!.onStop()
|
||||
}
|
||||
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (resultCode == Activity.RESULT_OK && data != null && data.extras!!.containsKey("QRCode")) {
|
||||
when (requestCode) {
|
||||
REQUEST_CODE_SCAN_QR -> {
|
||||
val uri = URI(data.getStringExtra("QRCode"))
|
||||
var query = uri.query
|
||||
var params = query.split("&")
|
||||
for (param in params) {
|
||||
if (param.startsWith("key=")) kraken!!.key = param.substring(4)
|
||||
else if (param.startsWith("secret=")) kraken!!.secret = param.substring(7)
|
||||
}
|
||||
tvKey!!.text = kraken!!.key
|
||||
tvSecret!!.text = kraken!!.secretDescription
|
||||
}
|
||||
}
|
||||
kraken!!.saveAccountInfo()
|
||||
doRequestBalance()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onTagDiscovered(tag: Tag) {
|
||||
try {
|
||||
// Log.w(javaClass.name, "Ignore discovered tag!")
|
||||
nfcManager!!.ignoreTag(tag)
|
||||
} catch (e: IOException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.presentation.fragment
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.AlertDialog
|
||||
import android.content.*
|
||||
import android.content.Context.CLIPBOARD_SERVICE
|
||||
import android.content.pm.PackageManager
|
||||
|
|
@ -36,6 +37,7 @@ import com.tangem.presentation.dialog.PINSwapWarningDialog
|
|||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog
|
||||
import com.tangem.util.Util
|
||||
import com.tangem.util.UtilHelper
|
||||
import com.tangem.wallet.BuildConfig
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.android.synthetic.main.fr_loaded_wallet.*
|
||||
import java.util.*
|
||||
|
|
@ -51,6 +53,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
private const val REQUEST_CODE_ENTER_NEW_PIN2 = 6
|
||||
private const val REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN = 7
|
||||
private const val REQUEST_CODE_SWAP_PIN = 8
|
||||
private const val REQUEST_CODE_RECEIVE_PAYMENT = 9
|
||||
}
|
||||
|
||||
private var singleToast: Toast? = null
|
||||
|
|
@ -133,12 +136,53 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
tvWallet.setOnClickListener { doShareWallet(false) }
|
||||
ivQR.setOnClickListener { doShareWallet(true) }
|
||||
btnLoad.setOnClickListener {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card))
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
showSingleToast(R.string.no_compatible_wallet)
|
||||
if (BuildConfig.DEBUG) {
|
||||
val items = arrayOf<CharSequence>(getString(R.string.in_app), getString(R.string.via_cryptonit), getString(R.string.via_kraken))
|
||||
val dialog = AlertDialog.Builder(activity).setTitle(getString(R.string.select_loading_method)).setItems(items
|
||||
) { _, which ->
|
||||
when (items[which]) {
|
||||
getString(R.string.in_app) -> {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card))
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
showSingleToast(R.string.no_compatible_wallet)
|
||||
}
|
||||
|
||||
}
|
||||
// getString(R.string.via_cryptonit2) -> {
|
||||
// val intent = Intent(context, PrepareCryptonitOtherAPIWithdrawalActivity::class.java)
|
||||
// intent.putExtra("UID", card!!.uid)
|
||||
// intent.putExtra("Card", card!!.asBundle)
|
||||
// startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
|
||||
// }
|
||||
getString(R.string.via_cryptonit) -> {
|
||||
val intent = Intent(context, PrepareCryptonitWithdrawalActivity::class.java)
|
||||
intent.putExtra("UID", card!!.uid)
|
||||
intent.putExtra("Card", card!!.asBundle)
|
||||
startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
|
||||
}
|
||||
getString(R.string.via_kraken) -> {
|
||||
val intent = Intent(context, PrepareKrakenWithdrawalActivity::class.java)
|
||||
intent.putExtra("UID", card!!.uid)
|
||||
intent.putExtra("Card", card!!.asBundle)
|
||||
startActivityForResult(intent, REQUEST_CODE_RECEIVE_PAYMENT)
|
||||
}
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
dialog.show()
|
||||
} else {
|
||||
try {
|
||||
val intent = Intent(Intent.ACTION_VIEW, CoinEngineFactory.create(card!!.blockchain)!!.getShareWalletUri(card))
|
||||
intent.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
showSingleToast(R.string.no_compatible_wallet)
|
||||
}
|
||||
}
|
||||
}
|
||||
btnDetails.setOnClickListener {
|
||||
|
|
@ -351,7 +395,7 @@ class LoadedWallet : Fragment(), NfcAdapter.ReaderCallback, CardProtocol.Notific
|
|||
}
|
||||
updateViews()
|
||||
}
|
||||
REQUEST_CODE_SEND_PAYMENT -> {
|
||||
REQUEST_CODE_SEND_PAYMENT, REQUEST_CODE_RECEIVE_PAYMENT -> {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
srlLoadedWallet!!.postDelayed({ this.refresh() }, 10000)
|
||||
srlLoadedWallet!!.isRefreshing = true
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue