Updated on 2026-08-14
This commit is contained in:
parent
8c17a8d4f0
commit
b19c306250
70 changed files with 6149 additions and 6206 deletions
52
app/src/main/java/com/tangem/VerticalTextView.java
Normal file
52
app/src/main/java/com/tangem/VerticalTextView.java
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
package com.tangem;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.support.v7.widget.AppCompatTextView;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
|
||||
public class VerticalTextView extends AppCompatTextView {
|
||||
final boolean topDown;
|
||||
|
||||
public VerticalTextView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
final int gravity = getGravity();
|
||||
if (Gravity.isVertical(gravity) && (gravity & Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
|
||||
setGravity((gravity & Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
|
||||
topDown = false;
|
||||
} else {
|
||||
topDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
|
||||
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
TextPaint textPaint = getPaint();
|
||||
textPaint.setColor(getCurrentTextColor());
|
||||
textPaint.drawableState = getDrawableState();
|
||||
|
||||
canvas.save();
|
||||
|
||||
if (topDown) {
|
||||
canvas.translate(getWidth(), 0);
|
||||
canvas.rotate(90);
|
||||
} else {
|
||||
canvas.translate(0, getHeight());
|
||||
canvas.rotate(-90);
|
||||
}
|
||||
|
||||
canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
|
||||
|
||||
getLayout().draw(canvas);
|
||||
canvas.restore();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package com.tangem.data.network;
|
||||
|
||||
public class Server {
|
||||
}
|
||||
|
|
@ -1,184 +1,182 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class Electrum_Request {
|
||||
public static final String METHOD_GetBalance = "blockchain.address.get_balance";
|
||||
public static final String METHOD_ListUnspent = "blockchain.address.listunspent";
|
||||
public static final String METHOD_GetHistory = "blockchain.address.get_history";
|
||||
public static final String METHOD_GetTransaction = "blockchain.transaction.get";
|
||||
public static final String METHOD_GetHeader = "blockchain.block.get_header";
|
||||
public static final String METHOD_SendTransaction = "blockchain.transaction.broadcast";
|
||||
public static final String METHOD_GetFee = "blockchain.estimatefee";
|
||||
|
||||
|
||||
|
||||
public JSONObject jsRequestData;
|
||||
public String answerData;
|
||||
public String error;
|
||||
public String WalletAddress;
|
||||
public String TxHash;
|
||||
public String Host;
|
||||
public int Port;
|
||||
|
||||
private Electrum_Request() {
|
||||
}
|
||||
|
||||
public Electrum_Request(JSONObject jsRequest) {
|
||||
try {
|
||||
jsRequestData = new JSONObject(jsRequest.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject getAnswer() {
|
||||
try {
|
||||
return new JSONObject(answerData);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return new JSONObject(String.format("[\"Error\":\"%s\"]", e.getMessage()));
|
||||
} catch (JSONException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return jsRequestData.toString();
|
||||
}
|
||||
|
||||
public void setID(int value) {
|
||||
try {
|
||||
jsRequestData.put("id", String.format("%d", value));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
try {
|
||||
return jsRequestData.getInt("id");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Electrum_Request CheckBalance(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetBalance + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
public static Electrum_Request GetFee(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try{
|
||||
request.WalletAddress = wallet; //METHOD_GetFee
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetFee + "\", \"params\":[\"" + 6 + "\"] }");
|
||||
}
|
||||
catch(JSONException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request GetHeader(String wallet, String height) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHeader + "\", \"params\":[\"" + height + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request ListUnspent(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ListUnspent + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request Broadcast(String wallet, String tx) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_SendTransaction + "\", \"params\":[\"" + tx + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request ListHistory(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHistory + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request GetTransaction(String wallet, String tx_hash) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.TxHash = tx_hash;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetTransaction + "\", \"params\":[\"" + tx_hash + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public boolean isMethod(String methodName) throws JSONException {
|
||||
return jsRequestData.getString("method").equals(methodName);
|
||||
}
|
||||
|
||||
public JSONArray getParams() throws JSONException {
|
||||
return jsRequestData.getJSONArray("params");
|
||||
}
|
||||
|
||||
public JSONObject getResult() throws JSONException {
|
||||
return getAnswer().getJSONObject("result");
|
||||
}
|
||||
|
||||
public String getResultString() throws JSONException {
|
||||
return getAnswer().getString("result");
|
||||
}
|
||||
|
||||
public JSONArray getResultArray() throws JSONException {
|
||||
return getAnswer().getJSONArray("result");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.tangem.data.network.request;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class Electrum_Request {
|
||||
public static final String METHOD_GetBalance = "blockchain.address.get_balance";
|
||||
public static final String METHOD_ListUnspent = "blockchain.address.listunspent";
|
||||
public static final String METHOD_GetHistory = "blockchain.address.get_history";
|
||||
public static final String METHOD_GetTransaction = "blockchain.transaction.get";
|
||||
public static final String METHOD_GetHeader = "blockchain.block.get_header";
|
||||
public static final String METHOD_SendTransaction = "blockchain.transaction.broadcast";
|
||||
public static final String METHOD_GetFee = "blockchain.estimatefee";
|
||||
|
||||
public JSONObject jsRequestData;
|
||||
public String answerData;
|
||||
public String error;
|
||||
public String WalletAddress;
|
||||
public String TxHash;
|
||||
public String Host;
|
||||
public int Port;
|
||||
|
||||
private Electrum_Request() {
|
||||
}
|
||||
|
||||
public Electrum_Request(JSONObject jsRequest) {
|
||||
try {
|
||||
jsRequestData = new JSONObject(jsRequest.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject getAnswer() {
|
||||
try {
|
||||
return new JSONObject(answerData);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return new JSONObject(String.format("[\"Error\":\"%s\"]", e.getMessage()));
|
||||
} catch (JSONException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return jsRequestData.toString();
|
||||
}
|
||||
|
||||
public void setID(int value) {
|
||||
try {
|
||||
jsRequestData.put("id", String.format("%d", value));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
try {
|
||||
return jsRequestData.getInt("id");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static Electrum_Request CheckBalance(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetBalance + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
public static Electrum_Request GetFee(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try{
|
||||
request.WalletAddress = wallet; //METHOD_GetFee
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetFee + "\", \"params\":[\"" + 6 + "\"] }");
|
||||
}
|
||||
catch(JSONException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request GetHeader(String wallet, String height) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHeader + "\", \"params\":[\"" + height + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request ListUnspent(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ListUnspent + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request Broadcast(String wallet, String tx) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_SendTransaction + "\", \"params\":[\"" + tx + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request ListHistory(String wallet) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHistory + "\", \"params\":[\"" + wallet + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public static Electrum_Request GetTransaction(String wallet, String tx_hash) {
|
||||
Electrum_Request request = new Electrum_Request();
|
||||
try {
|
||||
request.WalletAddress=wallet;
|
||||
request.TxHash = tx_hash;
|
||||
request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetTransaction + "\", \"params\":[\"" + tx_hash + "\"] }");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
request.error = e.toString();
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public boolean isMethod(String methodName) throws JSONException {
|
||||
return jsRequestData.getString("method").equals(methodName);
|
||||
}
|
||||
|
||||
public JSONArray getParams() throws JSONException {
|
||||
return jsRequestData.getJSONArray("params");
|
||||
}
|
||||
|
||||
public JSONObject getResult() throws JSONException {
|
||||
return getAnswer().getJSONObject("result");
|
||||
}
|
||||
|
||||
public String getResultString() throws JSONException {
|
||||
return getAnswer().getString("result");
|
||||
}
|
||||
|
||||
public JSONArray getResultArray() throws JSONException {
|
||||
return getAnswer().getJSONArray("result");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,92 +1,92 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class ExchangeRequest {
|
||||
public JSONObject jsRequestData;
|
||||
public String answerData;
|
||||
public String error;
|
||||
public String WalletAddress;
|
||||
public String currency;
|
||||
public String currencyAlter;
|
||||
|
||||
private ExchangeRequest() {
|
||||
}
|
||||
|
||||
public ExchangeRequest(JSONObject jsRequest) {
|
||||
try {
|
||||
jsRequestData = new JSONObject(jsRequest.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject getAnswer() {
|
||||
try {
|
||||
return new JSONObject(answerData);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return new JSONObject(String.format("[\"Error\":\"%s\"]", e.getMessage()));
|
||||
} catch (JSONException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JSONArray getAnswerList() throws JSONException {
|
||||
return new JSONArray(answerData);
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return jsRequestData.toString();
|
||||
}
|
||||
|
||||
public void setID(int value) {
|
||||
try {
|
||||
jsRequestData.put("id", String.format("%d", value));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
try {
|
||||
return jsRequestData.getInt("id");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static ExchangeRequest GetRate(String wallet, String currency, String alterCurrency) {
|
||||
ExchangeRequest request = new ExchangeRequest();
|
||||
request.WalletAddress=wallet;
|
||||
request.currency = currency;
|
||||
request.currencyAlter = alterCurrency;
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
public JSONArray getParams() throws JSONException {
|
||||
return jsRequestData.getJSONArray("params");
|
||||
}
|
||||
|
||||
public JSONObject getResult() throws JSONException {
|
||||
return getAnswer().getJSONObject("result");
|
||||
}
|
||||
|
||||
public String getResultString() throws JSONException {
|
||||
return getAnswer().getString("result");
|
||||
}
|
||||
|
||||
public JSONArray getResultArray() throws JSONException {
|
||||
return getAnswer().getJSONArray("result");
|
||||
}
|
||||
}
|
||||
package com.tangem.data.network.request;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class ExchangeRequest {
|
||||
public JSONObject jsRequestData;
|
||||
public String answerData;
|
||||
public String error;
|
||||
public String WalletAddress;
|
||||
public String currency;
|
||||
public String currencyAlter;
|
||||
|
||||
private ExchangeRequest() {
|
||||
}
|
||||
|
||||
public ExchangeRequest(JSONObject jsRequest) {
|
||||
try {
|
||||
jsRequestData = new JSONObject(jsRequest.toString());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject getAnswer() {
|
||||
try {
|
||||
return new JSONObject(answerData);
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
return new JSONObject(String.format("[\"Error\":\"%s\"]", e.getMessage()));
|
||||
} catch (JSONException e1) {
|
||||
e1.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JSONArray getAnswerList() throws JSONException {
|
||||
return new JSONArray(answerData);
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
return jsRequestData.toString();
|
||||
}
|
||||
|
||||
public void setID(int value) {
|
||||
try {
|
||||
jsRequestData.put("id", String.format("%d", value));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
try {
|
||||
return jsRequestData.getInt("id");
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static ExchangeRequest GetRate(String wallet, String currency, String alterCurrency) {
|
||||
ExchangeRequest request = new ExchangeRequest();
|
||||
request.WalletAddress=wallet;
|
||||
request.currency = currency;
|
||||
request.currencyAlter = alterCurrency;
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
public JSONArray getParams() throws JSONException {
|
||||
return jsRequestData.getJSONArray("params");
|
||||
}
|
||||
|
||||
public JSONObject getResult() throws JSONException {
|
||||
return getAnswer().getJSONObject("result");
|
||||
}
|
||||
|
||||
public String getResultString() throws JSONException {
|
||||
return getAnswer().getString("result");
|
||||
}
|
||||
|
||||
public JSONArray getResultArray() throws JSONException {
|
||||
return getAnswer().getJSONArray("result");
|
||||
}
|
||||
}
|
||||
|
|
@ -1,116 +1,119 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class Electrum_Task extends AsyncTask<Electrum_Request, Integer, List<Electrum_Request>> {
|
||||
public static final String logTag = "Electrum";
|
||||
//public static final String Host = /*"hsmiths.changeip.net";*/ "testnetnode.arihanc.com";
|
||||
//public static final int Port = /*8080*/51001;
|
||||
private int reqID = 1;
|
||||
private String Host = "";
|
||||
private int Port = 0;
|
||||
OutputStreamWriter out;
|
||||
BufferedReader in;
|
||||
|
||||
public SharedData sharedCounter = null;
|
||||
|
||||
|
||||
public Electrum_Task(String host, int port) {
|
||||
super();
|
||||
Host = host;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
public Electrum_Task(String host, int port, SharedData sharedCounter) {
|
||||
super();
|
||||
Host = host;
|
||||
Port = port;
|
||||
this.sharedCounter = sharedCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Electrum_Request> doInBackground(Electrum_Request... requests) {
|
||||
List<Electrum_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
try {
|
||||
|
||||
InetAddress serverAddress = InetAddress.getByName(Host);
|
||||
Log.v(logTag, "Connecting..."+Host);
|
||||
Socket socket = new Socket(serverAddress, Port);
|
||||
socket.setSoTimeout(5000);
|
||||
try {
|
||||
OutputStream os = socket.getOutputStream();
|
||||
out = new OutputStreamWriter(os, "UTF-8");
|
||||
Log.v(logTag, "Connected");
|
||||
InputStream is = socket.getInputStream();
|
||||
in = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
publishProgress(5);
|
||||
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
requests[i].setID(reqID++);
|
||||
doRequest(requests[i]);
|
||||
publishProgress(5 + 90 * (i + 1) / requests.length);
|
||||
}
|
||||
|
||||
publishProgress(100);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(logTag, "Error: ", e);
|
||||
} finally {
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(logTag, "Error: ", e);
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.get(i).error = e.toString();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void doRequest(Electrum_Request request) {
|
||||
try {
|
||||
|
||||
Log.v(logTag, "<< " + request.getAsString());
|
||||
|
||||
out.write(request.getAsString() + "\n");
|
||||
out.flush();
|
||||
|
||||
request.answerData = in.readLine();
|
||||
request.Host=Host;
|
||||
request.Port=Port;
|
||||
if (request.answerData != null) {
|
||||
Log.v(logTag, ">> " + request.answerData);
|
||||
} else {
|
||||
request.error = "No answer from server";
|
||||
Log.v(logTag, ">> <NULL>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
request.error = e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getValidationNodeDescription() {
|
||||
return "Electrum, "+Host+":"+String.valueOf(Port);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package com.tangem.data.network.task;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.data.network.request.Electrum_Request;
|
||||
import com.tangem.wallet.SharedData;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
*/
|
||||
|
||||
public class Electrum_Task extends AsyncTask<Electrum_Request, Integer, List<Electrum_Request>> {
|
||||
public static final String logTag = "Electrum";
|
||||
//public static final String Host = /*"hsmiths.changeip.net";*/ "testnetnode.arihanc.com";
|
||||
//public static final int Port = /*8080*/51001;
|
||||
private int reqID = 1;
|
||||
private String Host = "";
|
||||
private int Port = 0;
|
||||
OutputStreamWriter out;
|
||||
BufferedReader in;
|
||||
|
||||
public SharedData sharedCounter = null;
|
||||
|
||||
|
||||
public Electrum_Task(String host, int port) {
|
||||
super();
|
||||
Host = host;
|
||||
Port = port;
|
||||
}
|
||||
|
||||
public Electrum_Task(String host, int port, SharedData sharedCounter) {
|
||||
super();
|
||||
Host = host;
|
||||
Port = port;
|
||||
this.sharedCounter = sharedCounter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Electrum_Request> doInBackground(Electrum_Request... requests) {
|
||||
List<Electrum_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
try {
|
||||
|
||||
InetAddress serverAddress = InetAddress.getByName(Host);
|
||||
Log.v(logTag, "Connecting..."+Host);
|
||||
Socket socket = new Socket(serverAddress, Port);
|
||||
socket.setSoTimeout(5000);
|
||||
try {
|
||||
OutputStream os = socket.getOutputStream();
|
||||
out = new OutputStreamWriter(os, "UTF-8");
|
||||
Log.v(logTag, "Connected");
|
||||
InputStream is = socket.getInputStream();
|
||||
in = new BufferedReader(new InputStreamReader(is));
|
||||
|
||||
publishProgress(5);
|
||||
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
requests[i].setID(reqID++);
|
||||
doRequest(requests[i]);
|
||||
publishProgress(5 + 90 * (i + 1) / requests.length);
|
||||
}
|
||||
|
||||
publishProgress(100);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(logTag, "Error: ", e);
|
||||
} finally {
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(logTag, "Error: ", e);
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.get(i).error = e.toString();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private void doRequest(Electrum_Request request) {
|
||||
try {
|
||||
|
||||
Log.v(logTag, "<< " + request.getAsString());
|
||||
|
||||
out.write(request.getAsString() + "\n");
|
||||
out.flush();
|
||||
|
||||
request.answerData = in.readLine();
|
||||
request.Host=Host;
|
||||
request.Port=Port;
|
||||
if (request.answerData != null) {
|
||||
Log.v(logTag, ">> " + request.answerData);
|
||||
} else {
|
||||
request.error = "No answer from server";
|
||||
Log.v(logTag, ">> <NULL>");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
request.error = e.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public String getValidationNodeDescription() {
|
||||
return "Electrum, "+Host+":"+String.valueOf(Port);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,66 +1,66 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 16.01.2018.
|
||||
*/
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.tangem.wallet.ExchangeRequest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class ExchangeTask extends AsyncTask<ExchangeRequest, Void, List<ExchangeRequest>> {
|
||||
public ExchangeTask()
|
||||
{
|
||||
|
||||
}
|
||||
protected List<ExchangeRequest> doInBackground(ExchangeRequest... requests) {
|
||||
List<ExchangeRequest> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (ExchangeRequest request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
|
||||
URL url = new URL("https://api.coinmarketcap.com/v1/ticker/?convert=USD&lmit=10");
|
||||
httpcon = (HttpURLConnection) url.openConnection();
|
||||
httpcon.setRequestMethod("GET");
|
||||
|
||||
httpcon.connect();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
package com.tangem.data.network.task;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 16.01.2018.
|
||||
*/
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.tangem.data.network.request.ExchangeRequest;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class ExchangeTask extends AsyncTask<ExchangeRequest, Void, List<ExchangeRequest>> {
|
||||
public ExchangeTask()
|
||||
{
|
||||
|
||||
}
|
||||
protected List<ExchangeRequest> doInBackground(ExchangeRequest... requests) {
|
||||
List<ExchangeRequest> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (ExchangeRequest request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
|
||||
URL url = new URL("https://api.coinmarketcap.com/v1/ticker/?convert=USD&lmit=10");
|
||||
httpcon = (HttpURLConnection) url.openConnection();
|
||||
httpcon.setRequestMethod("GET");
|
||||
|
||||
httpcon.connect();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,63 +1,66 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class Fee_Task extends AsyncTask<Fee_Request, Void, List<Fee_Request>> {
|
||||
|
||||
public SharedData sharedCounter = null;
|
||||
|
||||
public Fee_Task(SharedData sharedData)
|
||||
{
|
||||
sharedCounter = sharedData;
|
||||
}
|
||||
protected List<Fee_Request> doInBackground(Fee_Request... requests) {
|
||||
List<Fee_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (Fee_Request request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
|
||||
URL url = new URL("https://estimatefee.com/n/"+String.valueOf(request.getBlockCount()));
|
||||
httpcon = (HttpURLConnection) url.openConnection();
|
||||
httpcon.setRequestMethod("GET");
|
||||
|
||||
httpcon.connect();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
package com.tangem.data.network.task;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.tangem.wallet.Fee_Request;
|
||||
import com.tangem.wallet.SharedData;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class Fee_Task extends AsyncTask<Fee_Request, Void, List<Fee_Request>> {
|
||||
|
||||
public SharedData sharedCounter = null;
|
||||
|
||||
public Fee_Task(SharedData sharedData)
|
||||
{
|
||||
sharedCounter = sharedData;
|
||||
}
|
||||
protected List<Fee_Request> doInBackground(Fee_Request... requests) {
|
||||
List<Fee_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (Fee_Request request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
|
||||
URL url = new URL("https://estimatefee.com/n/"+String.valueOf(request.getBlockCount()));
|
||||
httpcon = (HttpURLConnection) url.openConnection();
|
||||
httpcon.setRequestMethod("GET");
|
||||
|
||||
httpcon.connect();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,134 +1,137 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 19.12.2017.
|
||||
*/
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class Infura_Task extends AsyncTask<Infura_Request, Void, List<Infura_Request>> {
|
||||
private Exception exception;
|
||||
private Blockchain blockchain;
|
||||
public Infura_Task(Blockchain blockchainNet)
|
||||
{
|
||||
blockchain = blockchainNet;
|
||||
}
|
||||
boolean useOurNode = false;
|
||||
protected List<Infura_Request> doInBackground(Infura_Request... requests) {
|
||||
List<Infura_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (Infura_Request request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
URL url = new URL("https://rinkeby.infura.io/AfWg0tmYEX5Kukn2UkKV");
|
||||
|
||||
if(blockchain == Blockchain.Ethereum || blockchain == Blockchain.Token){
|
||||
if(useOurNode) {
|
||||
URL tmp = new URL("http://52.230.23.88");
|
||||
url = new URL(tmp.getProtocol(), tmp.getHost(), 27172, tmp.getFile());
|
||||
}else
|
||||
url = new URL("https://mainnet.infura.io/AfWg0tmYEX5Kukn2UkKV");
|
||||
|
||||
}
|
||||
|
||||
if(useOurNode)
|
||||
{
|
||||
httpcon = (HttpURLConnection)url.openConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
httpcon = (HttpsURLConnection)url.openConnection();
|
||||
}
|
||||
|
||||
if(httpcon == null)
|
||||
{
|
||||
request.error = String.format("Cann't connect to %s", url.getHost());
|
||||
return result;
|
||||
}
|
||||
|
||||
httpcon.setRequestMethod("POST");
|
||||
httpcon.setRequestProperty("Content-Type", "application/json");
|
||||
String params = request.getAsString();
|
||||
|
||||
OutputStream os = httpcon.getOutputStream();
|
||||
if(os == null)
|
||||
{
|
||||
request.error = String.format("Cann't recieve data from %s", url.getHost());
|
||||
return result;
|
||||
}
|
||||
BufferedWriter writer = new BufferedWriter(
|
||||
new OutputStreamWriter(os, "UTF-8"));
|
||||
if(writer == null)
|
||||
{
|
||||
request.error = String.format("Cann't send data to %s", url.getHost());
|
||||
|
||||
}
|
||||
writer.write(params);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
os.close();
|
||||
|
||||
|
||||
httpcon.connect();
|
||||
request.getParams();
|
||||
System.out.println("code:"+httpcon.getResponseCode());
|
||||
int code = httpcon.getResponseCode();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
this.exception = e;
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getValidationNodeDescription() {
|
||||
if(blockchain == Blockchain.Ethereum || blockchain == Blockchain.Token)
|
||||
{
|
||||
if(useOurNode)
|
||||
return "52.230.23.88:27172";
|
||||
else
|
||||
return "Infura, infura.io";
|
||||
}
|
||||
|
||||
|
||||
return "Infura, rinkeby.infura.io";
|
||||
}
|
||||
|
||||
}
|
||||
package com.tangem.data.network.task;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 19.12.2017.
|
||||
*/
|
||||
|
||||
import android.os.AsyncTask;
|
||||
|
||||
import com.tangem.wallet.Blockchain;
|
||||
import com.tangem.wallet.Infura_Request;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
||||
/**
|
||||
* Created by Ilia on 04.12.2017.
|
||||
*/
|
||||
|
||||
public class Infura_Task extends AsyncTask<Infura_Request, Void, List<Infura_Request>> {
|
||||
private Exception exception;
|
||||
private Blockchain blockchain;
|
||||
public Infura_Task(Blockchain blockchainNet)
|
||||
{
|
||||
blockchain = blockchainNet;
|
||||
}
|
||||
boolean useOurNode = false;
|
||||
protected List<Infura_Request> doInBackground(Infura_Request... requests) {
|
||||
List<Infura_Request> result = new ArrayList<>();
|
||||
for (int i = 0; i < requests.length; i++) {
|
||||
result.add(requests[i]);
|
||||
}
|
||||
|
||||
for (Infura_Request request: result)
|
||||
{
|
||||
HttpURLConnection httpcon = null;
|
||||
|
||||
try {
|
||||
URL url = new URL("https://rinkeby.infura.io/AfWg0tmYEX5Kukn2UkKV");
|
||||
|
||||
if(blockchain == Blockchain.Ethereum || blockchain == Blockchain.Token){
|
||||
if(useOurNode) {
|
||||
URL tmp = new URL("http://52.230.23.88");
|
||||
url = new URL(tmp.getProtocol(), tmp.getHost(), 27172, tmp.getFile());
|
||||
}else
|
||||
url = new URL("https://mainnet.infura.io/AfWg0tmYEX5Kukn2UkKV");
|
||||
|
||||
}
|
||||
|
||||
if(useOurNode)
|
||||
{
|
||||
httpcon = (HttpURLConnection)url.openConnection();
|
||||
}
|
||||
else
|
||||
{
|
||||
httpcon = (HttpsURLConnection)url.openConnection();
|
||||
}
|
||||
|
||||
if(httpcon == null)
|
||||
{
|
||||
request.error = String.format("Cann't connect to %s", url.getHost());
|
||||
return result;
|
||||
}
|
||||
|
||||
httpcon.setRequestMethod("POST");
|
||||
httpcon.setRequestProperty("Content-Type", "application/json");
|
||||
String params = request.getAsString();
|
||||
|
||||
OutputStream os = httpcon.getOutputStream();
|
||||
if(os == null)
|
||||
{
|
||||
request.error = String.format("Cann't recieve data from %s", url.getHost());
|
||||
return result;
|
||||
}
|
||||
BufferedWriter writer = new BufferedWriter(
|
||||
new OutputStreamWriter(os, "UTF-8"));
|
||||
if(writer == null)
|
||||
{
|
||||
request.error = String.format("Cann't send data to %s", url.getHost());
|
||||
|
||||
}
|
||||
writer.write(params);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
os.close();
|
||||
|
||||
|
||||
httpcon.connect();
|
||||
request.getParams();
|
||||
System.out.println("code:"+httpcon.getResponseCode());
|
||||
int code = httpcon.getResponseCode();
|
||||
|
||||
BufferedReader in = new BufferedReader(
|
||||
new InputStreamReader(httpcon.getInputStream()));
|
||||
String inputLine;
|
||||
StringBuffer response = new StringBuffer();
|
||||
|
||||
while ((inputLine = in.readLine()) != null) {
|
||||
response.append(inputLine);
|
||||
}
|
||||
in.close();
|
||||
|
||||
request.answerData = response.toString();
|
||||
|
||||
} catch (Exception e) {
|
||||
this.exception = e;
|
||||
request.error = e.getMessage();
|
||||
} finally {
|
||||
httpcon.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getValidationNodeDescription() {
|
||||
if(blockchain == Blockchain.Ethereum || blockchain == Blockchain.Token)
|
||||
{
|
||||
if(useOurNode)
|
||||
return "52.230.23.88:27172";
|
||||
else
|
||||
return "Infura, infura.io";
|
||||
}
|
||||
|
||||
|
||||
return "Infura, rinkeby.infura.io";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,238 +1,238 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
import org.spongycastle.asn1.DERSequence;
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.spongycastle.jce.spec.ECPrivateKeySpec;
|
||||
import org.spongycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* Created by dvol on 14.11.2017.
|
||||
*/
|
||||
|
||||
public class CardCrypto {
|
||||
public static PublicKey LoadPublicKey(byte[] publicKeyArray) throws Exception {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
KeyFactory factory = KeyFactory.getInstance("EC", "SC");
|
||||
|
||||
ECPoint p1 = spec.getCurve().decodePoint(publicKeyArray);
|
||||
ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec);
|
||||
|
||||
return factory.generatePublic(keySpec);
|
||||
}
|
||||
|
||||
public static boolean VerifySignature(byte[] publicKeyArray, byte[] data, byte[] signature) throws Exception {
|
||||
Signature signatureInstance = Signature.getInstance("SHA256withECDSA");
|
||||
PublicKey publicKey = LoadPublicKey(publicKeyArray);
|
||||
signatureInstance.initVerify(publicKey);
|
||||
signatureInstance.update(data);
|
||||
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
int size = signature.length / 2;
|
||||
v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, 0, size))));
|
||||
v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, size, size * 2))));
|
||||
byte[] sigDer = new DERSequence(v).getEncoded();
|
||||
|
||||
return signatureInstance.verify(sigDer);
|
||||
}
|
||||
|
||||
|
||||
// public static boolean isCanonical(BigInteger s) {
|
||||
//
|
||||
// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
//
|
||||
// BigInteger HALF_CURVE_ORDER = spec.getN().shiftRight(1);
|
||||
// return s.compareTo(HALF_CURVE_ORDER) <= 0;
|
||||
// }
|
||||
//
|
||||
// public static BigInteger toCanonicalised(BigInteger s) {
|
||||
//
|
||||
// // The order of the curve is the number of valid points that exist on that curve. If S is in the upper
|
||||
// // half of the number of valid points, then bring it back to the lower half. Otherwise, imagine that
|
||||
// // N = 10
|
||||
// // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions.
|
||||
// // 10 - 8 == 2, giving us always the latter solution, which is canonical.
|
||||
// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
// if(!isCanonical(s)) {
|
||||
// BigInteger canon = spec.getN().subtract(s);
|
||||
// //Log.e("TX_SIGN", "non Canonical S");
|
||||
// return canon;
|
||||
// }
|
||||
//
|
||||
// return s;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static BigInteger[] calcSign2(byte[] priv, byte[] hash)
|
||||
// {
|
||||
// ECDSASigner signer = new ECDSASigner();
|
||||
// BigInteger d = new BigInteger(priv);
|
||||
//
|
||||
// ECNamedCurveParameterSpec CURVE_PARAMS = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
// ECDomainParameters CURVE = new ECDomainParameters(CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(),
|
||||
// CURVE_PARAMS.getH());
|
||||
// ECPrivateKeyParameters params = new ECPrivateKeyParameters(d, CURVE);
|
||||
// //ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
|
||||
// signer.init(true, params);
|
||||
// BigInteger[] rs = signer.generateSignature(hash);
|
||||
// return rs;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static byte[] Signature3(byte[] privateKeyArray, byte[] data) throws Exception
|
||||
// {
|
||||
// byte[] hash=Util.calculateSHA256(data);
|
||||
// BigInteger[] signBI=calcSign2(privateKeyArray, hash);
|
||||
// //signBI[0]=toCanonicalised(signBI[0]);
|
||||
// signBI[1]=toCanonicalised(signBI[1]);
|
||||
// byte[] r = signBI[0].toByteArray();
|
||||
// byte[] s = signBI[1].toByteArray();
|
||||
//
|
||||
// byte[] res = new byte[64];
|
||||
// if( r.length==32 ) {
|
||||
// System.arraycopy(r, 0, res, 0, r.length);
|
||||
// }else if( r.length==33 && r[0]==0 ){
|
||||
// System.arraycopy(r, 1, res, 0, r.length-1);
|
||||
// }else {
|
||||
// throw new Exception("unsupported r-length");
|
||||
// }
|
||||
// if( s.length==32 ) {
|
||||
// System.arraycopy(s, 0, res, 32, 32);
|
||||
// }else{
|
||||
// throw new Exception("unsupported s-length");
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
|
||||
public static byte[] Signature(byte[] privateKeyArray, byte[] data) throws Exception {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
KeyFactory factory = KeyFactory.getInstance("EC", "SC");
|
||||
|
||||
ECPrivateKeySpec keySpecP = new ECPrivateKeySpec(new BigInteger(1,privateKeyArray), spec);
|
||||
|
||||
Signature signature = Signature.getInstance("SHA256withECDSA");
|
||||
|
||||
PrivateKey privateKey = factory.generatePrivate(keySpecP);
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data);
|
||||
byte[] enc = signature.sign();
|
||||
|
||||
if (enc[0] != 0x30) throw new Exception("bad encoding 1");
|
||||
if ((enc[1] & 0x80) != 0) throw new Exception("unsupported length encoding 1");
|
||||
if (enc[2] != 0x02) throw new Exception("bad encoding 2");
|
||||
if ((enc[3] & 0x80) != 0) throw new Exception("unsupported length encoding 2");
|
||||
int rLength = enc[3];
|
||||
|
||||
if (enc[4 + rLength] != 0x02) throw new Exception("bad encoding 3");
|
||||
if ((enc[5 + rLength] & 0x80) != 0) throw new Exception("unsupported length encoding 3");
|
||||
int sLength = enc[5 + rLength];
|
||||
|
||||
|
||||
int sPos = 6 + rLength;
|
||||
byte[] res = new byte[64];
|
||||
if (rLength <= 32) {
|
||||
System.arraycopy(enc, 4, res, 32-rLength, rLength);
|
||||
rLength=32;
|
||||
} else if (rLength == 33 && enc[4] == 0) {
|
||||
rLength--;
|
||||
System.arraycopy(enc, 5, res, 0, rLength);
|
||||
} else {
|
||||
Log.e("cardCrypto","r-length:" + String.valueOf(rLength));
|
||||
Log.e("cardCrypto","s-length:" + String.valueOf(sLength));
|
||||
Log.e("cardCrypto","enc:" +Util.bytesToHex(enc));
|
||||
throw new Exception("unsupported r-length - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc));
|
||||
}
|
||||
if (sLength <= 32) {
|
||||
System.arraycopy(enc, sPos, res, rLength+32-sLength, sLength);
|
||||
sLength=32;
|
||||
} else if (sLength == 33 && enc[sPos] == 0) {
|
||||
System.arraycopy(enc, sPos + 1, res, rLength, sLength - 1);
|
||||
} else {
|
||||
Log.e("cardCrypto","s-length:" + String.valueOf(sLength));
|
||||
Log.e("cardCrypto","r-length:" + String.valueOf(rLength));
|
||||
Log.e("cardCrypto","enc:" +Util.bytesToHex(enc));
|
||||
throw new Exception("unsupported s-length - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc));
|
||||
}
|
||||
|
||||
if(!VerifySignature(GeneratePublicKey(privateKeyArray), data, res))
|
||||
{
|
||||
throw new Exception("Signature self verify failed - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc)+",res:"+Util.bytesToHex(res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static byte[] GeneratePublicKey(byte[] privateKeyArray) throws NoSuchProviderException, NoSuchAlgorithmException {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
|
||||
|
||||
byte[] publicKeyArray = spec.getG().multiply(new BigInteger(1,privateKeyArray)).getEncoded(false);
|
||||
|
||||
return publicKeyArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the PBKDF2 hash of a password.
|
||||
*
|
||||
* @param password the password to hash.
|
||||
* @param salt the salt
|
||||
* @param iterations the iteration count (slowness factor)
|
||||
* @return the PBDKF2 hash of the password
|
||||
*/
|
||||
public static byte[] pbkdf2(byte[] password, byte[] salt, int iterations)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
|
||||
return PBKDF2.deriveKey(password, salt, iterations);
|
||||
}
|
||||
|
||||
public static byte[] Encrypt(byte[] key, byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
|
||||
{
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/PKCS7PADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] mEncryptedData = cipher.doFinal(data);
|
||||
return mEncryptedData;
|
||||
}
|
||||
|
||||
public static byte[] Decrypt(byte[] key, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
|
||||
try {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/PKCS7PADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] decryptedData = cipher.doFinal(Arrays.copyOfRange(data, 0, data.length ));
|
||||
return decryptedData;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/NOPADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] decryptedData = cipher.doFinal(Arrays.copyOfRange(data, 0, data.length ));
|
||||
Log.e("decrypt",Util.bytesToHex(decryptedData));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
import org.spongycastle.asn1.DERSequence;
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.spongycastle.jce.spec.ECPrivateKeySpec;
|
||||
import org.spongycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
/**
|
||||
* Created by dvol on 14.11.2017.
|
||||
*/
|
||||
|
||||
public class CardCrypto {
|
||||
public static PublicKey LoadPublicKey(byte[] publicKeyArray) throws Exception {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
KeyFactory factory = KeyFactory.getInstance("EC", "SC");
|
||||
|
||||
ECPoint p1 = spec.getCurve().decodePoint(publicKeyArray);
|
||||
ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec);
|
||||
|
||||
return factory.generatePublic(keySpec);
|
||||
}
|
||||
|
||||
public static boolean VerifySignature(byte[] publicKeyArray, byte[] data, byte[] signature) throws Exception {
|
||||
Signature signatureInstance = Signature.getInstance("SHA256withECDSA");
|
||||
PublicKey publicKey = LoadPublicKey(publicKeyArray);
|
||||
signatureInstance.initVerify(publicKey);
|
||||
signatureInstance.update(data);
|
||||
|
||||
ASN1EncodableVector v = new ASN1EncodableVector();
|
||||
int size = signature.length / 2;
|
||||
v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, 0, size))));
|
||||
v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(signature, size, size * 2))));
|
||||
byte[] sigDer = new DERSequence(v).getEncoded();
|
||||
|
||||
return signatureInstance.verify(sigDer);
|
||||
}
|
||||
|
||||
|
||||
// public static boolean isCanonical(BigInteger s) {
|
||||
//
|
||||
// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
//
|
||||
// BigInteger HALF_CURVE_ORDER = spec.getN().shiftRight(1);
|
||||
// return s.compareTo(HALF_CURVE_ORDER) <= 0;
|
||||
// }
|
||||
//
|
||||
// public static BigInteger toCanonicalised(BigInteger s) {
|
||||
//
|
||||
// // The order of the curve is the number of valid points that exist on that curve. If S is in the upper
|
||||
// // half of the number of valid points, then bring it back to the lower half. Otherwise, imagine that
|
||||
// // N = 10
|
||||
// // s = 8, so (-8 % 10 == 2) thus both (r, 8) and (r, 2) are valid solutions.
|
||||
// // 10 - 8 == 2, giving us always the latter solution, which is canonical.
|
||||
// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
// if(!isCanonical(s)) {
|
||||
// BigInteger canon = spec.getN().subtract(s);
|
||||
// //Log.e("TX_SIGN", "non Canonical S");
|
||||
// return canon;
|
||||
// }
|
||||
//
|
||||
// return s;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static BigInteger[] calcSign2(byte[] priv, byte[] hash)
|
||||
// {
|
||||
// ECDSASigner signer = new ECDSASigner();
|
||||
// BigInteger d = new BigInteger(priv);
|
||||
//
|
||||
// ECNamedCurveParameterSpec CURVE_PARAMS = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
// ECDomainParameters CURVE = new ECDomainParameters(CURVE_PARAMS.getCurve(), CURVE_PARAMS.getG(), CURVE_PARAMS.getN(),
|
||||
// CURVE_PARAMS.getH());
|
||||
// ECPrivateKeyParameters params = new ECPrivateKeyParameters(d, CURVE);
|
||||
// //ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE);
|
||||
// signer.init(true, params);
|
||||
// BigInteger[] rs = signer.generateSignature(hash);
|
||||
// return rs;
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public static byte[] Signature3(byte[] privateKeyArray, byte[] data) throws Exception
|
||||
// {
|
||||
// byte[] hash=Util.calculateSHA256(data);
|
||||
// BigInteger[] signBI=calcSign2(privateKeyArray, hash);
|
||||
// //signBI[0]=toCanonicalised(signBI[0]);
|
||||
// signBI[1]=toCanonicalised(signBI[1]);
|
||||
// byte[] r = signBI[0].toByteArray();
|
||||
// byte[] s = signBI[1].toByteArray();
|
||||
//
|
||||
// byte[] res = new byte[64];
|
||||
// if( r.length==32 ) {
|
||||
// System.arraycopy(r, 0, res, 0, r.length);
|
||||
// }else if( r.length==33 && r[0]==0 ){
|
||||
// System.arraycopy(r, 1, res, 0, r.length-1);
|
||||
// }else {
|
||||
// throw new Exception("unsupported r-length");
|
||||
// }
|
||||
// if( s.length==32 ) {
|
||||
// System.arraycopy(s, 0, res, 32, 32);
|
||||
// }else{
|
||||
// throw new Exception("unsupported s-length");
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
|
||||
public static byte[] Signature(byte[] privateKeyArray, byte[] data) throws Exception {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
KeyFactory factory = KeyFactory.getInstance("EC", "SC");
|
||||
|
||||
ECPrivateKeySpec keySpecP = new ECPrivateKeySpec(new BigInteger(1,privateKeyArray), spec);
|
||||
|
||||
Signature signature = Signature.getInstance("SHA256withECDSA");
|
||||
|
||||
PrivateKey privateKey = factory.generatePrivate(keySpecP);
|
||||
signature.initSign(privateKey);
|
||||
signature.update(data);
|
||||
byte[] enc = signature.sign();
|
||||
|
||||
if (enc[0] != 0x30) throw new Exception("bad encoding 1");
|
||||
if ((enc[1] & 0x80) != 0) throw new Exception("unsupported length encoding 1");
|
||||
if (enc[2] != 0x02) throw new Exception("bad encoding 2");
|
||||
if ((enc[3] & 0x80) != 0) throw new Exception("unsupported length encoding 2");
|
||||
int rLength = enc[3];
|
||||
|
||||
if (enc[4 + rLength] != 0x02) throw new Exception("bad encoding 3");
|
||||
if ((enc[5 + rLength] & 0x80) != 0) throw new Exception("unsupported length encoding 3");
|
||||
int sLength = enc[5 + rLength];
|
||||
|
||||
|
||||
int sPos = 6 + rLength;
|
||||
byte[] res = new byte[64];
|
||||
if (rLength <= 32) {
|
||||
System.arraycopy(enc, 4, res, 32-rLength, rLength);
|
||||
rLength=32;
|
||||
} else if (rLength == 33 && enc[4] == 0) {
|
||||
rLength--;
|
||||
System.arraycopy(enc, 5, res, 0, rLength);
|
||||
} else {
|
||||
Log.e("cardCrypto","r-length:" + String.valueOf(rLength));
|
||||
Log.e("cardCrypto","s-length:" + String.valueOf(sLength));
|
||||
Log.e("cardCrypto","enc:" +Util.bytesToHex(enc));
|
||||
throw new Exception("unsupported r-length - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc));
|
||||
}
|
||||
if (sLength <= 32) {
|
||||
System.arraycopy(enc, sPos, res, rLength+32-sLength, sLength);
|
||||
sLength=32;
|
||||
} else if (sLength == 33 && enc[sPos] == 0) {
|
||||
System.arraycopy(enc, sPos + 1, res, rLength, sLength - 1);
|
||||
} else {
|
||||
Log.e("cardCrypto","s-length:" + String.valueOf(sLength));
|
||||
Log.e("cardCrypto","r-length:" + String.valueOf(rLength));
|
||||
Log.e("cardCrypto","enc:" +Util.bytesToHex(enc));
|
||||
throw new Exception("unsupported s-length - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc));
|
||||
}
|
||||
|
||||
if(!VerifySignature(GeneratePublicKey(privateKeyArray), data, res))
|
||||
{
|
||||
throw new Exception("Signature self verify failed - r-length:" + String.valueOf(rLength)+",s-length:" + String.valueOf(sLength)+",enc:" +Util.bytesToHex(enc)+",res:"+Util.bytesToHex(res));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static byte[] GeneratePublicKey(byte[] privateKeyArray) throws NoSuchProviderException, NoSuchAlgorithmException {
|
||||
ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1");
|
||||
|
||||
|
||||
byte[] publicKeyArray = spec.getG().multiply(new BigInteger(1,privateKeyArray)).getEncoded(false);
|
||||
|
||||
return publicKeyArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the PBKDF2 hash of a password.
|
||||
*
|
||||
* @param password the password to hash.
|
||||
* @param salt the salt
|
||||
* @param iterations the iteration count (slowness factor)
|
||||
* @return the PBDKF2 hash of the password
|
||||
*/
|
||||
public static byte[] pbkdf2(byte[] password, byte[] salt, int iterations)
|
||||
throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException {
|
||||
return PBKDF2.deriveKey(password, salt, iterations);
|
||||
}
|
||||
|
||||
public static byte[] Encrypt(byte[] key, byte[] data) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
|
||||
{
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/PKCS7PADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] mEncryptedData = cipher.doFinal(data);
|
||||
return mEncryptedData;
|
||||
}
|
||||
|
||||
public static byte[] Decrypt(byte[] key, byte[] data) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
|
||||
try {
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/PKCS7PADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] decryptedData = cipher.doFinal(Arrays.copyOfRange(data, 0, data.length ));
|
||||
return decryptedData;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES/CBC/NOPADDING");
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
|
||||
cipher.init(Cipher.DECRYPT_MODE, skeySpec, new IvParameterSpec(new byte[16]));
|
||||
byte[] decryptedData = cipher.doFinal(Arrays.copyOfRange(data, 0, data.length ));
|
||||
Log.e("decrypt",Util.bytesToHex(decryptedData));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.cardReader;
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.cardReader;
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import android.content.Context;
|
||||
import android.nfc.TagLostException;
|
||||
|
|
@ -1,43 +1,43 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
public enum INS {
|
||||
Unknown(0x00),
|
||||
BootROM_SOS(0x40),
|
||||
BootROM_Tangem(0xF0),
|
||||
Personalize(0xF1),
|
||||
Read(0xF2),
|
||||
VerifyCard(0xF3),
|
||||
ValidateCard(0xF4),
|
||||
VerifyCode(0xF5),
|
||||
WriteIssuerData(0xF6),
|
||||
GetIssuerData(0xF7),
|
||||
CreateWallet(0xF8),
|
||||
CheckWallet(0xF9),
|
||||
SwapPIN(0xFA),
|
||||
Sign(0xFB),
|
||||
PurgeWallet(0xFC),
|
||||
Activate(0xFE),
|
||||
OpenSession(0xFF),
|
||||
ReadBlockedData(0xE4),
|
||||
CreateTestWallet(0xE0),
|
||||
ExtractWalletKey(0xE1),
|
||||
Test(0xE2),
|
||||
Depersonalize(0xE3);
|
||||
|
||||
INS(int Code) {
|
||||
this.Code = Code;
|
||||
}
|
||||
|
||||
public int Code;
|
||||
|
||||
public static INS ByCode(int Code) {
|
||||
INS[] allINS = INS.values();
|
||||
for (INS i : allINS) {
|
||||
if (i.Code == Code) return i;
|
||||
}
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
public enum INS {
|
||||
Unknown(0x00),
|
||||
BootROM_SOS(0x40),
|
||||
BootROM_Tangem(0xF0),
|
||||
Personalize(0xF1),
|
||||
Read(0xF2),
|
||||
VerifyCard(0xF3),
|
||||
ValidateCard(0xF4),
|
||||
VerifyCode(0xF5),
|
||||
WriteIssuerData(0xF6),
|
||||
GetIssuerData(0xF7),
|
||||
CreateWallet(0xF8),
|
||||
CheckWallet(0xF9),
|
||||
SwapPIN(0xFA),
|
||||
Sign(0xFB),
|
||||
PurgeWallet(0xFC),
|
||||
Activate(0xFE),
|
||||
OpenSession(0xFF),
|
||||
ReadBlockedData(0xE4),
|
||||
CreateTestWallet(0xE0),
|
||||
ExtractWalletKey(0xE1),
|
||||
Test(0xE2),
|
||||
Depersonalize(0xE3);
|
||||
|
||||
INS(int Code) {
|
||||
this.Code = Code;
|
||||
}
|
||||
|
||||
public int Code;
|
||||
|
||||
public static INS ByCode(int Code) {
|
||||
INS[] allINS = INS.values();
|
||||
for (INS i : allINS) {
|
||||
if (i.Code == Code) return i;
|
||||
}
|
||||
return Unknown;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,153 +1,155 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NfcManager {
|
||||
|
||||
private static final String TAG = "NfcManager";
|
||||
|
||||
|
||||
// reader mode flags: listen for type A (not B), skipping ndef check
|
||||
private static final int READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS;
|
||||
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private NFCEnableDialog mEnableNfcDialog;
|
||||
private Activity mActivity;
|
||||
private NfcAdapter.ReaderCallback mReaderCallback;
|
||||
|
||||
private boolean broadcomWorkaround = false;
|
||||
private static final int DELAY_PRESENCE = 1500;
|
||||
|
||||
public NfcManager(Activity activity, NfcAdapter.ReaderCallback readerCallback) {
|
||||
mActivity = activity;
|
||||
mReaderCallback = readerCallback;
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
// register broadcast receiver
|
||||
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
|
||||
mActivity.registerReceiver(mBroadcastReceiver, filter);
|
||||
|
||||
if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
|
||||
ShowNFCEnableDialog();
|
||||
|
||||
} else {
|
||||
enableReaderMode();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowNFCEnableDialog() {
|
||||
mEnableNfcDialog=new NFCEnableDialog();
|
||||
mEnableNfcDialog.show(mActivity.getFragmentManager(),"NFCEnableDialog");
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
mActivity.unregisterReceiver(mBroadcastReceiver);
|
||||
disableReaderMode();
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
if (mEnableNfcDialog != null) {
|
||||
mEnableNfcDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void IgnoreTag(Tag tag) throws IOException {
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
// mNfcAdapter.ignore(tag, 500, null, null);
|
||||
// }else{
|
||||
IsoDep isoDep = IsoDep.get(tag);
|
||||
if (isoDep != null) {
|
||||
isoDep.close();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action == null)
|
||||
return;
|
||||
if (action.equals(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)) {
|
||||
int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
|
||||
NfcAdapter.STATE_ON);
|
||||
if (state == NfcAdapter.STATE_ON
|
||||
|| state == NfcAdapter.STATE_TURNING_ON) {
|
||||
Log.d(TAG, "state: " + state + " , dialog: "
|
||||
+ mEnableNfcDialog);
|
||||
if (mEnableNfcDialog != null) {
|
||||
mEnableNfcDialog.dismiss();
|
||||
}
|
||||
if (state == NfcAdapter.STATE_ON) {
|
||||
enableReaderMode();
|
||||
}
|
||||
} else {
|
||||
if (mEnableNfcDialog == null || !mEnableNfcDialog.isVisible()) {
|
||||
ShowNFCEnableDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private void enableReaderMode() {
|
||||
Bundle options = new Bundle();
|
||||
if (broadcomWorkaround) {
|
||||
/* This is a work around for some Broadcom chipsets that does
|
||||
* the presence check by sending commands that interrupt the
|
||||
* processing of the ongoing command.
|
||||
*/
|
||||
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, DELAY_PRESENCE);
|
||||
}
|
||||
mNfcAdapter.enableReaderMode(mActivity, mReaderCallback, READER_FLAGS, options);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private void disableReaderMode() {
|
||||
if (mNfcAdapter != null) {
|
||||
mNfcAdapter.disableReaderMode(mActivity);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int REQUEST_NFC_PERMISSIONS = 1;
|
||||
private static String[] PERMISSIONS_NFC = {
|
||||
Manifest.permission.NFC
|
||||
};
|
||||
|
||||
//Checks if the app has NFC permission
|
||||
//If the app does not has permission then the user will be prompted to grant permissions
|
||||
public static void verifyPermissions(Activity activity) {
|
||||
// Check if we have write permission
|
||||
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.NFC);
|
||||
|
||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
||||
// We don't have permission so prompt the user
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
PERMISSIONS_NFC,
|
||||
REQUEST_NFC_PERMISSIONS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.nfc.tech.IsoDep;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.presentation.dialog.NFCEnableDialog;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NfcManager {
|
||||
|
||||
private static final String TAG = "NfcManager";
|
||||
|
||||
|
||||
// reader mode flags: listen for type A (not B), skipping ndef check
|
||||
private static final int READER_FLAGS = NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK | NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS;
|
||||
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private NFCEnableDialog mEnableNfcDialog;
|
||||
private Activity mActivity;
|
||||
private NfcAdapter.ReaderCallback mReaderCallback;
|
||||
|
||||
private boolean broadcomWorkaround = false;
|
||||
private static final int DELAY_PRESENCE = 1500;
|
||||
|
||||
public NfcManager(Activity activity, NfcAdapter.ReaderCallback readerCallback) {
|
||||
mActivity = activity;
|
||||
mReaderCallback = readerCallback;
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
// register broadcast receiver
|
||||
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED);
|
||||
mActivity.registerReceiver(mBroadcastReceiver, filter);
|
||||
|
||||
if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
|
||||
ShowNFCEnableDialog();
|
||||
|
||||
} else {
|
||||
enableReaderMode();
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowNFCEnableDialog() {
|
||||
mEnableNfcDialog=new NFCEnableDialog();
|
||||
mEnableNfcDialog.show(mActivity.getFragmentManager(),"NFCEnableDialog");
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
mActivity.unregisterReceiver(mBroadcastReceiver);
|
||||
disableReaderMode();
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
if (mEnableNfcDialog != null) {
|
||||
mEnableNfcDialog.dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
public void IgnoreTag(Tag tag) throws IOException {
|
||||
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
// mNfcAdapter.ignore(tag, 500, null, null);
|
||||
// }else{
|
||||
IsoDep isoDep = IsoDep.get(tag);
|
||||
if (isoDep != null) {
|
||||
isoDep.close();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action == null)
|
||||
return;
|
||||
if (action.equals(NfcAdapter.ACTION_ADAPTER_STATE_CHANGED)) {
|
||||
int state = intent.getIntExtra(NfcAdapter.EXTRA_ADAPTER_STATE,
|
||||
NfcAdapter.STATE_ON);
|
||||
if (state == NfcAdapter.STATE_ON
|
||||
|| state == NfcAdapter.STATE_TURNING_ON) {
|
||||
Log.d(TAG, "state: " + state + " , dialog: "
|
||||
+ mEnableNfcDialog);
|
||||
if (mEnableNfcDialog != null) {
|
||||
mEnableNfcDialog.dismiss();
|
||||
}
|
||||
if (state == NfcAdapter.STATE_ON) {
|
||||
enableReaderMode();
|
||||
}
|
||||
} else {
|
||||
if (mEnableNfcDialog == null || !mEnableNfcDialog.isVisible()) {
|
||||
ShowNFCEnableDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private void enableReaderMode() {
|
||||
Bundle options = new Bundle();
|
||||
if (broadcomWorkaround) {
|
||||
/* This is a work around for some Broadcom chipsets that does
|
||||
* the presence check by sending commands that interrupt the
|
||||
* processing of the ongoing command.
|
||||
*/
|
||||
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, DELAY_PRESENCE);
|
||||
}
|
||||
mNfcAdapter.enableReaderMode(mActivity, mReaderCallback, READER_FLAGS, options);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.KITKAT)
|
||||
private void disableReaderMode() {
|
||||
if (mNfcAdapter != null) {
|
||||
mNfcAdapter.disableReaderMode(mActivity);
|
||||
}
|
||||
}
|
||||
|
||||
private static final int REQUEST_NFC_PERMISSIONS = 1;
|
||||
private static String[] PERMISSIONS_NFC = {
|
||||
Manifest.permission.NFC
|
||||
};
|
||||
|
||||
//Checks if the app has NFC permission
|
||||
//If the app does not has permission then the user will be prompted to grant permissions
|
||||
public static void verifyPermissions(Activity activity) {
|
||||
// Check if we have write permission
|
||||
int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.NFC);
|
||||
|
||||
if (permission != PackageManager.PERMISSION_GRANTED) {
|
||||
// We don't have permission so prompt the user
|
||||
ActivityCompat.requestPermissions(
|
||||
activity,
|
||||
PERMISSIONS_NFC,
|
||||
REQUEST_NFC_PERMISSIONS
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
package com.tangem.cardReader;
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import org.spongycastle.crypto.CipherParameters;
|
||||
import org.spongycastle.crypto.digests.SHA256Digest;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.cardReader;
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.Arrays;
|
||||
|
|
@ -1,43 +1,43 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
|
||||
public class SW {
|
||||
public static final int PROCESS_COMPLETED = 0x9000;
|
||||
public static final int INVALID_PARAMS = 0x6A86;
|
||||
public static final int ERROR_PROCESSING_COMMAND = 0x6286;
|
||||
public static final int INVALID_STATE = 0x6985;
|
||||
public static final int PINS_NOT_CHANGED = PROCESS_COMPLETED;
|
||||
public static final int PIN1_CHANGED = PROCESS_COMPLETED + 0x0001;
|
||||
public static final int PIN2_CHANGED = PROCESS_COMPLETED + 0x0002;
|
||||
public static final int PINS_CHANGED = PROCESS_COMPLETED + 0x0003;
|
||||
public static final int INS_NOT_SUPPORTED = 0x6D00;
|
||||
public static final int NEED_ENCRYPTION = 0x6982;
|
||||
public static final int NEED_PAUSE = 0x9789;
|
||||
|
||||
public static String getDescription(int sw) {
|
||||
switch (sw) {
|
||||
case ERROR_PROCESSING_COMMAND:
|
||||
return "SW_ERROR_PROCESSING_COMMAND";
|
||||
case INVALID_PARAMS:
|
||||
return "SW_INVALID_PARAMS";
|
||||
case INVALID_STATE:
|
||||
return "SW_INVALID_STATE";
|
||||
case INS_NOT_SUPPORTED:
|
||||
return "SW_INS_NOT_SUPPORTED";
|
||||
case NEED_ENCRYPTION:
|
||||
return "SW_NEED_ENCRYPTION";
|
||||
case PIN1_CHANGED:
|
||||
return "SW_PIN1_CHANGED";
|
||||
case PIN2_CHANGED:
|
||||
return "SW_PIN2_CHANGED";
|
||||
case PINS_CHANGED:
|
||||
return "SW_PINS_CHANGED";
|
||||
case PROCESS_COMPLETED:
|
||||
return "SW_PROCESS_COMPLETED";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
|
||||
public class SW {
|
||||
public static final int PROCESS_COMPLETED = 0x9000;
|
||||
public static final int INVALID_PARAMS = 0x6A86;
|
||||
public static final int ERROR_PROCESSING_COMMAND = 0x6286;
|
||||
public static final int INVALID_STATE = 0x6985;
|
||||
public static final int PINS_NOT_CHANGED = PROCESS_COMPLETED;
|
||||
public static final int PIN1_CHANGED = PROCESS_COMPLETED + 0x0001;
|
||||
public static final int PIN2_CHANGED = PROCESS_COMPLETED + 0x0002;
|
||||
public static final int PINS_CHANGED = PROCESS_COMPLETED + 0x0003;
|
||||
public static final int INS_NOT_SUPPORTED = 0x6D00;
|
||||
public static final int NEED_ENCRYPTION = 0x6982;
|
||||
public static final int NEED_PAUSE = 0x9789;
|
||||
|
||||
public static String getDescription(int sw) {
|
||||
switch (sw) {
|
||||
case ERROR_PROCESSING_COMMAND:
|
||||
return "SW_ERROR_PROCESSING_COMMAND";
|
||||
case INVALID_PARAMS:
|
||||
return "SW_INVALID_PARAMS";
|
||||
case INVALID_STATE:
|
||||
return "SW_INVALID_STATE";
|
||||
case INS_NOT_SUPPORTED:
|
||||
return "SW_INS_NOT_SUPPORTED";
|
||||
case NEED_ENCRYPTION:
|
||||
return "SW_NEED_ENCRYPTION";
|
||||
case PIN1_CHANGED:
|
||||
return "SW_PIN1_CHANGED";
|
||||
case PIN2_CHANGED:
|
||||
return "SW_PIN2_CHANGED";
|
||||
case PINS_CHANGED:
|
||||
return "SW_PINS_CHANGED";
|
||||
case PROCESS_COMPLETED:
|
||||
return "SW_PROCESS_COMPLETED";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
|
||||
public class SettingsMask {
|
||||
public static final int IsReusable = 0x0001;
|
||||
public static final int UseActivation = 0x0002;
|
||||
public static final int UseBlock = 0x0008;
|
||||
|
||||
public static final int AllowSwapPIN = 0x0010;
|
||||
public static final int AllowSwapPIN2 = 0x0020;
|
||||
public static final int UseCVC = 0x0040;
|
||||
public static final int ForbidDefaultPIN = 0x0080;
|
||||
|
||||
public static final int UseOneCommandAtTime = 0x0100;
|
||||
public static final int UseNDEF = 0x0200;
|
||||
public static final int UseDynamicNDEF = 0x0400;
|
||||
public static final int SmartSecurityDelay = 0x0800;
|
||||
|
||||
public static final int Protocol_AllowUnencrypted = 0x1000;
|
||||
public static final int Protocol_AllowStaticEncryption = 0x2000;
|
||||
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 07.03.2018.
|
||||
*/
|
||||
|
||||
public class SettingsMask {
|
||||
public static final int IsReusable = 0x0001;
|
||||
public static final int UseActivation = 0x0002;
|
||||
public static final int UseBlock = 0x0008;
|
||||
|
||||
public static final int AllowSwapPIN = 0x0010;
|
||||
public static final int AllowSwapPIN2 = 0x0020;
|
||||
public static final int UseCVC = 0x0040;
|
||||
public static final int ForbidDefaultPIN = 0x0080;
|
||||
|
||||
public static final int UseOneCommandAtTime = 0x0100;
|
||||
public static final int UseNDEF = 0x0200;
|
||||
public static final int UseDynamicNDEF = 0x0400;
|
||||
public static final int SmartSecurityDelay = 0x0800;
|
||||
|
||||
public static final int Protocol_AllowUnencrypted = 0x1000;
|
||||
public static final int Protocol_AllowStaticEncryption = 0x2000;
|
||||
|
||||
}
|
||||
|
|
@ -1,222 +1,222 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by dvol on 23.06.2017.
|
||||
*/
|
||||
|
||||
public class TLV {
|
||||
public enum Tag {
|
||||
TAG_Unknown(0x00),
|
||||
TAG_CardID(0x01),
|
||||
TAG_Status(0x02),
|
||||
TAG_CardPublicKey(0x03),
|
||||
TAG_CardSignature(0x04),
|
||||
TAG_CurveID(0x05),
|
||||
TAG_HashAlgID(0x06),
|
||||
TAG_SigningMethod(0x07),
|
||||
TAG_MaxSignatures(0x08),
|
||||
TAG_PauseBeforePIN2(0x09),
|
||||
TAG_SettingsMask(0x0A),
|
||||
TAG_CardData(0x0C),
|
||||
TAG_NDEFData(0x0D),
|
||||
TAG_CreateWalletAtPersonalize(0x0E),
|
||||
TAG_Health(0x0F),
|
||||
|
||||
TAG_PIN(0x10),
|
||||
TAG_PIN2(0x11),
|
||||
TAG_NewPIN(0x12),
|
||||
TAG_NewPIN2(0x13),
|
||||
TAG_NewPIN_Hash(0x14),
|
||||
TAG_NewPIN2_Hash(0x15),
|
||||
TAG_Challenge(0x16),
|
||||
TAG_Salt(0x17),
|
||||
TAG_ValidationCounter(0x18),
|
||||
TAG_CVC(0x19),
|
||||
|
||||
TAG_Session_Key_A(0x1A),
|
||||
TAG_Session_Key_B(0x1B),
|
||||
TAG_Pause(0x1C),
|
||||
|
||||
TAG_Manufacture_ID(0x20),
|
||||
TAG_Manufacturer_Signature(0x21),
|
||||
|
||||
TAG_Issuer_Data_PublicKey(0x30),
|
||||
TAG_Issuer_Transaction_PublicKey(0x31),
|
||||
TAG_Issuer_Data(0x32),
|
||||
TAG_Issuer_Data_Signature(0x33),
|
||||
TAG_Issuer_Transaction_Signature(0x34),
|
||||
|
||||
TAG_IsActivated(0x3A),
|
||||
TAG_ActivationSeed(0x3B),
|
||||
TAG_ResetPIN(0x36),
|
||||
|
||||
TAG_CodePageAddress(0x40),
|
||||
TAG_CodePageCount(0x41),
|
||||
TAG_CodeHash(0x42),
|
||||
|
||||
TAG_TrOut_Hash(0x50),
|
||||
TAG_TrOut_HashSize(0x51),
|
||||
TAG_TrOut_Raw(0x52),
|
||||
|
||||
TAG_Wallet_PublicKey(0x60),
|
||||
TAG_Signature(0x61),
|
||||
TAG_RemainingSignatures(0x62),
|
||||
TAG_SignedHashes(0x63),
|
||||
|
||||
TAG_Wallet_PrivateKey(0x70),
|
||||
TAG_Card_PrivateKey(0x71),
|
||||
TAG_Block_Reason(0x72),
|
||||
|
||||
|
||||
TAG_Firmware(0x80),
|
||||
TAG_Batch(0x81),
|
||||
TAG_ManufactureDateTime(0x82),
|
||||
TAG_Issuer_ID(0x83),
|
||||
TAG_Blockchain_ID(0x84),
|
||||
TAG_Manufacturer_PublicKey(0x85),
|
||||
TAG_CardID_Manufacturer_Signature(0x86),
|
||||
|
||||
TAG_Token_Symbol(0xA0),
|
||||
TAG_Token_Contract_Address(0xA1),
|
||||
TAG_Token_Decimal(0xA2),
|
||||
TAG_Denomination(/*0xC0*/0xee), //TODO: quick fix
|
||||
TAG_ValidatedBalance(0xC1),
|
||||
TAG_LastSign_Date(0xC2);
|
||||
|
||||
|
||||
Tag(int Code) {
|
||||
this.Code = Code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return Code;
|
||||
}
|
||||
|
||||
private int Code;
|
||||
|
||||
public static Tag ByCode(int Code) {
|
||||
Tag[] allTags = Tag.values();
|
||||
for (Tag t : allTags) if (t.getCode() == Code) return t;
|
||||
return TAG_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private Tag tag;
|
||||
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public byte[] Value;
|
||||
|
||||
public TLV(Tag tag, byte[] value) {
|
||||
this.tag = tag;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public void WriteToStream(ByteArrayOutputStream stream) throws IOException {
|
||||
stream.write(tag.getCode());
|
||||
if (Value != null) {
|
||||
if (Value.length > 0xFE) {
|
||||
stream.write(0xFF);
|
||||
stream.write((Value.length >> 8) & 0xFF);
|
||||
stream.write(Value.length & 0xFF);
|
||||
} else {
|
||||
stream.write(Value.length & 0xFF);
|
||||
}
|
||||
stream.write(Value);
|
||||
} else {
|
||||
stream.write(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
public static TLV ReadFromStream(ByteArrayInputStream stream) throws IOException {
|
||||
int code = stream.read();
|
||||
if (code == -1) return null;
|
||||
int len = stream.read();
|
||||
if (len == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
if (len == 0xFF) {
|
||||
int lenH = stream.read();
|
||||
if (lenH == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
len = stream.read();
|
||||
if (len == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
len |= (lenH << 8);
|
||||
}
|
||||
byte[] value = new byte[len];
|
||||
if (len > 0) {
|
||||
if (len != stream.read(value)) {
|
||||
throw new IOException("Can't read TLV");
|
||||
}
|
||||
}
|
||||
Tag tag = Tag.ByCode(code);
|
||||
TLV result = new TLV(tag, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getAsInt() {
|
||||
return Util.byteArrayToInt(Value);
|
||||
}
|
||||
|
||||
public String getAsHexString() {
|
||||
return Util.bytesToHex(Value);
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
//String s=String.valueOf(Value);
|
||||
if (Value[Value.length - 1] == 0) {
|
||||
String s1 = new String(Arrays.copyOfRange(Value, 0, Value.length - 1), Charset.forName("utf-8"));
|
||||
return s1.trim();
|
||||
} else {
|
||||
String s1 = new String(Value, Charset.forName("utf-8"));
|
||||
return s1.trim();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (tag) {
|
||||
case TAG_CardData:
|
||||
case TAG_Issuer_Data: {
|
||||
try {
|
||||
TLVList tlvSub = TLVList.fromBytes(Value);
|
||||
return String.format("%s[%d]: %s (%s)", tag.name(), Value.length, Util.bytesToHex(Value), tlvSub.toString());
|
||||
} catch (TLVException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s (non TLV)", tag.name(), Value.length, Util.bytesToHex(Value));
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
}
|
||||
case TAG_CurveID:
|
||||
case TAG_HashAlgID:
|
||||
case TAG_Blockchain_ID:
|
||||
case TAG_Manufacture_ID:
|
||||
case TAG_Firmware:
|
||||
case TAG_Issuer_ID:
|
||||
case TAG_Token_Symbol:
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s(%s)", tag.name(), Value.length, Util.bytesToHex(Value), getAsString());
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
default:
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s", tag.name(), Value.length, Util.bytesToHex(Value));
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by dvol on 23.06.2017.
|
||||
*/
|
||||
|
||||
public class TLV {
|
||||
public enum Tag {
|
||||
TAG_Unknown(0x00),
|
||||
TAG_CardID(0x01),
|
||||
TAG_Status(0x02),
|
||||
TAG_CardPublicKey(0x03),
|
||||
TAG_CardSignature(0x04),
|
||||
TAG_CurveID(0x05),
|
||||
TAG_HashAlgID(0x06),
|
||||
TAG_SigningMethod(0x07),
|
||||
TAG_MaxSignatures(0x08),
|
||||
TAG_PauseBeforePIN2(0x09),
|
||||
TAG_SettingsMask(0x0A),
|
||||
TAG_CardData(0x0C),
|
||||
TAG_NDEFData(0x0D),
|
||||
TAG_CreateWalletAtPersonalize(0x0E),
|
||||
TAG_Health(0x0F),
|
||||
|
||||
TAG_PIN(0x10),
|
||||
TAG_PIN2(0x11),
|
||||
TAG_NewPIN(0x12),
|
||||
TAG_NewPIN2(0x13),
|
||||
TAG_NewPIN_Hash(0x14),
|
||||
TAG_NewPIN2_Hash(0x15),
|
||||
TAG_Challenge(0x16),
|
||||
TAG_Salt(0x17),
|
||||
TAG_ValidationCounter(0x18),
|
||||
TAG_CVC(0x19),
|
||||
|
||||
TAG_Session_Key_A(0x1A),
|
||||
TAG_Session_Key_B(0x1B),
|
||||
TAG_Pause(0x1C),
|
||||
|
||||
TAG_Manufacture_ID(0x20),
|
||||
TAG_Manufacturer_Signature(0x21),
|
||||
|
||||
TAG_Issuer_Data_PublicKey(0x30),
|
||||
TAG_Issuer_Transaction_PublicKey(0x31),
|
||||
TAG_Issuer_Data(0x32),
|
||||
TAG_Issuer_Data_Signature(0x33),
|
||||
TAG_Issuer_Transaction_Signature(0x34),
|
||||
|
||||
TAG_IsActivated(0x3A),
|
||||
TAG_ActivationSeed(0x3B),
|
||||
TAG_ResetPIN(0x36),
|
||||
|
||||
TAG_CodePageAddress(0x40),
|
||||
TAG_CodePageCount(0x41),
|
||||
TAG_CodeHash(0x42),
|
||||
|
||||
TAG_TrOut_Hash(0x50),
|
||||
TAG_TrOut_HashSize(0x51),
|
||||
TAG_TrOut_Raw(0x52),
|
||||
|
||||
TAG_Wallet_PublicKey(0x60),
|
||||
TAG_Signature(0x61),
|
||||
TAG_RemainingSignatures(0x62),
|
||||
TAG_SignedHashes(0x63),
|
||||
|
||||
TAG_Wallet_PrivateKey(0x70),
|
||||
TAG_Card_PrivateKey(0x71),
|
||||
TAG_Block_Reason(0x72),
|
||||
|
||||
|
||||
TAG_Firmware(0x80),
|
||||
TAG_Batch(0x81),
|
||||
TAG_ManufactureDateTime(0x82),
|
||||
TAG_Issuer_ID(0x83),
|
||||
TAG_Blockchain_ID(0x84),
|
||||
TAG_Manufacturer_PublicKey(0x85),
|
||||
TAG_CardID_Manufacturer_Signature(0x86),
|
||||
|
||||
TAG_Token_Symbol(0xA0),
|
||||
TAG_Token_Contract_Address(0xA1),
|
||||
TAG_Token_Decimal(0xA2),
|
||||
TAG_Denomination(/*0xC0*/0xee), //TODO: quick fix
|
||||
TAG_ValidatedBalance(0xC1),
|
||||
TAG_LastSign_Date(0xC2);
|
||||
|
||||
|
||||
Tag(int Code) {
|
||||
this.Code = Code;
|
||||
}
|
||||
|
||||
public int getCode() {
|
||||
return Code;
|
||||
}
|
||||
|
||||
private int Code;
|
||||
|
||||
public static Tag ByCode(int Code) {
|
||||
Tag[] allTags = Tag.values();
|
||||
for (Tag t : allTags) if (t.getCode() == Code) return t;
|
||||
return TAG_Unknown;
|
||||
}
|
||||
}
|
||||
|
||||
private Tag tag;
|
||||
|
||||
public Tag getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public byte[] Value;
|
||||
|
||||
public TLV(Tag tag, byte[] value) {
|
||||
this.tag = tag;
|
||||
this.Value = value;
|
||||
}
|
||||
|
||||
public void WriteToStream(ByteArrayOutputStream stream) throws IOException {
|
||||
stream.write(tag.getCode());
|
||||
if (Value != null) {
|
||||
if (Value.length > 0xFE) {
|
||||
stream.write(0xFF);
|
||||
stream.write((Value.length >> 8) & 0xFF);
|
||||
stream.write(Value.length & 0xFF);
|
||||
} else {
|
||||
stream.write(Value.length & 0xFF);
|
||||
}
|
||||
stream.write(Value);
|
||||
} else {
|
||||
stream.write(0x00);
|
||||
}
|
||||
}
|
||||
|
||||
public static TLV ReadFromStream(ByteArrayInputStream stream) throws IOException {
|
||||
int code = stream.read();
|
||||
if (code == -1) return null;
|
||||
int len = stream.read();
|
||||
if (len == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
if (len == 0xFF) {
|
||||
int lenH = stream.read();
|
||||
if (lenH == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
len = stream.read();
|
||||
if (len == -1)
|
||||
throw new IOException("Can't read TLV");
|
||||
len |= (lenH << 8);
|
||||
}
|
||||
byte[] value = new byte[len];
|
||||
if (len > 0) {
|
||||
if (len != stream.read(value)) {
|
||||
throw new IOException("Can't read TLV");
|
||||
}
|
||||
}
|
||||
Tag tag = Tag.ByCode(code);
|
||||
TLV result = new TLV(tag, value);
|
||||
return result;
|
||||
}
|
||||
|
||||
public int getAsInt() {
|
||||
return Util.byteArrayToInt(Value);
|
||||
}
|
||||
|
||||
public String getAsHexString() {
|
||||
return Util.bytesToHex(Value);
|
||||
}
|
||||
|
||||
public String getAsString() {
|
||||
//String s=String.valueOf(Value);
|
||||
if (Value[Value.length - 1] == 0) {
|
||||
String s1 = new String(Arrays.copyOfRange(Value, 0, Value.length - 1), Charset.forName("utf-8"));
|
||||
return s1.trim();
|
||||
} else {
|
||||
String s1 = new String(Value, Charset.forName("utf-8"));
|
||||
return s1.trim();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
switch (tag) {
|
||||
case TAG_CardData:
|
||||
case TAG_Issuer_Data: {
|
||||
try {
|
||||
TLVList tlvSub = TLVList.fromBytes(Value);
|
||||
return String.format("%s[%d]: %s (%s)", tag.name(), Value.length, Util.bytesToHex(Value), tlvSub.toString());
|
||||
} catch (TLVException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s (non TLV)", tag.name(), Value.length, Util.bytesToHex(Value));
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
}
|
||||
case TAG_CurveID:
|
||||
case TAG_HashAlgID:
|
||||
case TAG_Blockchain_ID:
|
||||
case TAG_Manufacture_ID:
|
||||
case TAG_Firmware:
|
||||
case TAG_Issuer_ID:
|
||||
case TAG_Token_Symbol:
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s(%s)", tag.name(), Value.length, Util.bytesToHex(Value), getAsString());
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
default:
|
||||
if (Value != null) {
|
||||
return String.format("%s[%d]: %s", tag.name(), Value.length, Util.bytesToHex(Value));
|
||||
} else {
|
||||
return String.format("%s[]: [[NULL]]", tag.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,18 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
public class TLVException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TLVException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TLVException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TLVException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
public class TLVException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public TLVException(String message){
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TLVException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TLVException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,72 +1,72 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 23.06.2017.
|
||||
*/
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class TLVList extends ArrayList<TLV> {
|
||||
public String getParsedTLVs(String Prefix) {
|
||||
String parsed = "";
|
||||
for (int i = 0; i < size(); i++) {
|
||||
parsed += Prefix + this.get(i).toString() + (i < size() - 1 ? "\n" : "");
|
||||
}
|
||||
return parsed;//.substring(0,parsed.length()-2);
|
||||
}
|
||||
|
||||
public TLVList() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TLVList(@NonNull Collection<? extends TLV> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public TLV getTLV(TLV.Tag tag) {
|
||||
for (TLV tlv : this) {
|
||||
if (tlv.getTag() == tag) return tlv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getTagAsInt(TLV.Tag tag) {
|
||||
TLV tlv = getTLV(tag);
|
||||
return Util.byteArrayToInt(tlv.Value);
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
for (TLV tlv : this) {
|
||||
try {
|
||||
tlv.WriteToStream(stream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stream.toByteArray();
|
||||
}
|
||||
|
||||
public static TLVList fromBytes(byte[] mData) throws TLVException {
|
||||
TLVList tlvList = new TLVList();
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(mData);
|
||||
TLV tlv = null;
|
||||
do {
|
||||
try {
|
||||
tlv = TLV.ReadFromStream(stream);
|
||||
if (tlv != null) tlvList.add(tlv);
|
||||
} catch (IOException e) {
|
||||
throw new TLVException("TLVError: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
while (tlv != null);
|
||||
return tlvList;
|
||||
}
|
||||
}
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
/**
|
||||
* Created by dvol on 23.06.2017.
|
||||
*/
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public class TLVList extends ArrayList<TLV> {
|
||||
public String getParsedTLVs(String Prefix) {
|
||||
String parsed = "";
|
||||
for (int i = 0; i < size(); i++) {
|
||||
parsed += Prefix + this.get(i).toString() + (i < size() - 1 ? "\n" : "");
|
||||
}
|
||||
return parsed;//.substring(0,parsed.length()-2);
|
||||
}
|
||||
|
||||
public TLVList() {
|
||||
super();
|
||||
}
|
||||
|
||||
public TLVList(@NonNull Collection<? extends TLV> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
public TLV getTLV(TLV.Tag tag) {
|
||||
for (TLV tlv : this) {
|
||||
if (tlv.getTag() == tag) return tlv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public int getTagAsInt(TLV.Tag tag) {
|
||||
TLV tlv = getTLV(tag);
|
||||
return Util.byteArrayToInt(tlv.Value);
|
||||
}
|
||||
|
||||
public byte[] toBytes() {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
for (TLV tlv : this) {
|
||||
try {
|
||||
tlv.WriteToStream(stream);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stream.toByteArray();
|
||||
}
|
||||
|
||||
public static TLVList fromBytes(byte[] mData) throws TLVException {
|
||||
TLVList tlvList = new TLVList();
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(mData);
|
||||
TLV tlv = null;
|
||||
do {
|
||||
try {
|
||||
tlv = TLV.ReadFromStream(stream);
|
||||
if (tlv != null) tlvList.add(tlv);
|
||||
} catch (IOException e) {
|
||||
throw new TLVException("TLVError: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
while (tlv != null);
|
||||
return tlvList;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.cardReader;
|
||||
package com.tangem.domain.cardReader;
|
||||
|
||||
import android.text.format.DateUtils;
|
||||
|
||||
|
|
@ -18,7 +18,6 @@ import java.security.MessageDigest;
|
|||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.BitSet;
|
||||
import java.util.Date;
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
package com.tangem.presentation;
|
||||
|
||||
public class Screen {
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import android.view.MenuItem;
|
|||
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
import com.tangem.wallet.WalletInfoFragment;
|
||||
import com.tangem.presentation.fragment.WalletInfoFragment;
|
||||
|
||||
public class CardInfoActivity extends AppCompatActivity implements WalletInfoFragment.OnFragmentInteractionListener {
|
||||
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@ import android.widget.RadioGroup;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
import com.tangem.wallet.BTCUtils;
|
||||
import com.tangem.wallet.Blockchain;
|
||||
import com.tangem.wallet.CoinEngine;
|
||||
import com.tangem.wallet.CoinEngineFactory;
|
||||
import com.tangem.wallet.DerEncodingUtil;
|
||||
import com.tangem.wallet.Electrum_Request;
|
||||
import com.tangem.wallet.Electrum_Task;
|
||||
import com.tangem.data.network.request.Electrum_Request;
|
||||
import com.tangem.data.network.task.Electrum_Task;
|
||||
import com.tangem.wallet.Fee_Request;
|
||||
import com.tangem.wallet.Fee_Task;
|
||||
import com.tangem.data.network.task.Fee_Task;
|
||||
import com.tangem.wallet.FormatUtil;
|
||||
import com.tangem.wallet.Infura_Request;
|
||||
import com.tangem.wallet.Infura_Task;
|
||||
import com.tangem.data.network.task.Infura_Task;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.SharedData;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.wallet.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.wallet.PINStorage;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
import com.tangem.wallet.WaitSecurityDelayDialog;
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||
|
||||
public class CreateNewWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
||||
|
||||
|
|
|
|||
|
|
@ -17,14 +17,14 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.wallet.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
import com.tangem.wallet.VerifyCardTask;
|
||||
import com.tangem.wallet.WaitSecurityDelayDialog;
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||
|
||||
public class EmptyWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import android.nfc.Tag;
|
|||
import android.os.Bundle;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.tangem.wallet.LoadedWalletActivityFragment;
|
||||
import com.tangem.presentation.fragment.LoadedWalletActivityFragment;
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ import com.tangem.wallet.DeviceNFCAntennaLocation;
|
|||
import com.tangem.wallet.LastSignStorage;
|
||||
import com.tangem.wallet.LogFileProvider;
|
||||
import com.tangem.wallet.Logger;
|
||||
import com.tangem.wallet.MainActivityFragment;
|
||||
import com.tangem.presentation.fragment.MainActivityFragment;
|
||||
import com.tangem.wallet.PINStorage;
|
||||
import com.tangem.wallet.PhoneUtility;
|
||||
import com.tangem.wallet.R;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import android.widget.EditText;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.wallet.Blockchain;
|
||||
import com.tangem.wallet.CoinEngine;
|
||||
import com.tangem.wallet.CoinEngineFactory;
|
||||
|
|
|
|||
|
|
@ -15,14 +15,14 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.wallet.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.wallet.PINStorage;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
import com.tangem.wallet.WaitSecurityDelayDialog;
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||
|
||||
public class PurgeActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import android.widget.Button;
|
|||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.wallet.FingerprintHelper;
|
||||
import com.tangem.wallet.PINStorage;
|
||||
import com.tangem.wallet.R;
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ import android.widget.Toast;
|
|||
import com.tangem.wallet.Blockchain;
|
||||
import com.tangem.wallet.CoinEngine;
|
||||
import com.tangem.wallet.CoinEngineFactory;
|
||||
import com.tangem.wallet.Electrum_Request;
|
||||
import com.tangem.wallet.Electrum_Task;
|
||||
import com.tangem.data.network.request.Electrum_Request;
|
||||
import com.tangem.data.network.task.Electrum_Task;
|
||||
import com.tangem.wallet.Infura_Request;
|
||||
import com.tangem.wallet.Infura_Task;
|
||||
import com.tangem.data.network.task.Infura_Task;
|
||||
import com.tangem.wallet.LastSignStorage;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.SharedData;
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -15,14 +15,14 @@ import android.widget.ProgressBar;
|
|||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.wallet.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog;
|
||||
import com.tangem.wallet.PINStorage;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
import com.tangem.wallet.WaitSecurityDelayDialog;
|
||||
import com.tangem.presentation.dialog.WaitSecurityDelayDialog;
|
||||
|
||||
public class SwapPINActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications {
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import android.os.Bundle;
|
|||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.VerifyCardActivityFragment;
|
||||
import com.tangem.presentation.fragment.VerifyCardActivityFragment;
|
||||
|
||||
public class VerifyCardActivity extends AppCompatActivity {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.wallet;
|
||||
package com.tangem.presentation.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
|
|
@ -10,9 +10,14 @@ import android.view.LayoutInflater;
|
|||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tangem.wallet.Blockchain;
|
||||
import com.tangem.wallet.CoinEngine;
|
||||
import com.tangem.wallet.CoinEngineFactory;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
|
@ -1,83 +1,86 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import static android.text.Html.FROM_HTML_MODE_COMPACT;
|
||||
|
||||
/**
|
||||
* Created by dvol on 17.07.2017.
|
||||
*/
|
||||
|
||||
public class CardUnspentListAdapter extends BaseAdapter {
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private Context mContext;
|
||||
private Tangem_Card mCard;
|
||||
|
||||
public CardUnspentListAdapter(LayoutInflater layoutInflater, Tangem_Card card) {
|
||||
mLayoutInflater = layoutInflater;
|
||||
mContext = layoutInflater.getContext();
|
||||
mCard = card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i).txID.hashCode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup viewGroup) {
|
||||
if (convertView == null) {
|
||||
convertView = mLayoutInflater.inflate(R.layout.card_unspent_list_item, viewGroup,
|
||||
false);
|
||||
}
|
||||
TextView tvItem = (TextView) convertView.findViewById(R.id.tvItem);
|
||||
|
||||
Tangem_Card.UnspentTransaction unspentTransaction = (Tangem_Card.UnspentTransaction) getItem(position);
|
||||
|
||||
String html=String.format("<b>%d mBTC</b><br>%s", unspentTransaction.Amount, unspentTransaction.txID);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
tvItem.setText(Html.fromHtml(html, FROM_HTML_MODE_COMPACT));
|
||||
} else {
|
||||
tvItem.setText(Html.fromHtml(html.toString()));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
mCard.getUnspentTransactions().clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void UpdateUnspent(String tx_hash, int value, int height) {
|
||||
Tangem_Card.UnspentTransaction newUT=new Tangem_Card.UnspentTransaction();
|
||||
newUT.txID=tx_hash;
|
||||
newUT.Amount=value;
|
||||
newUT.Height=height;
|
||||
mCard.getUnspentTransactions().add(newUT);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
package com.tangem.presentation.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.Html;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.BaseAdapter;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
|
||||
import static android.text.Html.FROM_HTML_MODE_COMPACT;
|
||||
|
||||
/**
|
||||
* Created by dvol on 17.07.2017.
|
||||
*/
|
||||
|
||||
public class CardUnspentListAdapter extends BaseAdapter {
|
||||
private LayoutInflater mLayoutInflater;
|
||||
private Context mContext;
|
||||
private Tangem_Card mCard;
|
||||
|
||||
public CardUnspentListAdapter(LayoutInflater layoutInflater, Tangem_Card card) {
|
||||
mLayoutInflater = layoutInflater;
|
||||
mContext = layoutInflater.getContext();
|
||||
mCard = card;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int i) {
|
||||
if (mCard != null && mCard.getUnspentTransactions() != null)
|
||||
return mCard.getUnspentTransactions().get(i).txID.hashCode();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup viewGroup) {
|
||||
if (convertView == null) {
|
||||
convertView = mLayoutInflater.inflate(R.layout.card_unspent_list_item, viewGroup,
|
||||
false);
|
||||
}
|
||||
TextView tvItem = (TextView) convertView.findViewById(R.id.tvItem);
|
||||
|
||||
Tangem_Card.UnspentTransaction unspentTransaction = (Tangem_Card.UnspentTransaction) getItem(position);
|
||||
|
||||
String html=String.format("<b>%d mBTC</b><br>%s", unspentTransaction.Amount, unspentTransaction.txID);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
tvItem.setText(Html.fromHtml(html, FROM_HTML_MODE_COMPACT));
|
||||
} else {
|
||||
tvItem.setText(Html.fromHtml(html.toString()));
|
||||
}
|
||||
return convertView;
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
mCard.getUnspentTransactions().clear();
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public void UpdateUnspent(String tx_hash, int value, int height) {
|
||||
Tangem_Card.UnspentTransaction newUT=new Tangem_Card.UnspentTransaction();
|
||||
newUT.txID=tx_hash;
|
||||
newUT.Amount=value;
|
||||
newUT.Height=height;
|
||||
mCard.getUnspentTransactions().add(newUT);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +1,45 @@
|
|||
package com.tangem.cardReader;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
/**
|
||||
* Created by dvol on 18.02.2018.
|
||||
*/
|
||||
|
||||
public class NFCEnableDialog extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setCancelable(false)
|
||||
.setIcon(R.drawable.ic_action_nfc_gray)
|
||||
.setTitle(R.string.nfc_disabled)
|
||||
.setMessage(R.string.enable_nfc)
|
||||
.setPositiveButton(R.string.dialog_ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int id) {
|
||||
// take user to wireless settings
|
||||
getActivity().startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_quit,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int id) {
|
||||
dialog.cancel();
|
||||
getActivity().finish();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
package com.tangem.presentation.dialog;
|
||||
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
/**
|
||||
* Created by dvol on 18.02.2018.
|
||||
*/
|
||||
|
||||
public class NFCEnableDialog extends DialogFragment {
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setCancelable(false)
|
||||
.setIcon(R.drawable.ic_action_nfc_gray)
|
||||
.setTitle(R.string.nfc_disabled)
|
||||
.setMessage(R.string.enable_nfc)
|
||||
.setPositiveButton(R.string.dialog_ok,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int id) {
|
||||
// take user to wireless settings
|
||||
getActivity().startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
|
||||
}
|
||||
})
|
||||
.setNegativeButton(R.string.dialog_quit,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog,
|
||||
int id) {
|
||||
dialog.cancel();
|
||||
getActivity().finish();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +1,36 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
public class NoExtendedLengthSupportDialog extends DialogFragment {
|
||||
|
||||
public static boolean allreadyShowed=false;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Warning")
|
||||
.setMessage("The NFC adapter of the device does not support extended length APDU, it's possible that some functions will not work!")
|
||||
.setPositiveButton("Got it",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
NoExtendedLengthSupportDialog.allreadyShowed=true;
|
||||
}
|
||||
}
|
||||
)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
package com.tangem.presentation.dialog;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
public class NoExtendedLengthSupportDialog extends DialogFragment {
|
||||
|
||||
public static boolean allreadyShowed=false;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Warning")
|
||||
.setMessage("The NFC adapter of the device does not support extended length APDU, it's possible that some functions will not work!")
|
||||
.setPositiveButton("Got it",
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int whichButton) {
|
||||
NoExtendedLengthSupportDialog.allreadyShowed=true;
|
||||
}
|
||||
}
|
||||
)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,166 +1,168 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Created by dvol on 06.03.2018.
|
||||
*/
|
||||
public class WaitSecurityDelayDialog extends DialogFragment {
|
||||
ProgressBar progressBar;
|
||||
int msTimeout = 60000, msProgress = 0;
|
||||
Timer timer;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
|
||||
// Inflate and set the layout for the dialog
|
||||
// Pass null as the parent view because its going in the dialog layout
|
||||
View v = inflater.inflate(R.layout.dialog_wait_pin2, null);
|
||||
|
||||
progressBar = v.findViewById(R.id.progressBar);
|
||||
progressBar.setMax(msTimeout);
|
||||
progressBar.setProgress(msProgress);
|
||||
|
||||
timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int progress = WaitSecurityDelayDialog.this.progressBar.getProgress();
|
||||
if (progress < WaitSecurityDelayDialog.this.progressBar.getMax()) {
|
||||
WaitSecurityDelayDialog.this.progressBar.setProgress(progress + 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1000, 1000);
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Security delay")
|
||||
.setView(v)
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
|
||||
public void setup(int msTimeout, int msProgress) {
|
||||
this.msTimeout = msTimeout;
|
||||
this.msProgress = msProgress;
|
||||
}
|
||||
|
||||
public void setRemainingTimeout(final int msec) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int progress = WaitSecurityDelayDialog.this.progressBar.getProgress();
|
||||
if (timer != null) {
|
||||
// we get delay latency from card for first time - don't change progress by timer, only by card answer
|
||||
progressBar.setMax(progress + msec);
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
} else {
|
||||
int newProgress = progressBar.getMax() - msec;
|
||||
if (newProgress > progress) {
|
||||
progressBar.setProgress(newProgress);
|
||||
} else {
|
||||
progressBar.setMax(progress + msec);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Timer timerToShowDelayDialog = null;
|
||||
static WaitSecurityDelayDialog instance = null;
|
||||
|
||||
public static WaitSecurityDelayDialog getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final static int MinRemainingDelayToShowDialog=1000;
|
||||
private final static int DelayBeforeShowDialog=5000;
|
||||
|
||||
public static void onReadBeforeRequest(final Activity activity, final int timeout) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog != null || timeout < DelayBeforeShowDialog+MinRemainingDelayToShowDialog) return;
|
||||
timerToShowDelayDialog = new Timer();
|
||||
timerToShowDelayDialog.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (WaitSecurityDelayDialog.instance != null) return;
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
instance.setup(timeout, DelayBeforeShowDialog);
|
||||
instance.setCancelable(false);
|
||||
instance.show(activity.getFragmentManager(), "WaitSecurityDelayDialog");
|
||||
}
|
||||
}, DelayBeforeShowDialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onReadAfterRequest(final Activity activity) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog == null) return;
|
||||
timerToShowDelayDialog.cancel();
|
||||
timerToShowDelayDialog = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void OnReadWait(final Activity activity, final int msec) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog != null) {
|
||||
timerToShowDelayDialog.cancel();
|
||||
timerToShowDelayDialog = null;
|
||||
}
|
||||
|
||||
if (msec == 0) {
|
||||
if (instance != null) {
|
||||
instance.dismiss();
|
||||
instance = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (instance == null) {
|
||||
if( msec>MinRemainingDelayToShowDialog ) {
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
// 1000ms - card delay notification interval
|
||||
instance.setup(msec + 1000, 1000);
|
||||
instance.setCancelable(false);
|
||||
instance.show(activity.getFragmentManager(), "WaitSecurityDelayDialog");
|
||||
}
|
||||
} else {
|
||||
instance.setRemainingTimeout(msec);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
package com.tangem.presentation.dialog;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import com.tangem.wallet.R;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
/**
|
||||
* Created by dvol on 06.03.2018.
|
||||
*/
|
||||
public class WaitSecurityDelayDialog extends DialogFragment {
|
||||
ProgressBar progressBar;
|
||||
int msTimeout = 60000, msProgress = 0;
|
||||
Timer timer;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
|
||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||
|
||||
// Inflate and set the layout for the dialog
|
||||
// Pass null as the parent view because its going in the dialog layout
|
||||
View v = inflater.inflate(R.layout.dialog_wait_pin2, null);
|
||||
|
||||
progressBar = v.findViewById(R.id.progressBar);
|
||||
progressBar.setMax(msTimeout);
|
||||
progressBar.setProgress(msProgress);
|
||||
|
||||
timer = new Timer();
|
||||
timer.scheduleAtFixedRate(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int progress = WaitSecurityDelayDialog.this.progressBar.getProgress();
|
||||
if (progress < WaitSecurityDelayDialog.this.progressBar.getMax()) {
|
||||
WaitSecurityDelayDialog.this.progressBar.setProgress(progress + 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1000, 1000);
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setIcon(R.drawable.tangem_logo_small_new)
|
||||
.setTitle("Security delay")
|
||||
.setView(v)
|
||||
.setCancelable(false)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
}
|
||||
|
||||
public void setup(int msTimeout, int msProgress) {
|
||||
this.msTimeout = msTimeout;
|
||||
this.msProgress = msProgress;
|
||||
}
|
||||
|
||||
public void setRemainingTimeout(final int msec) {
|
||||
progressBar.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int progress = WaitSecurityDelayDialog.this.progressBar.getProgress();
|
||||
if (timer != null) {
|
||||
// we get delay latency from card for first time - don't change progress by timer, only by card answer
|
||||
progressBar.setMax(progress + msec);
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
} else {
|
||||
int newProgress = progressBar.getMax() - msec;
|
||||
if (newProgress > progress) {
|
||||
progressBar.setProgress(newProgress);
|
||||
} else {
|
||||
progressBar.setMax(progress + msec);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static Timer timerToShowDelayDialog = null;
|
||||
static WaitSecurityDelayDialog instance = null;
|
||||
|
||||
public static WaitSecurityDelayDialog getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final static int MinRemainingDelayToShowDialog=1000;
|
||||
private final static int DelayBeforeShowDialog=5000;
|
||||
|
||||
public static void onReadBeforeRequest(final Activity activity, final int timeout) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog != null || timeout < DelayBeforeShowDialog+MinRemainingDelayToShowDialog) return;
|
||||
timerToShowDelayDialog = new Timer();
|
||||
timerToShowDelayDialog.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (WaitSecurityDelayDialog.instance != null) return;
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
instance.setup(timeout, DelayBeforeShowDialog);
|
||||
instance.setCancelable(false);
|
||||
instance.show(activity.getFragmentManager(), "WaitSecurityDelayDialog");
|
||||
}
|
||||
}, DelayBeforeShowDialog);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void onReadAfterRequest(final Activity activity) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog == null) return;
|
||||
timerToShowDelayDialog.cancel();
|
||||
timerToShowDelayDialog = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void OnReadWait(final Activity activity, final int msec) {
|
||||
activity.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (timerToShowDelayDialog != null) {
|
||||
timerToShowDelayDialog.cancel();
|
||||
timerToShowDelayDialog = null;
|
||||
}
|
||||
|
||||
if (msec == 0) {
|
||||
if (instance != null) {
|
||||
instance.dismiss();
|
||||
instance = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (instance == null) {
|
||||
if( msec>MinRemainingDelayToShowDialog ) {
|
||||
instance = new WaitSecurityDelayDialog();
|
||||
// 1000ms - card delay notification interval
|
||||
instance.setup(msec + 1000, 1000);
|
||||
instance.setCancelable(false);
|
||||
instance.show(activity.getFragmentManager(), "WaitSecurityDelayDialog");
|
||||
}
|
||||
} else {
|
||||
instance.setRemainingTimeout(msec);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,360 +1,362 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class VerifyCardActivityFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback {
|
||||
|
||||
Tangem_Card mCard;
|
||||
TextView tvCardID, tvManufacturer, tvRegistrationDate, tvCardIdentity, tvLastSigned, tvRemainingSignatures, tvReusable, tvOk, tvError, tvMessage,
|
||||
tvIssuer, tvIssuerData, tvFeatures, tvBlockchain, tvSignedTx, tvSigningMethod, tvFirmware, tvWalletIdentity, tvWallet;
|
||||
ImageView ivBlockchain, ivPIN, ivPIN2orSecurityDelay, ivDeveloperVersion;
|
||||
SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private NfcManager mNfcManager;
|
||||
|
||||
public VerifyCardActivityFragment() {
|
||||
|
||||
}
|
||||
|
||||
public void onRefresh() {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_verify_card, container, false);
|
||||
|
||||
mNfcManager = new NfcManager(this.getActivity(), this);
|
||||
|
||||
|
||||
// SwipeRefreshLayout
|
||||
mSwipeRefreshLayout = v.findViewById(R.id.swipe_container);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
mCard = new Tangem_Card(getActivity().getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getActivity().getIntent().getExtras().getBundle("Card"));
|
||||
tvCardID = v.findViewById(R.id.tvCardID);
|
||||
|
||||
tvLastSigned = v.findViewById(R.id.tvLastSigned);
|
||||
tvRemainingSignatures = v.findViewById(R.id.tvRemainingSignatures);
|
||||
|
||||
tvReusable = v.findViewById(R.id.tvReusable);
|
||||
|
||||
tvManufacturer = v.findViewById(R.id.tvManufacturerInfo);
|
||||
|
||||
tvCardIdentity = v.findViewById(R.id.tvCardIdentity);
|
||||
|
||||
tvRegistrationDate = v.findViewById(R.id.tvCardRegistredDate);
|
||||
|
||||
ivBlockchain = v.findViewById(R.id.imgBlockchain);
|
||||
ivPIN = v.findViewById(R.id.imgPIN);
|
||||
ivPIN2orSecurityDelay = v.findViewById(R.id.imgPIN2orSecurityDelay);
|
||||
ivDeveloperVersion = v.findViewById(R.id.imgDeveloperVersion);
|
||||
|
||||
tvError = v.findViewById(R.id.tvError);
|
||||
tvMessage = v.findViewById(R.id.tvMessage);
|
||||
|
||||
tvIssuer = v.findViewById(R.id.tvIssuer);
|
||||
tvIssuerData = v.findViewById(R.id.tvIssuerData);
|
||||
|
||||
tvFirmware = v.findViewById(R.id.tvFirmware);
|
||||
tvFeatures = v.findViewById(R.id.tvFeatures);
|
||||
tvBlockchain = v.findViewById(R.id.tvBlockchain);
|
||||
|
||||
tvSignedTx = v.findViewById(R.id.tvSignedTx);
|
||||
tvSigningMethod = v.findViewById(R.id.tvSigningMethod);
|
||||
|
||||
tvOk = v.findViewById(R.id.tvOk);
|
||||
if (tvOk != null) {
|
||||
tvOk.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent data = prepareResultIntent();
|
||||
data.putExtra("modification", "update");
|
||||
getActivity().setResult(Activity.RESULT_OK, data);
|
||||
getActivity().finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tvWallet = v.findViewById(R.id.tvWallet);
|
||||
tvWalletIdentity = v.findViewById(R.id.tvWalletIdentity);
|
||||
|
||||
UpdateViews();
|
||||
|
||||
// if (NeedUpdate) {
|
||||
// mSwipeRefreshLayout.setRefreshing(true);
|
||||
// mSwipeRefreshLayout.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// onRefresh();
|
||||
// }
|
||||
// }, 1000);
|
||||
// }
|
||||
return v;
|
||||
}
|
||||
|
||||
void UpdateViews() {
|
||||
try {
|
||||
if (timerHideErrorAndMessage != null) {
|
||||
timerHideErrorAndMessage.cancel();
|
||||
timerHideErrorAndMessage = null;
|
||||
}
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
if (mCard.getError() == null || mCard.getError().isEmpty()) {
|
||||
tvError.setVisibility(View.GONE);
|
||||
tvError.setText("");
|
||||
} else {
|
||||
tvError.setVisibility(View.VISIBLE);
|
||||
tvError.setText(mCard.getError());
|
||||
}
|
||||
if (mCard.getMessage() == null || mCard.getMessage().isEmpty()) {
|
||||
tvMessage.setVisibility(View.GONE);
|
||||
tvMessage.setText("");
|
||||
} else {
|
||||
tvMessage.setVisibility(View.VISIBLE);
|
||||
tvMessage.setText(mCard.getMessage());
|
||||
}
|
||||
|
||||
tvManufacturer.setText(mCard.getManufacturer().getOfficialName());
|
||||
|
||||
if (mCard.isManufacturerConfirmed() && mCard.isCardPublicKeyValid()) {
|
||||
tvCardIdentity.setText("Attested");
|
||||
tvCardIdentity.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
} else {
|
||||
tvCardIdentity.setText("Not confirmed");
|
||||
tvCardIdentity.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
}
|
||||
|
||||
tvIssuer.setText(mCard.getIssuerDescription());
|
||||
tvIssuerData.setText(mCard.getIssuerDataDescription());
|
||||
|
||||
tvRegistrationDate.setText(mCard.getPersonalizationDateTimeDescription());
|
||||
|
||||
//tvBlockchain.setText(mCard.getBlockchain().getOfficialName());
|
||||
tvBlockchain.setText(mCard.getBlockchainName());
|
||||
ivBlockchain.setImageResource(mCard.getBlockchain().getImageResource(this.getContext(), mCard.getTokenSymbol()));
|
||||
|
||||
if (mCard.isReusable()) {
|
||||
tvReusable.setText("Reusable");
|
||||
} else {
|
||||
tvReusable.setText("One-off banknote");
|
||||
}
|
||||
|
||||
tvSigningMethod.setText(mCard.getSigningMethod().getDescription());
|
||||
|
||||
if (mCard.getStatus() == Tangem_Card.Status.Loaded || mCard.getStatus() == Tangem_Card.Status.Purged) {
|
||||
|
||||
tvLastSigned.setText(mCard.getLastSignedDescription());
|
||||
if (mCard.getRemainingSignatures() == 0) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("None");
|
||||
} else if (mCard.getRemainingSignatures() == 1) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("Last one!");
|
||||
} else if (mCard.getRemainingSignatures() > 1000) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("Unlimited");
|
||||
} else {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText(String.valueOf(mCard.getRemainingSignatures()));
|
||||
}
|
||||
tvSignedTx.setText(String.valueOf(mCard.getMaxSignatures() - mCard.getRemainingSignatures()));
|
||||
} else {
|
||||
tvLastSigned.setText("");
|
||||
tvRemainingSignatures.setText("");
|
||||
tvSignedTx.setText("");
|
||||
}
|
||||
|
||||
tvFirmware.setText(mCard.getFirmwareVersion());
|
||||
|
||||
String features = "";
|
||||
|
||||
if (mCard.allowSwapPIN() && mCard.allowSwapPIN2()) {
|
||||
features += "Allows change PIN1 and PIN2\n";
|
||||
} else if (mCard.allowSwapPIN()) {
|
||||
features += "Allows change PIN1\n";
|
||||
} else if (mCard.allowSwapPIN2()) {
|
||||
features += "Allows change PIN2\n";
|
||||
} else {
|
||||
features += "Fixed PIN1 and PIN2\n";
|
||||
}
|
||||
|
||||
if (mCard.needCVC()) {
|
||||
features += "Requires CVC\n";
|
||||
}
|
||||
|
||||
if (mCard.supportDynamicNDEF()) {
|
||||
features += "Dynamic NDEF for iOS\n";
|
||||
} else if (mCard.supportNDEF()) {
|
||||
features += "NDEF\n";
|
||||
}
|
||||
|
||||
if (mCard.supportBlock()) {
|
||||
features += "Blockable\n";
|
||||
}
|
||||
|
||||
if (mCard.supportOnlyOneCommandAtTime()) {
|
||||
features += "Atomic command mode";
|
||||
}
|
||||
|
||||
if (features.endsWith("\n")) {
|
||||
features = features.substring(0, features.length() - 1);
|
||||
}
|
||||
tvFeatures.setText(features);
|
||||
|
||||
if (mCard.useDefaultPIN1()) {
|
||||
ivPIN.setImageResource(R.drawable.unlock_pin1);
|
||||
ivPIN.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by default PIN1 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivPIN.setImageResource(R.drawable.lock_pin1);
|
||||
ivPIN.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by user's PIN1 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0 && (mCard.useDefaultPIN2() || !mCard.useSmartSecurityDelay())) {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.timer);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), String.format("This banknote will enforce %.0f seconds security delay for all operations requiring PIN2 code", mCard.getPauseBeforePIN2() / 1000.0), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
} else if (mCard.useDefaultPIN2()) {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by default PIN2 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.lock_pin2);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by user's PIN2 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (mCard.useDevelopersFirmware()) {
|
||||
ivDeveloperVersion.setImageResource(R.drawable.ic_developer_version);
|
||||
ivDeveloperVersion.setVisibility(View.VISIBLE);
|
||||
ivDeveloperVersion.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "Unlocked banknote, only for development use", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivDeveloperVersion.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (mCard.getStatus() == Tangem_Card.Status.Loaded) {
|
||||
tvWallet.setText(mCard.getShortWalletString());
|
||||
if (mCard.isWalletPublicKeyValid()) {
|
||||
tvWalletIdentity.setText("Possession proved");
|
||||
tvWalletIdentity.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
} else {
|
||||
tvWalletIdentity.setText("Possession NOT proved");
|
||||
tvWalletIdentity.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
}
|
||||
} else {
|
||||
tvWallet.setText("not available");
|
||||
tvWalletIdentity.setText("-- -- --");
|
||||
}
|
||||
|
||||
timerHideErrorAndMessage = new Timer();
|
||||
timerHideErrorAndMessage.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
tvError.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tvMessage.setVisibility(View.GONE);
|
||||
tvError.setVisibility(View.GONE);
|
||||
mCard.setError(null);
|
||||
mCard.setMessage(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Timer timerHideErrorAndMessage = null;
|
||||
|
||||
public Intent prepareResultIntent() {
|
||||
Intent data = new Intent();
|
||||
data.putExtra("UID", mCard.getUID());
|
||||
data.putExtra("Card", mCard.getAsBundle());
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mNfcManager.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mNfcManager.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
Log.w(getClass().getName(), "Ignore discovered tag!");
|
||||
mNfcManager.IgnoreTag(tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package com.tangem.presentation.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.Tag;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class VerifyCardActivityFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback {
|
||||
|
||||
Tangem_Card mCard;
|
||||
TextView tvCardID, tvManufacturer, tvRegistrationDate, tvCardIdentity, tvLastSigned, tvRemainingSignatures, tvReusable, tvOk, tvError, tvMessage,
|
||||
tvIssuer, tvIssuerData, tvFeatures, tvBlockchain, tvSignedTx, tvSigningMethod, tvFirmware, tvWalletIdentity, tvWallet;
|
||||
ImageView ivBlockchain, ivPIN, ivPIN2orSecurityDelay, ivDeveloperVersion;
|
||||
SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
private NfcManager mNfcManager;
|
||||
|
||||
public VerifyCardActivityFragment() {
|
||||
|
||||
}
|
||||
|
||||
public void onRefresh() {
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View v = inflater.inflate(R.layout.fragment_verify_card, container, false);
|
||||
|
||||
mNfcManager = new NfcManager(this.getActivity(), this);
|
||||
|
||||
|
||||
// SwipeRefreshLayout
|
||||
mSwipeRefreshLayout = v.findViewById(R.id.swipe_container);
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
|
||||
mCard = new Tangem_Card(getActivity().getIntent().getStringExtra("UID"));
|
||||
mCard.LoadFromBundle(getActivity().getIntent().getExtras().getBundle("Card"));
|
||||
tvCardID = v.findViewById(R.id.tvCardID);
|
||||
|
||||
tvLastSigned = v.findViewById(R.id.tvLastSigned);
|
||||
tvRemainingSignatures = v.findViewById(R.id.tvRemainingSignatures);
|
||||
|
||||
tvReusable = v.findViewById(R.id.tvReusable);
|
||||
|
||||
tvManufacturer = v.findViewById(R.id.tvManufacturerInfo);
|
||||
|
||||
tvCardIdentity = v.findViewById(R.id.tvCardIdentity);
|
||||
|
||||
tvRegistrationDate = v.findViewById(R.id.tvCardRegistredDate);
|
||||
|
||||
ivBlockchain = v.findViewById(R.id.imgBlockchain);
|
||||
ivPIN = v.findViewById(R.id.imgPIN);
|
||||
ivPIN2orSecurityDelay = v.findViewById(R.id.imgPIN2orSecurityDelay);
|
||||
ivDeveloperVersion = v.findViewById(R.id.imgDeveloperVersion);
|
||||
|
||||
tvError = v.findViewById(R.id.tvError);
|
||||
tvMessage = v.findViewById(R.id.tvMessage);
|
||||
|
||||
tvIssuer = v.findViewById(R.id.tvIssuer);
|
||||
tvIssuerData = v.findViewById(R.id.tvIssuerData);
|
||||
|
||||
tvFirmware = v.findViewById(R.id.tvFirmware);
|
||||
tvFeatures = v.findViewById(R.id.tvFeatures);
|
||||
tvBlockchain = v.findViewById(R.id.tvBlockchain);
|
||||
|
||||
tvSignedTx = v.findViewById(R.id.tvSignedTx);
|
||||
tvSigningMethod = v.findViewById(R.id.tvSigningMethod);
|
||||
|
||||
tvOk = v.findViewById(R.id.tvOk);
|
||||
if (tvOk != null) {
|
||||
tvOk.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent data = prepareResultIntent();
|
||||
data.putExtra("modification", "update");
|
||||
getActivity().setResult(Activity.RESULT_OK, data);
|
||||
getActivity().finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
tvWallet = v.findViewById(R.id.tvWallet);
|
||||
tvWalletIdentity = v.findViewById(R.id.tvWalletIdentity);
|
||||
|
||||
UpdateViews();
|
||||
|
||||
// if (NeedUpdate) {
|
||||
// mSwipeRefreshLayout.setRefreshing(true);
|
||||
// mSwipeRefreshLayout.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// onRefresh();
|
||||
// }
|
||||
// }, 1000);
|
||||
// }
|
||||
return v;
|
||||
}
|
||||
|
||||
void UpdateViews() {
|
||||
try {
|
||||
if (timerHideErrorAndMessage != null) {
|
||||
timerHideErrorAndMessage.cancel();
|
||||
timerHideErrorAndMessage = null;
|
||||
}
|
||||
tvCardID.setText(mCard.getCIDDescription());
|
||||
|
||||
if (mCard.getError() == null || mCard.getError().isEmpty()) {
|
||||
tvError.setVisibility(View.GONE);
|
||||
tvError.setText("");
|
||||
} else {
|
||||
tvError.setVisibility(View.VISIBLE);
|
||||
tvError.setText(mCard.getError());
|
||||
}
|
||||
if (mCard.getMessage() == null || mCard.getMessage().isEmpty()) {
|
||||
tvMessage.setVisibility(View.GONE);
|
||||
tvMessage.setText("");
|
||||
} else {
|
||||
tvMessage.setVisibility(View.VISIBLE);
|
||||
tvMessage.setText(mCard.getMessage());
|
||||
}
|
||||
|
||||
tvManufacturer.setText(mCard.getManufacturer().getOfficialName());
|
||||
|
||||
if (mCard.isManufacturerConfirmed() && mCard.isCardPublicKeyValid()) {
|
||||
tvCardIdentity.setText("Attested");
|
||||
tvCardIdentity.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
} else {
|
||||
tvCardIdentity.setText("Not confirmed");
|
||||
tvCardIdentity.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
}
|
||||
|
||||
tvIssuer.setText(mCard.getIssuerDescription());
|
||||
tvIssuerData.setText(mCard.getIssuerDataDescription());
|
||||
|
||||
tvRegistrationDate.setText(mCard.getPersonalizationDateTimeDescription());
|
||||
|
||||
//tvBlockchain.setText(mCard.getBlockchain().getOfficialName());
|
||||
tvBlockchain.setText(mCard.getBlockchainName());
|
||||
ivBlockchain.setImageResource(mCard.getBlockchain().getImageResource(this.getContext(), mCard.getTokenSymbol()));
|
||||
|
||||
if (mCard.isReusable()) {
|
||||
tvReusable.setText("Reusable");
|
||||
} else {
|
||||
tvReusable.setText("One-off banknote");
|
||||
}
|
||||
|
||||
tvSigningMethod.setText(mCard.getSigningMethod().getDescription());
|
||||
|
||||
if (mCard.getStatus() == Tangem_Card.Status.Loaded || mCard.getStatus() == Tangem_Card.Status.Purged) {
|
||||
|
||||
tvLastSigned.setText(mCard.getLastSignedDescription());
|
||||
if (mCard.getRemainingSignatures() == 0) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("None");
|
||||
} else if (mCard.getRemainingSignatures() == 1) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("Last one!");
|
||||
} else if (mCard.getRemainingSignatures() > 1000) {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText("Unlimited");
|
||||
} else {
|
||||
tvRemainingSignatures.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
tvRemainingSignatures.setText(String.valueOf(mCard.getRemainingSignatures()));
|
||||
}
|
||||
tvSignedTx.setText(String.valueOf(mCard.getMaxSignatures() - mCard.getRemainingSignatures()));
|
||||
} else {
|
||||
tvLastSigned.setText("");
|
||||
tvRemainingSignatures.setText("");
|
||||
tvSignedTx.setText("");
|
||||
}
|
||||
|
||||
tvFirmware.setText(mCard.getFirmwareVersion());
|
||||
|
||||
String features = "";
|
||||
|
||||
if (mCard.allowSwapPIN() && mCard.allowSwapPIN2()) {
|
||||
features += "Allows change PIN1 and PIN2\n";
|
||||
} else if (mCard.allowSwapPIN()) {
|
||||
features += "Allows change PIN1\n";
|
||||
} else if (mCard.allowSwapPIN2()) {
|
||||
features += "Allows change PIN2\n";
|
||||
} else {
|
||||
features += "Fixed PIN1 and PIN2\n";
|
||||
}
|
||||
|
||||
if (mCard.needCVC()) {
|
||||
features += "Requires CVC\n";
|
||||
}
|
||||
|
||||
if (mCard.supportDynamicNDEF()) {
|
||||
features += "Dynamic NDEF for iOS\n";
|
||||
} else if (mCard.supportNDEF()) {
|
||||
features += "NDEF\n";
|
||||
}
|
||||
|
||||
if (mCard.supportBlock()) {
|
||||
features += "Blockable\n";
|
||||
}
|
||||
|
||||
if (mCard.supportOnlyOneCommandAtTime()) {
|
||||
features += "Atomic command mode";
|
||||
}
|
||||
|
||||
if (features.endsWith("\n")) {
|
||||
features = features.substring(0, features.length() - 1);
|
||||
}
|
||||
tvFeatures.setText(features);
|
||||
|
||||
if (mCard.useDefaultPIN1()) {
|
||||
ivPIN.setImageResource(R.drawable.unlock_pin1);
|
||||
ivPIN.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by default PIN1 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivPIN.setImageResource(R.drawable.lock_pin1);
|
||||
ivPIN.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by user's PIN1 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (mCard.getPauseBeforePIN2() > 0 && (mCard.useDefaultPIN2() || !mCard.useSmartSecurityDelay())) {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.timer);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), String.format("This banknote will enforce %.0f seconds security delay for all operations requiring PIN2 code", mCard.getPauseBeforePIN2() / 1000.0), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
|
||||
} else if (mCard.useDefaultPIN2()) {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.unlock_pin2);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by default PIN2 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivPIN2orSecurityDelay.setImageResource(R.drawable.lock_pin2);
|
||||
ivPIN2orSecurityDelay.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "This banknote is protected by user's PIN2 code", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (mCard.useDevelopersFirmware()) {
|
||||
ivDeveloperVersion.setImageResource(R.drawable.ic_developer_version);
|
||||
ivDeveloperVersion.setVisibility(View.VISIBLE);
|
||||
ivDeveloperVersion.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Toast.makeText(getContext(), "Unlocked banknote, only for development use", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
ivDeveloperVersion.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (mCard.getStatus() == Tangem_Card.Status.Loaded) {
|
||||
tvWallet.setText(mCard.getShortWalletString());
|
||||
if (mCard.isWalletPublicKeyValid()) {
|
||||
tvWalletIdentity.setText("Possession proved");
|
||||
tvWalletIdentity.setTextColor(getResources().getColor(R.color.confirmed, getActivity().getTheme()));
|
||||
} else {
|
||||
tvWalletIdentity.setText("Possession NOT proved");
|
||||
tvWalletIdentity.setTextColor(getResources().getColor(R.color.not_confirmed, getActivity().getTheme()));
|
||||
}
|
||||
} else {
|
||||
tvWallet.setText("not available");
|
||||
tvWalletIdentity.setText("-- -- --");
|
||||
}
|
||||
|
||||
timerHideErrorAndMessage = new Timer();
|
||||
timerHideErrorAndMessage.schedule(new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
tvError.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
tvMessage.setVisibility(View.GONE);
|
||||
tvError.setVisibility(View.GONE);
|
||||
mCard.setError(null);
|
||||
mCard.setMessage(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
Timer timerHideErrorAndMessage = null;
|
||||
|
||||
public Intent prepareResultIntent() {
|
||||
Intent data = new Intent();
|
||||
data.putExtra("UID", mCard.getUID());
|
||||
data.putExtra("Card", mCard.getAsBundle());
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mNfcManager.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
mNfcManager.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
mNfcManager.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTagDiscovered(Tag tag) {
|
||||
try {
|
||||
Log.w(getClass().getName(), "Ignore discovered tag!");
|
||||
mNfcManager.IgnoreTag(tag);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,150 +1,152 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* {@link OnFragmentInteractionListener} interface
|
||||
* to handle interaction events.
|
||||
* Use the {@link WalletInfoFragment#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class WalletInfoFragment extends Fragment {
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private Tangem_Card mCard;
|
||||
|
||||
private OnFragmentInteractionListener mListener;
|
||||
|
||||
public WalletInfoFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @return A new instance of fragment WalletInfoFragment.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
public static WalletInfoFragment newInstance(Tangem_Card card) {
|
||||
WalletInfoFragment fragment = new WalletInfoFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("UID",card.getUID());
|
||||
card.SaveToBundle(args);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mCard = new Tangem_Card(getArguments().getString("UID"));
|
||||
mCard.LoadFromBundle(getArguments());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View result=inflater.inflate(R.layout.fragment_wallet_info, container, false);
|
||||
|
||||
ImageView mImage= (ImageView)result.findViewById(R.id.qrWallet);
|
||||
try {
|
||||
mImage.setImageBitmap(generateQrCode(mCard.getWallet()));
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
TextView mText=(TextView)result.findViewById(R.id.strWallet);
|
||||
mText.setText(mCard.getWallet());
|
||||
|
||||
mText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
TextView mText = (TextView) view;
|
||||
ClipboardManager clipboard = (ClipboardManager)getActivity().getSystemService(CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(mText.getText(), mText.getText()));
|
||||
Toast.makeText(getContext(),"Copied to clipboard",Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Bitmap generateQrCode(String myCodeText) throws WriterException {
|
||||
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
|
||||
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // H = 30% damage
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
|
||||
int size = 256;
|
||||
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(myCodeText, BarcodeFormat.QR_CODE, size, size, hintMap);
|
||||
int width = bitMatrix.getWidth();
|
||||
Bitmap bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < width; y++) {
|
||||
bmp.setPixel(y, x, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof OnFragmentInteractionListener) {
|
||||
mListener = (OnFragmentInteractionListener) context;
|
||||
} else {
|
||||
throw new RuntimeException(context.toString()
|
||||
+ " must implement OnFragmentInteractionListener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface must be implemented by activities that contain this
|
||||
* fragment to allow an interaction in this fragment to be communicated
|
||||
* to the activity and potentially other fragments contained in that
|
||||
* activity.
|
||||
* <p>
|
||||
* See the Android Training lesson <a href=
|
||||
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
||||
* >Communicating with Other Fragments</a> for more information.
|
||||
*/
|
||||
public interface OnFragmentInteractionListener {
|
||||
// TODO: Update argument type and name
|
||||
// void onFragmentInteraction(Uri uri);
|
||||
}
|
||||
}
|
||||
package com.tangem.presentation.fragment;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.qrcode.QRCodeWriter;
|
||||
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
|
||||
import com.tangem.wallet.R;
|
||||
import com.tangem.wallet.Tangem_Card;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import static android.content.Context.CLIPBOARD_SERVICE;
|
||||
|
||||
/**
|
||||
* A simple {@link Fragment} subclass.
|
||||
* Activities that contain this fragment must implement the
|
||||
* {@link OnFragmentInteractionListener} interface
|
||||
* to handle interaction events.
|
||||
* Use the {@link WalletInfoFragment#newInstance} factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
public class WalletInfoFragment extends Fragment {
|
||||
|
||||
// TODO: Rename and change types of parameters
|
||||
private Tangem_Card mCard;
|
||||
|
||||
private OnFragmentInteractionListener mListener;
|
||||
|
||||
public WalletInfoFragment() {
|
||||
// Required empty public constructor
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @return A new instance of fragment WalletInfoFragment.
|
||||
*/
|
||||
// TODO: Rename and change types and number of parameters
|
||||
public static WalletInfoFragment newInstance(Tangem_Card card) {
|
||||
WalletInfoFragment fragment = new WalletInfoFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putString("UID",card.getUID());
|
||||
card.SaveToBundle(args);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mCard = new Tangem_Card(getArguments().getString("UID"));
|
||||
mCard.LoadFromBundle(getArguments());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
// Inflate the layout for this fragment
|
||||
View result=inflater.inflate(R.layout.fragment_wallet_info, container, false);
|
||||
|
||||
ImageView mImage= (ImageView)result.findViewById(R.id.qrWallet);
|
||||
try {
|
||||
mImage.setImageBitmap(generateQrCode(mCard.getWallet()));
|
||||
} catch (WriterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
TextView mText=(TextView)result.findViewById(R.id.strWallet);
|
||||
mText.setText(mCard.getWallet());
|
||||
|
||||
mText.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
TextView mText = (TextView) view;
|
||||
ClipboardManager clipboard = (ClipboardManager)getActivity().getSystemService(CLIPBOARD_SERVICE);
|
||||
clipboard.setPrimaryClip(ClipData.newPlainText(mText.getText(), mText.getText()));
|
||||
Toast.makeText(getContext(),"Copied to clipboard",Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
public static Bitmap generateQrCode(String myCodeText) throws WriterException {
|
||||
Hashtable<EncodeHintType, ErrorCorrectionLevel> hintMap = new Hashtable<EncodeHintType, ErrorCorrectionLevel>();
|
||||
hintMap.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); // H = 30% damage
|
||||
|
||||
QRCodeWriter qrCodeWriter = new QRCodeWriter();
|
||||
|
||||
int size = 256;
|
||||
|
||||
BitMatrix bitMatrix = qrCodeWriter.encode(myCodeText, BarcodeFormat.QR_CODE, size, size, hintMap);
|
||||
int width = bitMatrix.getWidth();
|
||||
Bitmap bmp = Bitmap.createBitmap(width, width, Bitmap.Config.RGB_565);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < width; y++) {
|
||||
bmp.setPixel(y, x, bitMatrix.get(x, y) ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
}
|
||||
return bmp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
if (context instanceof OnFragmentInteractionListener) {
|
||||
mListener = (OnFragmentInteractionListener) context;
|
||||
} else {
|
||||
throw new RuntimeException(context.toString()
|
||||
+ " must implement OnFragmentInteractionListener");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This interface must be implemented by activities that contain this
|
||||
* fragment to allow an interaction in this fragment to be communicated
|
||||
* to the activity and potentially other fragments contained in that
|
||||
* activity.
|
||||
* <p>
|
||||
* See the Android Training lesson <a href=
|
||||
* "http://developer.android.com/training/basics/fragments/communicating.html"
|
||||
* >Communicating with Other Fragments</a> for more information.
|
||||
*/
|
||||
public interface OnFragmentInteractionListener {
|
||||
// TODO: Update argument type and name
|
||||
// void onFragmentInteraction(Uri uri);
|
||||
}
|
||||
}
|
||||
|
|
@ -6,49 +6,18 @@ package com.tangem.wallet;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.cardReader.Util;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
import org.spongycastle.asn1.DERSequence;
|
||||
import org.spongycastle.asn1.DERSequenceGenerator;
|
||||
import org.spongycastle.asn1.sec.SECNamedCurves;
|
||||
import org.spongycastle.asn1.x9.X9ECParameters;
|
||||
import org.spongycastle.asn1.x9.X9IntegerConverter;
|
||||
import org.spongycastle.crypto.params.ECDomainParameters;
|
||||
import org.spongycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.spongycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.spongycastle.crypto.signers.ECDSASigner;
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
import org.spongycastle.jce.spec.ECPrivateKeySpec;
|
||||
import org.spongycastle.jce.spec.ECPublicKeySpec;
|
||||
import org.spongycastle.math.ec.ECAlgorithms;
|
||||
import org.spongycastle.math.ec.ECCurve;
|
||||
import org.spongycastle.math.ec.ECPoint;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.text.Format;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.bitcoinj.core.ECKey.CURVE;
|
||||
import static org.bitcoinj.core.ECKey.HALF_CURVE_ORDER;
|
||||
|
||||
@SuppressWarnings({"WeakerAccess", "TryWithIdenticalCatches", "unused"})
|
||||
public final class BTCUtils {
|
||||
|
|
|
|||
|
|
@ -1,19 +1,6 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.Util;
|
||||
|
||||
import org.bitcoinj.core.Base58;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by dvol on 06.08.2017.
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package com.tangem.wallet;
|
|||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.TLV;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ package com.tangem.wallet;
|
|||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.TLV;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.wallet;
|
|||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
|
|
|||
|
|
@ -5,16 +5,14 @@ package com.tangem.wallet;
|
|||
*/
|
||||
|
||||
public class CoinEngineFactory {
|
||||
public static CoinEngine Create(Blockchain chain)
|
||||
{
|
||||
if(Blockchain.BitcoinCash == chain || Blockchain.BitcoinCashTestNet == chain) {
|
||||
public static CoinEngine Create(Blockchain chain) {
|
||||
if (Blockchain.BitcoinCash == chain || Blockchain.BitcoinCashTestNet == chain) {
|
||||
return new BtcCashEngine();
|
||||
}else if(Blockchain.Bitcoin == chain || Blockchain.BitcoinTestNet == chain) {
|
||||
} else if (Blockchain.Bitcoin == chain || Blockchain.BitcoinTestNet == chain) {
|
||||
return new BtcEngine(); //TODO: ВРЕМЕНГГО!!!!
|
||||
}else if(Blockchain.Ethereum == chain || Blockchain.EthereumTestNet == chain) {
|
||||
} else if (Blockchain.Ethereum == chain || Blockchain.EthereumTestNet == chain) {
|
||||
return new EthEngine();
|
||||
}
|
||||
else if(Blockchain.Token == chain) {
|
||||
} else if (Blockchain.Token == chain) {
|
||||
return new TokenEngine();
|
||||
} else {
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.wallet;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import org.spongycastle.asn1.ASN1EncodableVector;
|
||||
import org.spongycastle.asn1.ASN1Integer;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package com.tangem.wallet;
|
|||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.TLV;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,9 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import com.tangem.cardReader.CardCrypto;
|
||||
import com.tangem.domain.cardReader.CardCrypto;
|
||||
|
||||
import org.spongycastle.jce.ECNamedCurveTable;
|
||||
import org.spongycastle.jce.spec.ECNamedCurveParameterSpec;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static com.tangem.cardReader.CardCrypto.*;
|
||||
|
||||
/**
|
||||
* Created by dvol on 14.11.2017.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.wallet;
|
|||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import android.content.SharedPreferences;
|
|||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -31,7 +31,7 @@ public class PINStorage {
|
|||
}
|
||||
|
||||
|
||||
static List<String> getPINs() {
|
||||
public static List<String> getPINs() {
|
||||
ArrayList<String> result = new ArrayList<>();
|
||||
if (mLastUsedPIN != null) result.add(mLastUsedPIN);
|
||||
if (mEncryptedPIN != null && !result.contains(mEncryptedPIN)) result.add(mEncryptedPIN);
|
||||
|
|
@ -41,7 +41,7 @@ public class PINStorage {
|
|||
return result;
|
||||
}
|
||||
|
||||
static void setLastUsedPIN(String PIN) {
|
||||
public static void setLastUsedPIN(String PIN) {
|
||||
mLastUsedPIN = PIN;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,16 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.cardReader.SettingsMask;
|
||||
import com.tangem.cardReader.Util;
|
||||
import com.tangem.domain.cardReader.SettingsMask;
|
||||
import com.tangem.domain.cardReader.Util;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
/**
|
||||
* Created by dvol on 16.07.2017.
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import android.net.Uri;
|
|||
import android.util.Log;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.TLV;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.TLV;
|
||||
|
||||
import org.bitcoinj.core.ECKey;
|
||||
|
||||
|
|
@ -24,51 +24,46 @@ import static com.tangem.wallet.FormatUtil.GetDecimalFormat;
|
|||
* Created by Ilia on 20.03.2018.
|
||||
*/
|
||||
|
||||
public class TokenEngine extends CoinEngine{
|
||||
public String GetNextNode(Tangem_Card mCard)
|
||||
{
|
||||
public class TokenEngine extends CoinEngine {
|
||||
public String GetNextNode(Tangem_Card mCard) {
|
||||
return "abc1.hsmiths.com";
|
||||
}
|
||||
public int GetNextNodePort(Tangem_Card mCard)
|
||||
{
|
||||
|
||||
public int GetNextNodePort(Tangem_Card mCard) {
|
||||
return 60001;
|
||||
}
|
||||
public String GetNode(Tangem_Card mCard)
|
||||
{
|
||||
|
||||
public String GetNode(Tangem_Card mCard) {
|
||||
return "abc1.hsmiths.com";
|
||||
}
|
||||
public int GetNodePort(Tangem_Card mCard)
|
||||
{
|
||||
|
||||
public int GetNodePort(Tangem_Card mCard) {
|
||||
return 60001;
|
||||
}
|
||||
public void SwitchNode(Tangem_Card mCard)
|
||||
{
|
||||
|
||||
public void SwitchNode(Tangem_Card mCard) {
|
||||
}
|
||||
public boolean AwaitingConfirmation(Tangem_Card card)
|
||||
{
|
||||
|
||||
public boolean AwaitingConfirmation(Tangem_Card card) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean InOutPutVisible()
|
||||
{
|
||||
public boolean InOutPutVisible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String GetBalanceCurrency(Tangem_Card card)
|
||||
{
|
||||
public String GetBalanceCurrency(Tangem_Card card) {
|
||||
String currency = card.getTokenSymbol();
|
||||
if(Strings.isNullOrEmpty(currency))
|
||||
if (Strings.isNullOrEmpty(currency))
|
||||
return "NoN";
|
||||
return currency;
|
||||
}
|
||||
|
||||
public String GetFeeCurrency()
|
||||
{
|
||||
public String GetFeeCurrency() {
|
||||
return "Gwei";
|
||||
}
|
||||
|
||||
BigDecimal convertToEth(String value)
|
||||
{
|
||||
BigDecimal convertToEth(String value) {
|
||||
BigInteger m = new BigInteger(value, 10);
|
||||
BigDecimal n = new BigDecimal(m);
|
||||
BigDecimal d = n.divide(new BigDecimal("1000000000000000000"));
|
||||
|
|
@ -77,17 +72,15 @@ public class TokenEngine extends CoinEngine{
|
|||
}
|
||||
|
||||
|
||||
public int GetTokenDecimals(Tangem_Card card)
|
||||
{
|
||||
public int GetTokenDecimals(Tangem_Card card) {
|
||||
return card.getTokensDecimal();
|
||||
}
|
||||
|
||||
public String GetContractAddress(Tangem_Card card)
|
||||
{
|
||||
public String GetContractAddress(Tangem_Card card) {
|
||||
return card.getContractAddress();
|
||||
}
|
||||
public boolean IsNeedCheckNode()
|
||||
{
|
||||
|
||||
public boolean IsNeedCheckNode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -96,21 +89,18 @@ public class TokenEngine extends CoinEngine{
|
|||
return false;
|
||||
}
|
||||
|
||||
if(!address.startsWith("0x")&&!address.startsWith("0X"))
|
||||
{
|
||||
if (!address.startsWith("0x") && !address.startsWith("0X")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(address.length()!=42)
|
||||
{
|
||||
if (address.length() != 42) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String GetBalanceAlterValue(Tangem_Card mCard)
|
||||
{
|
||||
public String GetBalanceAlterValue(Tangem_Card mCard) {
|
||||
String dec = mCard.getDecimalBalanceAlter();
|
||||
BigDecimal d = convertToEth(dec);
|
||||
String s = d.toString();
|
||||
|
|
@ -121,9 +111,8 @@ public class TokenEngine extends CoinEngine{
|
|||
return output;
|
||||
}
|
||||
|
||||
public String GetBalanceValue(Tangem_Card mCard)
|
||||
{
|
||||
if(!HasBalanceInfo(mCard))
|
||||
public String GetBalanceValue(Tangem_Card mCard) {
|
||||
if (!HasBalanceInfo(mCard))
|
||||
return "-- -- -- " + GetBalanceCurrency(mCard);
|
||||
|
||||
String dec = mCard.getDecimalBalance();
|
||||
|
|
@ -138,28 +127,24 @@ public class TokenEngine extends CoinEngine{
|
|||
return output;
|
||||
}
|
||||
|
||||
public boolean CheckAmount(Tangem_Card card, String amount) throws Exception
|
||||
{
|
||||
public boolean CheckAmount(Tangem_Card card, String amount) throws Exception {
|
||||
DecimalFormat decimalFormat = GetDecimalFormat();
|
||||
BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); //new BigDecimal(strAmount);
|
||||
BigDecimal maxValue = new BigDecimal(GetBalanceValue(card));
|
||||
if(amountValue.compareTo(maxValue) > 0 )
|
||||
{
|
||||
if (amountValue.compareTo(maxValue) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public Long GetBalanceLong(Tangem_Card mCard)
|
||||
{
|
||||
public Long GetBalanceLong(Tangem_Card mCard) {
|
||||
return mCard.getBalance();
|
||||
}
|
||||
|
||||
public boolean IsBalanceAlterNotZero(Tangem_Card card)
|
||||
{
|
||||
public boolean IsBalanceAlterNotZero(Tangem_Card card) {
|
||||
String balance = card.getDecimalBalanceAlter();
|
||||
if(balance == null || balance == "")
|
||||
if (balance == null || balance == "")
|
||||
return false;
|
||||
|
||||
BigDecimal bi = new BigDecimal(balance);
|
||||
|
|
@ -170,10 +155,9 @@ public class TokenEngine extends CoinEngine{
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean IsBalanceNotZero(Tangem_Card card)
|
||||
{
|
||||
public boolean IsBalanceNotZero(Tangem_Card card) {
|
||||
String balance = card.getDecimalBalance();
|
||||
if(balance == null || balance == "")
|
||||
if (balance == null || balance == "")
|
||||
return false;
|
||||
|
||||
BigDecimal bi = new BigDecimal(balance);
|
||||
|
|
@ -184,21 +168,20 @@ public class TokenEngine extends CoinEngine{
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean HasBalanceInfo(Tangem_Card card)
|
||||
{
|
||||
public boolean HasBalanceInfo(Tangem_Card card) {
|
||||
String balance = card.getDecimalBalance();
|
||||
if(balance == null || balance == "")
|
||||
if (balance == null || balance == "")
|
||||
return false;
|
||||
|
||||
String balanceEx = card.getDecimalBalanceAlter();
|
||||
if(balanceEx == null || balanceEx == "")
|
||||
if (balanceEx == null || balanceEx == "")
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String GetBalanceEquivalent(Tangem_Card mCard) {
|
||||
if(!HasBalanceInfo(mCard)){
|
||||
if (!HasBalanceInfo(mCard)) {
|
||||
return "-- -- -- ";
|
||||
}
|
||||
String dec = mCard.getDecimalBalance();
|
||||
|
|
@ -208,7 +191,7 @@ public class TokenEngine extends CoinEngine{
|
|||
|
||||
@Override
|
||||
public String GetBalance(Tangem_Card mCard) {
|
||||
if(!HasBalanceInfo(mCard)){
|
||||
if (!HasBalanceInfo(mCard)) {
|
||||
return "-- -- -- " + GetBalanceCurrency(mCard);
|
||||
}
|
||||
|
||||
|
|
@ -218,15 +201,12 @@ public class TokenEngine extends CoinEngine{
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public String GetBalanceWithAlter(Tangem_Card mCard)
|
||||
{
|
||||
public String GetBalanceWithAlter(Tangem_Card mCard) {
|
||||
//return GetBalance(mCard) + "\n(" + GetBalanceAlterValue(mCard) + " ETH)";
|
||||
return " " + GetBalance(mCard) + " <br><small><small> + " + GetBalanceAlterValue(mCard) + " ETH for gas</small></small>";
|
||||
}
|
||||
|
||||
public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException {
|
||||
public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException {
|
||||
Keccak256 kec = new Keccak256();
|
||||
int lenPk = pkUncompressed.length;
|
||||
if (lenPk < 2) {
|
||||
|
|
@ -262,35 +242,29 @@ public class TokenEngine extends CoinEngine{
|
|||
}
|
||||
|
||||
|
||||
public String GetAmountEqualentDescriptor(Tangem_Card mCard, String value)
|
||||
{
|
||||
public String GetAmountEqualentDescriptor(Tangem_Card mCard, String value) {
|
||||
BigDecimal d = new BigDecimal(value);
|
||||
return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRate());
|
||||
}
|
||||
|
||||
public String GetFeeEqualentDescriptor(Tangem_Card mCard, String value)
|
||||
{
|
||||
public String GetFeeEqualentDescriptor(Tangem_Card mCard, String value) {
|
||||
BigDecimal d = new BigDecimal(value);
|
||||
return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRateAlter());
|
||||
}
|
||||
|
||||
public Uri getShareWalletURIExplorer(Tangem_Card mCard)
|
||||
{
|
||||
return Uri.parse("https://etherscan.io/token/"+GetContractAddress(mCard)+"?a=" + mCard.getWallet());
|
||||
public Uri getShareWalletURIExplorer(Tangem_Card mCard) {
|
||||
return Uri.parse("https://etherscan.io/token/" + GetContractAddress(mCard) + "?a=" + mCard.getWallet());
|
||||
}
|
||||
|
||||
public Uri getShareWalletURI(Tangem_Card mCard)
|
||||
{
|
||||
public Uri getShareWalletURI(Tangem_Card mCard) {
|
||||
return Uri.parse("" + mCard.getWallet());
|
||||
}
|
||||
|
||||
public boolean CheckUnspentTransaction(Tangem_Card mCard)
|
||||
{
|
||||
public boolean CheckUnspentTransaction(Tangem_Card mCard) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits)
|
||||
{
|
||||
public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) {
|
||||
Long fee = null;
|
||||
BigDecimal amount = null;
|
||||
try {
|
||||
|
|
@ -301,14 +275,14 @@ public class TokenEngine extends CoinEngine{
|
|||
return false;
|
||||
}
|
||||
|
||||
if(fee == null || amount == null)
|
||||
if (fee == null || amount == null)
|
||||
return false;
|
||||
|
||||
if(fee == 0 || amount.compareTo(BigDecimal.ZERO) == 0)
|
||||
if (fee == 0 || amount.compareTo(BigDecimal.ZERO) == 0)
|
||||
return false;
|
||||
|
||||
|
||||
if(fee < minFeeInInternalUnits)
|
||||
if (fee < minFeeInInternalUnits)
|
||||
return false;
|
||||
|
||||
|
||||
|
|
@ -322,8 +296,7 @@ public class TokenEngine extends CoinEngine{
|
|||
return true;
|
||||
}
|
||||
|
||||
public String EvaluteFeeEquivalent(Tangem_Card mCard, String fee)
|
||||
{
|
||||
public String EvaluteFeeEquivalent(Tangem_Card mCard, String fee) {
|
||||
BigDecimal gweFee = new BigDecimal(fee);
|
||||
gweFee = gweFee.divide(new BigDecimal("1000000000"));
|
||||
gweFee = gweFee.setScale(18, RoundingMode.DOWN);
|
||||
|
|
@ -334,7 +307,7 @@ public class TokenEngine extends CoinEngine{
|
|||
|
||||
BigInteger nonceValue = mCard.GetConfirmTXCount();
|
||||
byte[] pbKey = mCard.getWalletPublicKey();
|
||||
boolean flag = (mCard.getSigningMethod()== Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
boolean flag = (mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer);
|
||||
Issuer issuer = mCard.getIssuer();
|
||||
|
||||
|
||||
|
|
@ -353,8 +326,6 @@ public class TokenEngine extends CoinEngine{
|
|||
BigInteger amount = amountDec.toBigInteger(); //new BigInteger(amountValue, 10);
|
||||
|
||||
|
||||
|
||||
|
||||
//amount = amount.subtract(fee);
|
||||
|
||||
BigInteger nonce = nonceValue;
|
||||
|
|
@ -384,12 +355,11 @@ public class TokenEngine extends CoinEngine{
|
|||
amountLeadZero = amountLeadZero.substring(2);
|
||||
}
|
||||
|
||||
while(amountLeadZero.length() < 64)
|
||||
{
|
||||
while (amountLeadZero.length() < 64) {
|
||||
amountLeadZero = "0" + amountLeadZero;
|
||||
}
|
||||
|
||||
String cmd = "a9059cbb000000000000000000000000"+to+amountLeadZero; //TODO only for BAT
|
||||
String cmd = "a9059cbb000000000000000000000000" + to + amountLeadZero; //TODO only for BAT
|
||||
|
||||
|
||||
byte[] data = BTCUtils.fromHex(cmd);
|
||||
|
|
@ -416,8 +386,7 @@ public class TokenEngine extends CoinEngine{
|
|||
|
||||
boolean f = ECKey.verify(for_hash, new ECKey.ECDSASignature(r, s), pbKey);
|
||||
|
||||
if(!f)
|
||||
{
|
||||
if (!f) {
|
||||
Log.e("ETH-CHECK", "Sign Failed.");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import android.content.Context;
|
|||
import android.nfc.tech.IsoDep;
|
||||
import android.util.Log;
|
||||
|
||||
import com.tangem.cardReader.CardProtocol;
|
||||
import com.tangem.cardReader.NfcManager;
|
||||
import com.tangem.domain.cardReader.CardProtocol;
|
||||
import com.tangem.domain.cardReader.NfcManager;
|
||||
|
||||
/**
|
||||
* Created by dvol on 04.02.2018.
|
||||
|
|
|
|||
|
|
@ -1,70 +0,0 @@
|
|||
package com.tangem.wallet;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.text.TextPaint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.Gravity;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class VerticalTextView extends TextView
|
||||
{
|
||||
final boolean topDown;
|
||||
|
||||
public VerticalTextView( Context context,
|
||||
AttributeSet attrs )
|
||||
{
|
||||
super( context, attrs );
|
||||
final int gravity = getGravity();
|
||||
if ( Gravity.isVertical( gravity )
|
||||
&& ( gravity & Gravity.VERTICAL_GRAVITY_MASK )
|
||||
== Gravity.BOTTOM )
|
||||
{
|
||||
setGravity(
|
||||
( gravity & Gravity.HORIZONTAL_GRAVITY_MASK )
|
||||
| Gravity.TOP );
|
||||
topDown = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
topDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure( int widthMeasureSpec,
|
||||
int heightMeasureSpec )
|
||||
{
|
||||
super.onMeasure( heightMeasureSpec,
|
||||
widthMeasureSpec );
|
||||
setMeasuredDimension( getMeasuredHeight(),
|
||||
getMeasuredWidth() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw( Canvas canvas )
|
||||
{
|
||||
TextPaint textPaint = getPaint();
|
||||
textPaint.setColor( getCurrentTextColor() );
|
||||
textPaint.drawableState = getDrawableState();
|
||||
|
||||
canvas.save();
|
||||
|
||||
if ( topDown )
|
||||
{
|
||||
canvas.translate( getWidth(), 0 );
|
||||
canvas.rotate( 90 );
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas.translate( 0, getHeight() );
|
||||
canvas.rotate( -90 );
|
||||
}
|
||||
|
||||
canvas.translate( getCompoundPaddingLeft(),
|
||||
getExtendedPaddingTop() );
|
||||
|
||||
getLayout().draw( canvas );
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue