From 52ce16bb09cde354554bec5a0ef0c96b1db73ba2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 29 May 2018 21:45:37 +0300 Subject: [PATCH] Updated on 2026-08-14 --- .idea/caches/build_file_checksums.ser | Bin 536 -> 536 bytes .idea/misc.xml | 2 +- app/build.gradle | 35 +- app/src/main/AndroidManifest.xml | 4 +- .../tangem/{wallet => }/LogFileProvider.java | 216 +- ...trum_Request.java => ElectrumRequest.java} | 34 +- .../network/request/FeeRequest.java} | 204 +- .../{Electrum_Task.java => ElectrumTask.java} | 16 +- .../task/{Fee_Task.java => FeeTask.java} | 14 +- .../{Infura_Task.java => InfuraTask.java} | 8 +- .../network/task}/VerifyCardTask.java | 220 +- .../main/java/com/tangem/domain/Logic.java | 4 - .../tangem/domain/cardReader/CardCrypto.java | 4 +- .../domain/cardReader/CardProtocol.java | 49 +- .../tangem/domain/cardReader/CommandApdu.java | 2 + .../domain/cardReader/CustomCardReader.java | 2 + .../domain/cardReader/ResponseApdu.java | 2 + .../com/tangem/domain/cardReader/TLV.java | 2 + .../com/tangem/domain/cardReader/TLVList.java | 2 + .../tangem/{ => domain}/wallet/BTCUtils.java | 976 ++-- .../tangem/{ => domain}/wallet/Base58.java | 228 +- .../{ => domain}/wallet/BitcoinException.java | 70 +- .../wallet/BitcoinInputStream.java | 138 +- .../wallet/BitcoinOutputStream.java | 83 +- .../{ => domain}/wallet/Blockchain.java | 173 +- .../{ => domain}/wallet/BtcCashEngine.java | 817 ++-- .../tangem/{ => domain}/wallet/BtcEngine.java | 1088 +++-- .../tangem/{ => domain}/wallet/ByteUtil.java | 76 +- .../com/tangem/domain/wallet/CoinEngine.java | 82 + .../wallet/CoinEngineFactory.java | 42 +- .../{ => domain}/wallet/CryptoUtil.java | 540 +-- .../{ => domain}/wallet/DerEncodingUtil.java | 262 +- .../wallet/DeviceNFCAntennaLocation.java | 50 +- .../{ => domain}/wallet/DeviceName.java | 4182 ++++++++--------- .../tangem/{ => domain}/wallet/Digest.java | 226 +- .../{ => domain}/wallet/DigestEngine.java | 440 +- .../wallet/ECDSASignature_ETH.java | 104 +- .../{ => domain}/wallet/ETH_Transaction.java | 458 +- .../tangem/{ => domain}/wallet/EthEngine.java | 784 +-- .../wallet/FingerprintHelper.java | 2 +- .../{ => domain}/wallet/FormatUtil.java | 102 +- .../{ => domain}/wallet/Infura_Request.java | 394 +- .../tangem/{ => domain}/wallet/Issuer.java | 240 +- .../tangem/{ => domain}/wallet/Keccak256.java | 76 +- .../{ => domain}/wallet/KeccakCore.java | 1092 ++--- .../{ => domain}/wallet/LastSignStorage.java | 290 +- .../tangem/{ => domain}/wallet/Logger.java | 570 +-- .../{ => domain}/wallet/Manufacturer.java | 237 +- .../{ => domain}/wallet/PINStorage.java | 410 +- .../com/tangem/{ => domain}/wallet/RLP.java | 454 +- .../{ => domain}/wallet/RLPElement.java | 24 +- .../tangem/{ => domain}/wallet/RLPList.java | 74 +- .../{ => domain}/wallet/SharedData.java | 44 +- .../wallet/TangemCard.java} | 8 +- .../{ => domain}/wallet/TokenEngine.java | 810 ++-- .../{ => domain}/wallet/Transaction.java | 1262 +++-- .../wallet/UnspentOutputInfo.java | 54 +- .../activity/CardInfoActivity.java | 6 +- .../activity/ConfirmPaymentActivity.java | 78 +- .../activity/CreateNewWalletActivity.java | 10 +- .../activity/EmptyWalletActivity.java | 12 +- .../activity/LoadedWalletActivity.java | 8 +- .../presentation/activity/LogoActivity.java | 25 +- .../presentation/activity/MainActivity.java | 18 +- .../activity/PreparePaymentActivity.java | 14 +- .../presentation/activity/PurgeActivity.java | 10 +- .../activity/RequestPINActivity.java | 10 +- .../activity/SavePINActivity.java | 4 +- .../activity/SendTransactionActivity.java | 38 +- .../activity/SignPaymentActivity.java | 2 +- .../activity/SwapPINActivity.java | 10 +- .../activity/VerifyCardActivity.java | 6 +- .../presentation/adapter/CardListAdapter.java | 72 +- .../adapter/CardUnspentListAdapter.java | 10 +- ...ragment.java => LoadedWalletFragment.java} | 102 +- ...ctivityFragment.java => MainFragment.java} | 94 +- ...yFragment.java => VerifyCardFragment.java} | 14 +- .../fragment/WalletInfoFragment.java | 8 +- .../tangem/{wallet => util}/PhoneUtility.java | 72 +- .../{domain/cardReader => util}/Util.java | 2 +- .../java/com/tangem/wallet/CoinEngine.java | 82 - app/src/main/res/layout/activity_logo.xml | 2 +- .../main/res/layout/content_loaded_wallet.xml | 2 +- app/src/main/res/layout/content_main.xml | 2 +- .../main/res/layout/content_verify_card.xml | 2 +- build.gradle | 5 - 86 files changed, 9207 insertions(+), 9295 deletions(-) rename app/src/main/java/com/tangem/{wallet => }/LogFileProvider.java (96%) rename app/src/main/java/com/tangem/data/network/request/{Electrum_Request.java => ElectrumRequest.java} (83%) rename app/src/main/java/com/tangem/{wallet/Fee_Request.java => data/network/request/FeeRequest.java} (85%) rename app/src/main/java/com/tangem/data/network/task/{Electrum_Task.java => ElectrumTask.java} (85%) rename app/src/main/java/com/tangem/data/network/task/{Fee_Task.java => FeeTask.java} (79%) rename app/src/main/java/com/tangem/data/network/task/{Infura_Task.java => InfuraTask.java} (94%) rename app/src/main/java/com/tangem/{wallet => data/network/task}/VerifyCardTask.java (90%) delete mode 100644 app/src/main/java/com/tangem/domain/Logic.java rename app/src/main/java/com/tangem/{ => domain}/wallet/BTCUtils.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Base58.java (97%) rename app/src/main/java/com/tangem/{ => domain}/wallet/BitcoinException.java (95%) rename app/src/main/java/com/tangem/{ => domain}/wallet/BitcoinInputStream.java (91%) rename app/src/main/java/com/tangem/{ => domain}/wallet/BitcoinOutputStream.java (93%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Blockchain.java (91%) rename app/src/main/java/com/tangem/{ => domain}/wallet/BtcCashEngine.java (63%) rename app/src/main/java/com/tangem/{ => domain}/wallet/BtcEngine.java (67%) rename app/src/main/java/com/tangem/{ => domain}/wallet/ByteUtil.java (94%) create mode 100644 app/src/main/java/com/tangem/domain/wallet/CoinEngine.java rename app/src/main/java/com/tangem/{ => domain}/wallet/CoinEngineFactory.java (93%) rename app/src/main/java/com/tangem/{ => domain}/wallet/CryptoUtil.java (97%) rename app/src/main/java/com/tangem/{ => domain}/wallet/DerEncodingUtil.java (95%) rename app/src/main/java/com/tangem/{ => domain}/wallet/DeviceNFCAntennaLocation.java (93%) rename app/src/main/java/com/tangem/{ => domain}/wallet/DeviceName.java (97%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Digest.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/DigestEngine.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/ECDSASignature_ETH.java (92%) rename app/src/main/java/com/tangem/{ => domain}/wallet/ETH_Transaction.java (95%) rename app/src/main/java/com/tangem/{ => domain}/wallet/EthEngine.java (77%) rename app/src/main/java/com/tangem/{ => domain}/wallet/FingerprintHelper.java (98%) rename app/src/main/java/com/tangem/{ => domain}/wallet/FormatUtil.java (94%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Infura_Request.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Issuer.java (97%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Keccak256.java (90%) rename app/src/main/java/com/tangem/{ => domain}/wallet/KeccakCore.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/LastSignStorage.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Logger.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Manufacturer.java (89%) rename app/src/main/java/com/tangem/{ => domain}/wallet/PINStorage.java (96%) rename app/src/main/java/com/tangem/{ => domain}/wallet/RLP.java (95%) rename app/src/main/java/com/tangem/{ => domain}/wallet/RLPElement.java (79%) rename app/src/main/java/com/tangem/{ => domain}/wallet/RLPList.java (93%) rename app/src/main/java/com/tangem/{ => domain}/wallet/SharedData.java (90%) rename app/src/main/java/com/tangem/{wallet/Tangem_Card.java => domain/wallet/TangemCard.java} (99%) rename app/src/main/java/com/tangem/{ => domain}/wallet/TokenEngine.java (79%) rename app/src/main/java/com/tangem/{ => domain}/wallet/Transaction.java (97%) rename app/src/main/java/com/tangem/{ => domain}/wallet/UnspentOutputInfo.java (93%) rename app/src/main/java/com/tangem/presentation/fragment/{LoadedWalletActivityFragment.java => LoadedWalletFragment.java} (94%) rename app/src/main/java/com/tangem/presentation/fragment/{MainActivityFragment.java => MainFragment.java} (92%) rename app/src/main/java/com/tangem/presentation/fragment/{VerifyCardActivityFragment.java => VerifyCardFragment.java} (96%) rename app/src/main/java/com/tangem/{wallet => util}/PhoneUtility.java (95%) rename app/src/main/java/com/tangem/{domain/cardReader => util}/Util.java (99%) delete mode 100644 app/src/main/java/com/tangem/wallet/CoinEngine.java diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 14e5826a1f2f42cf22bfa29132e48bc3e16e898d..f5952dda1bbf4d27d19039597fb3820e71cd23d1 100644 GIT binary patch delta 53 zcmV-50LuTE1egSnm;|je4(ySfpAg-eO=io;22C%n`$uljLno6<0lX2xiH!N*OtsNo L?6~RF@OMLamM|Ls delta 53 zcmV-50LuTE1egSnm;|fkvRsjzpAcUj2ui2Jp<-O`TXjcrd`FW@0lX2}grV;{%`YJZ L(KS?xaLW^Tcd!>y diff --git a/.idea/misc.xml b/.idea/misc.xml index dc3456943d..cc51e58ed3 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -25,7 +25,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index a244f5075b..c7f95c1e96 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,41 +9,44 @@ android { minSdkVersion 23 targetSdkVersion 27 versionCode 1 - versionName "1.0" -// versionCode versionBuild -// versionName versionPrefix+"."+getVersionExtentionString(versionBuild) + versionName "0.85.5.831.dev" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } + buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } } dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation fileTree(include: ['*.jar'], dir: 'libs') + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:27.1.1' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.android.support:design:27.1.1' implementation 'com.android.support:support-compat:27.1.1' implementation 'com.android.support.constraint:constraint-layout:1.1.0' - implementation 'com.madgag.spongycastle:core:1.56.0.0' - implementation 'com.madgag.spongycastle:prov:1.56.0.0' - implementation 'com.google.zxing:core:3.3.2' - implementation 'org.bitcoinj:bitcoinj-parent:0.14.4' - implementation 'org.bitcoinj:bitcoinj-core:0.14.4' implementation 'com.android.support:cardview-v7:27.1.1' implementation 'com.android.support:support-v4:27.1.1' - testImplementation 'junit:junit:4.12' + implementation 'com.google.zxing:core:3.3.2' + implementation 'com.google.dagger:dagger:2.13' + implementation 'com.madgag.spongycastle:core:1.56.0.0' + implementation 'com.madgag.spongycastle:prov:1.56.0.0' + implementation 'org.bitcoinj:bitcoinj-parent:0.14.4' + implementation 'org.bitcoinj:bitcoinj-core:0.14.4' implementation 'me.dm7.barcodescanner:zxing:1.9.8' implementation 'com.scottyab:rootbeer-lib:0.0.6' implementation 'com.skyfishjy.ripplebackground:library:1.0.1' implementation 'info.hoang8f:android-segmented:1.0.6' - implementation 'com.google.dagger:dagger:2.13' -} + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 10b3fd44d6..9b038f071c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,8 +25,8 @@ android:theme="@style/AppTheme"> diff --git a/app/src/main/java/com/tangem/wallet/LogFileProvider.java b/app/src/main/java/com/tangem/LogFileProvider.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/LogFileProvider.java rename to app/src/main/java/com/tangem/LogFileProvider.java index 7c09580b29..8a0a3efd35 100644 --- a/app/src/main/java/com/tangem/wallet/LogFileProvider.java +++ b/app/src/main/java/com/tangem/LogFileProvider.java @@ -1,108 +1,108 @@ -package com.tangem.wallet; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.UriMatcher; -import android.database.Cursor; -import android.net.Uri; -import android.os.ParcelFileDescriptor; -import android.util.Log; - -import java.io.File; -import java.io.FileNotFoundException; - -/** - * Created by dvol on 15.02.2018. - */ - -public class LogFileProvider extends ContentProvider { - - private static final String CLASS_NAME = "LogFileProvider"; - - // The authority is the symbolic name for the provider class - public static final String AUTHORITY = "com.tangem.wallet.LogFileProvider"; - - // UriMatcher used to match against incoming requests - private UriMatcher uriMatcher; - - @Override - public boolean onCreate() { - uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - - // Add a URI to the matcher which will match against the form - // 'content://it.my.app.LogFileProvider/*' - // and return 1 in the case that the incoming Uri matches this pattern - uriMatcher.addURI(AUTHORITY, "*", 1); - - return true; - } - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - - String LOG_TAG = CLASS_NAME+"-oF"; - - Log.v(LOG_TAG, - "Called with uri: '" + uri + "'." + uri.getLastPathSegment()); - - // Check incoming Uri against the matcher - switch (uriMatcher.match(uri)) { - - // If it returns 1 - then it matches the Uri defined in onCreate - case 1: - - // The desired file name is specified by the last segment of the - // path - // E.g. - // 'content://it.my.app.LogFileProvider/Test.txt' - // Take this and build the path to the file - String fileLocation = getContext().getCacheDir() + File.separator - + uri.getLastPathSegment(); - - // Create & return a ParcelFileDescriptor pointing to the file - // Note: I don't care what mode they ask for - they're only getting - // read only - ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File( - fileLocation), ParcelFileDescriptor.MODE_READ_ONLY); - return pfd; - - // Otherwise unrecognised Uri - default: - Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'."); - throw new FileNotFoundException("Unsupported uri: " - + uri.toString()); - } - } - - // ////////////////////////////////////////////////////////////// - // Not supported / used / required for this example - // ////////////////////////////////////////////////////////////// - - @Override - public int update(Uri uri, ContentValues contentvalues, String s, - String[] as) { - return 0; - } - - @Override - public int delete(Uri uri, String s, String[] as) { - return 0; - } - - @Override - public Uri insert(Uri uri, ContentValues contentvalues) { - return null; - } - - @Override - public String getType(Uri uri) { - return null; - } - - @Override - public Cursor query(Uri uri, String[] projection, String s, String[] as1, - String s1) { - return null; - } -} +package com.tangem; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.content.UriMatcher; +import android.database.Cursor; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.util.Log; + +import java.io.File; +import java.io.FileNotFoundException; + +/** + * Created by dvol on 15.02.2018. + */ + +public class LogFileProvider extends ContentProvider { + + private static final String CLASS_NAME = "LogFileProvider"; + + // The authority is the symbolic name for the provider class + public static final String AUTHORITY = "com.tangem.wallet.LogFileProvider"; + + // UriMatcher used to match against incoming requests + private UriMatcher uriMatcher; + + @Override + public boolean onCreate() { + uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); + + // Add a URI to the matcher which will match against the form + // 'content://it.my.app.LogFileProvider/*' + // and return 1 in the case that the incoming Uri matches this pattern + uriMatcher.addURI(AUTHORITY, "*", 1); + + return true; + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) + throws FileNotFoundException { + + String LOG_TAG = CLASS_NAME+"-oF"; + + Log.v(LOG_TAG, + "Called with uri: '" + uri + "'." + uri.getLastPathSegment()); + + // Check incoming Uri against the matcher + switch (uriMatcher.match(uri)) { + + // If it returns 1 - then it matches the Uri defined in onCreate + case 1: + + // The desired file name is specified by the last segment of the + // path + // E.g. + // 'content://it.my.app.LogFileProvider/Test.txt' + // Take this and build the path to the file + String fileLocation = getContext().getCacheDir() + File.separator + + uri.getLastPathSegment(); + + // Create & return a ParcelFileDescriptor pointing to the file + // Note: I don't care what mode they ask for - they're only getting + // read only + ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File( + fileLocation), ParcelFileDescriptor.MODE_READ_ONLY); + return pfd; + + // Otherwise unrecognised Uri + default: + Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'."); + throw new FileNotFoundException("Unsupported uri: " + + uri.toString()); + } + } + + // ////////////////////////////////////////////////////////////// + // Not supported / used / required for this example + // ////////////////////////////////////////////////////////////// + + @Override + public int update(Uri uri, ContentValues contentvalues, String s, + String[] as) { + return 0; + } + + @Override + public int delete(Uri uri, String s, String[] as) { + return 0; + } + + @Override + public Uri insert(Uri uri, ContentValues contentvalues) { + return null; + } + + @Override + public String getType(Uri uri) { + return null; + } + + @Override + public Cursor query(Uri uri, String[] projection, String s, String[] as1, + String s1) { + return null; + } +} diff --git a/app/src/main/java/com/tangem/data/network/request/Electrum_Request.java b/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java similarity index 83% rename from app/src/main/java/com/tangem/data/network/request/Electrum_Request.java rename to app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java index bb61241842..cabe3dfe88 100644 --- a/app/src/main/java/com/tangem/data/network/request/Electrum_Request.java +++ b/app/src/main/java/com/tangem/data/network/request/ElectrumRequest.java @@ -8,7 +8,7 @@ import org.json.JSONObject; * Created by dvol on 16.07.2017. */ -public class Electrum_Request { +public class ElectrumRequest { 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"; @@ -25,10 +25,10 @@ public class Electrum_Request { public String Host; public int Port; - private Electrum_Request() { + private ElectrumRequest() { } - public Electrum_Request(JSONObject jsRequest) { + public ElectrumRequest(JSONObject jsRequest) { try { jsRequestData = new JSONObject(jsRequest.toString()); } catch (JSONException e) { @@ -70,8 +70,8 @@ public class Electrum_Request { } } - public static Electrum_Request CheckBalance(String wallet) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest CheckBalance(String wallet) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetBalance + "\", \"params\":[\"" + wallet + "\"] }"); @@ -83,8 +83,8 @@ public class Electrum_Request { } - public static Electrum_Request GetFee(String wallet) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest GetFee(String wallet) { + ElectrumRequest request = new ElectrumRequest(); try{ request.WalletAddress = wallet; //METHOD_GetFee request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetFee + "\", \"params\":[\"" + 6 + "\"] }"); @@ -97,8 +97,8 @@ public class Electrum_Request { return request; } - public static Electrum_Request GetHeader(String wallet, String height) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest GetHeader(String wallet, String height) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHeader + "\", \"params\":[\"" + height + "\"] }"); @@ -109,8 +109,8 @@ public class Electrum_Request { return request; } - public static Electrum_Request ListUnspent(String wallet) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest ListUnspent(String wallet) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ListUnspent + "\", \"params\":[\"" + wallet + "\"] }"); @@ -121,8 +121,8 @@ public class Electrum_Request { return request; } - public static Electrum_Request Broadcast(String wallet, String tx) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest Broadcast(String wallet, String tx) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_SendTransaction + "\", \"params\":[\"" + tx + "\"] }"); @@ -133,8 +133,8 @@ public class Electrum_Request { return request; } - public static Electrum_Request ListHistory(String wallet) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest ListHistory(String wallet) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_GetHistory + "\", \"params\":[\"" + wallet + "\"] }"); @@ -145,8 +145,8 @@ public class Electrum_Request { return request; } - public static Electrum_Request GetTransaction(String wallet, String tx_hash) { - Electrum_Request request = new Electrum_Request(); + public static ElectrumRequest GetTransaction(String wallet, String tx_hash) { + ElectrumRequest request = new ElectrumRequest(); try { request.WalletAddress=wallet; request.TxHash = tx_hash; diff --git a/app/src/main/java/com/tangem/wallet/Fee_Request.java b/app/src/main/java/com/tangem/data/network/request/FeeRequest.java similarity index 85% rename from app/src/main/java/com/tangem/wallet/Fee_Request.java rename to app/src/main/java/com/tangem/data/network/request/FeeRequest.java index 8170e82ac4..aaca678c3d 100644 --- a/app/src/main/java/com/tangem/wallet/Fee_Request.java +++ b/app/src/main/java/com/tangem/data/network/request/FeeRequest.java @@ -1,102 +1,102 @@ -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 Fee_Request { - public JSONObject jsRequestData; - public String answerData; - public String error; - public String WalletAddress; - public long txSize = 0; - - private Fee_Request() { - } - - public Fee_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 answerData; - } - - public static final int PRIORITY = 2; - public static final int NORMAL = 3; - public static final int MINIMAL = 6; - private int blockCount = NORMAL; - public void setBlockCount(int count - ) - { - blockCount = count; - } - - public int getBlockCount() - { - return blockCount; - } - - 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 Fee_Request GetFee(String wallet, long txSize, int blockCount) { - Fee_Request request = new Fee_Request(); - request.WalletAddress=wallet; - request.txSize = txSize; - request.setBlockCount(blockCount); - 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 FeeRequest { + public JSONObject jsRequestData; + public String answerData; + public String error; + public String WalletAddress; + public long txSize = 0; + + private FeeRequest() { + } + + public FeeRequest(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 answerData; + } + + public static final int PRIORITY = 2; + public static final int NORMAL = 3; + public static final int MINIMAL = 6; + private int blockCount = NORMAL; + public void setBlockCount(int count + ) + { + blockCount = count; + } + + public int getBlockCount() + { + return blockCount; + } + + 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 FeeRequest GetFee(String wallet, long txSize, int blockCount) { + FeeRequest request = new FeeRequest(); + request.WalletAddress=wallet; + request.txSize = txSize; + request.setBlockCount(blockCount); + 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"); + } +} diff --git a/app/src/main/java/com/tangem/data/network/task/Electrum_Task.java b/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java similarity index 85% rename from app/src/main/java/com/tangem/data/network/task/Electrum_Task.java rename to app/src/main/java/com/tangem/data/network/task/ElectrumTask.java index d59e1cc05d..558688e739 100644 --- a/app/src/main/java/com/tangem/data/network/task/Electrum_Task.java +++ b/app/src/main/java/com/tangem/data/network/task/ElectrumTask.java @@ -3,8 +3,8 @@ 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 com.tangem.data.network.request.ElectrumRequest; +import com.tangem.domain.wallet.SharedData; import java.io.BufferedReader; import java.io.InputStream; @@ -20,7 +20,7 @@ import java.util.List; * Created by dvol on 16.07.2017. */ -public class Electrum_Task extends AsyncTask> { +public class ElectrumTask extends AsyncTask> { public static final String logTag = "Electrum"; //public static final String Host = /*"hsmiths.changeip.net";*/ "testnetnode.arihanc.com"; //public static final int Port = /*8080*/51001; @@ -33,13 +33,13 @@ public class Electrum_Task extends AsyncTask doInBackground(Electrum_Request... requests) { - List result = new ArrayList<>(); + protected List doInBackground(ElectrumRequest... requests) { + List result = new ArrayList<>(); for (int i = 0; i < requests.length; i++) { result.add(requests[i]); } @@ -89,7 +89,7 @@ public class Electrum_Task extends AsyncTask> { +public class FeeTask extends AsyncTask> { public SharedData sharedCounter = null; - public Fee_Task(SharedData sharedData) + public FeeTask(SharedData sharedData) { sharedCounter = sharedData; } - protected List doInBackground(Fee_Request... requests) { - List result = new ArrayList<>(); + protected List doInBackground(FeeRequest... requests) { + List result = new ArrayList<>(); for (int i = 0; i < requests.length; i++) { result.add(requests[i]); } - for (Fee_Request request: result) + for (FeeRequest request: result) { HttpURLConnection httpcon = null; diff --git a/app/src/main/java/com/tangem/data/network/task/Infura_Task.java b/app/src/main/java/com/tangem/data/network/task/InfuraTask.java similarity index 94% rename from app/src/main/java/com/tangem/data/network/task/Infura_Task.java rename to app/src/main/java/com/tangem/data/network/task/InfuraTask.java index da4afee677..fd16b8ef74 100644 --- a/app/src/main/java/com/tangem/data/network/task/Infura_Task.java +++ b/app/src/main/java/com/tangem/data/network/task/InfuraTask.java @@ -6,8 +6,8 @@ package com.tangem.data.network.task; import android.os.AsyncTask; -import com.tangem.wallet.Blockchain; -import com.tangem.wallet.Infura_Request; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.Infura_Request; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -25,10 +25,10 @@ import javax.net.ssl.HttpsURLConnection; * Created by Ilia on 04.12.2017. */ -public class Infura_Task extends AsyncTask> { +public class InfuraTask extends AsyncTask> { private Exception exception; private Blockchain blockchain; - public Infura_Task(Blockchain blockchainNet) + public InfuraTask(Blockchain blockchainNet) { blockchain = blockchainNet; } diff --git a/app/src/main/java/com/tangem/wallet/VerifyCardTask.java b/app/src/main/java/com/tangem/data/network/task/VerifyCardTask.java similarity index 90% rename from app/src/main/java/com/tangem/wallet/VerifyCardTask.java rename to app/src/main/java/com/tangem/data/network/task/VerifyCardTask.java index b11e4c8566..0f487578e5 100644 --- a/app/src/main/java/com/tangem/wallet/VerifyCardTask.java +++ b/app/src/main/java/com/tangem/data/network/task/VerifyCardTask.java @@ -1,109 +1,111 @@ -package com.tangem.wallet; - -import android.content.Context; -import android.nfc.tech.IsoDep; -import android.util.Log; - -import com.tangem.domain.cardReader.CardProtocol; -import com.tangem.domain.cardReader.NfcManager; - -/** - * Created by dvol on 04.02.2018. - */ - -public class VerifyCardTask extends Thread { - - IsoDep mIsoDep; - CardProtocol.Notifications mNotifications; - private final String logTag = "VerifyCardTask"; - private boolean isCancelled = false; - private Context mContext; - private Tangem_Card mCard; - private NfcManager mNfcManager; - - public VerifyCardTask(Context context, Tangem_Card card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) { - mCard = card; - mContext = context; - mIsoDep = isoDep; - mNotifications = notifications; - mNfcManager = nfcManager; - } - - @Override - public void run() { - if (mIsoDep == null) { - return; - } - try { - // for Samsung's bugs - - // Workaround for the Samsung Galaxy S5 (since the - // first connection always hangs on transceive). - int timeout = mIsoDep.getTimeout(); - mIsoDep.connect(); - mIsoDep.close(); - mIsoDep.connect(); - mIsoDep.setTimeout(timeout); - try { - CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications); - mNotifications.OnReadStart(protocol); - try { - mNotifications.OnReadProgress(protocol, 5); - - Log.i("VerifyCardTask", "[-- Start verify card --]"); - - if (isCancelled) return; - - String PIN = mCard.getPIN(); - protocol.setPIN(PIN); - protocol.run_Read(); - PINStorage.setLastUsedPIN(PIN); - mNotifications.OnReadProgress(protocol, 30); - if (isCancelled) return; - protocol.run_VerifyCard(); - mNotifications.OnReadProgress(protocol, 60); - Log.i("VerifyCardTask", "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName()); - if (isCancelled) return; - if (protocol.getCard().getStatus() == Tangem_Card.Status.Loaded) { - protocol.run_CheckWalletWithSignatureVerify(); - mNotifications.OnReadProgress(protocol, 90); - } - - - -// if (isCancelled) return; -// if (protocol.getCard().getStatus() == Tangem_Card.Status.Loaded) { -// protocol.run_CheckWithSignatureVerify(); -// } - - } catch (Exception e) { - e.printStackTrace(); - protocol.setError(e); - - } finally { - Log.i("VerifyCardTask", "[-- Finish verify card --]"); - mNotifications.OnReadFinish(protocol); - } - } finally { - mNfcManager.IgnoreTag(mIsoDep.getTag()); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - void cancel(Boolean AllowInterrupt) { - try { - if (this.isAlive()) { - isCancelled = true; - join(500); - } - if (this.isAlive() && AllowInterrupt) { - interrupt(); - mNotifications.OnReadCancel(); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - -} +package com.tangem.data.network.task; + +import android.content.Context; +import android.nfc.tech.IsoDep; +import android.util.Log; + +import com.tangem.domain.cardReader.CardProtocol; +import com.tangem.domain.cardReader.NfcManager; +import com.tangem.domain.wallet.PINStorage; +import com.tangem.domain.wallet.TangemCard; + +/** + * Created by dvol on 04.02.2018. + */ + +public class VerifyCardTask extends Thread { + + IsoDep mIsoDep; + CardProtocol.Notifications mNotifications; + private final String logTag = "VerifyCardTask"; + private boolean isCancelled = false; + private Context mContext; + private TangemCard mCard; + private NfcManager mNfcManager; + + public VerifyCardTask(Context context, TangemCard card, NfcManager nfcManager, IsoDep isoDep, CardProtocol.Notifications notifications) { + mCard = card; + mContext = context; + mIsoDep = isoDep; + mNotifications = notifications; + mNfcManager = nfcManager; + } + + @Override + public void run() { + if (mIsoDep == null) { + return; + } + try { + // for Samsung's bugs - + // Workaround for the Samsung Galaxy S5 (since the + // first connection always hangs on transceive). + int timeout = mIsoDep.getTimeout(); + mIsoDep.connect(); + mIsoDep.close(); + mIsoDep.connect(); + mIsoDep.setTimeout(timeout); + try { + CardProtocol protocol = new CardProtocol(mContext, mIsoDep, mCard, mNotifications); + mNotifications.OnReadStart(protocol); + try { + mNotifications.OnReadProgress(protocol, 5); + + Log.i("VerifyCardTask", "[-- Start verify card --]"); + + if (isCancelled) return; + + String PIN = mCard.getPIN(); + protocol.setPIN(PIN); + protocol.run_Read(); + PINStorage.setLastUsedPIN(PIN); + mNotifications.OnReadProgress(protocol, 30); + if (isCancelled) return; + protocol.run_VerifyCard(); + mNotifications.OnReadProgress(protocol, 60); + Log.i("VerifyCardTask", "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName()); + if (isCancelled) return; + if (protocol.getCard().getStatus() == TangemCard.Status.Loaded) { + protocol.run_CheckWalletWithSignatureVerify(); + mNotifications.OnReadProgress(protocol, 90); + } + + + +// if (isCancelled) return; +// if (protocol.getCard().getStatus() == TangemCard.Status.Loaded) { +// protocol.run_CheckWithSignatureVerify(); +// } + + } catch (Exception e) { + e.printStackTrace(); + protocol.setError(e); + + } finally { + Log.i("VerifyCardTask", "[-- Finish verify card --]"); + mNotifications.OnReadFinish(protocol); + } + } finally { + mNfcManager.IgnoreTag(mIsoDep.getTag()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + void cancel(Boolean AllowInterrupt) { + try { + if (this.isAlive()) { + isCancelled = true; + join(500); + } + if (this.isAlive() && AllowInterrupt) { + interrupt(); + mNotifications.OnReadCancel(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/app/src/main/java/com/tangem/domain/Logic.java b/app/src/main/java/com/tangem/domain/Logic.java deleted file mode 100644 index b222756f36..0000000000 --- a/app/src/main/java/com/tangem/domain/Logic.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.tangem.domain; - -public class Logic { -} diff --git a/app/src/main/java/com/tangem/domain/cardReader/CardCrypto.java b/app/src/main/java/com/tangem/domain/cardReader/CardCrypto.java index b21b9072b4..fc44b64f60 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CardCrypto.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CardCrypto.java @@ -2,6 +2,8 @@ package com.tangem.domain.cardReader; import android.util.Log; +import com.tangem.util.Util; + import org.spongycastle.asn1.ASN1EncodableVector; import org.spongycastle.asn1.ASN1Integer; import org.spongycastle.asn1.DERSequence; @@ -163,7 +165,7 @@ public class CardCrypto { } else { Log.e("cardCrypto","r-length:" + String.valueOf(rLength)); Log.e("cardCrypto","s-length:" + String.valueOf(sLength)); - Log.e("cardCrypto","enc:" +Util.bytesToHex(enc)); + 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) { diff --git a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java index 7f05266bab..e314ad0f9f 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CardProtocol.java @@ -6,11 +6,12 @@ import android.nfc.TagLostException; import android.nfc.tech.IsoDep; import android.util.Log; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; -import com.tangem.wallet.Issuer; -import com.tangem.wallet.Tangem_Card; -import com.tangem.wallet.Manufacturer; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.domain.wallet.Issuer; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.domain.wallet.Manufacturer; +import com.tangem.util.Util; import org.spongycastle.jce.ECNamedCurveTable; import org.spongycastle.jce.interfaces.ECPublicKey; @@ -58,7 +59,7 @@ public class CardProtocol { mError = error; } - public Tangem_Card getCard() { + public TangemCard getCard() { return mCard; } @@ -88,7 +89,7 @@ public class CardProtocol { } } - protected Tangem_Card mCard; + protected TangemCard mCard; protected Exception mError; protected Context mContext; @@ -101,10 +102,10 @@ public class CardProtocol { mIsoDep = isoDep; mNotifications = notifications; mPIN = null; - mCard = new Tangem_Card(Util.byteArrayToHexString(mIsoDep.getTag().getId())); + mCard = new TangemCard(Util.byteArrayToHexString(mIsoDep.getTag().getId())); } - public CardProtocol(Context context, IsoDep isoDep, Tangem_Card card, Notifications notifications) { + public CardProtocol(Context context, IsoDep isoDep, TangemCard card, Notifications notifications) { mContext = context; mIsoDep = isoDep; mNotifications = notifications; @@ -164,7 +165,7 @@ public class CardProtocol { byte[] sessionKey = null; - public void run_OpenSession(Tangem_Card.EncryptionMode encryptionMode) throws Exception { + public void run_OpenSession(TangemCard.EncryptionMode encryptionMode) throws Exception { sessionKey = null; try { CommandApdu cmdApdu = new CommandApdu(CommandApdu.ISO_CLA, INS.OpenSession.Code, 0, encryptionMode.getP()); @@ -280,7 +281,7 @@ public class CardProtocol { // send command APDU, get response APDU, and display HEX data to user private ResponseApdu SendAndReceive(CommandApdu cmdApdu, boolean breakOnNeedPause) throws Exception { - if (mCard.encryptionMode != Tangem_Card.EncryptionMode.None) { + if (mCard.encryptionMode != TangemCard.EncryptionMode.None) { if (sessionKey == null) { run_OpenSession(mCard.encryptionMode); } @@ -307,7 +308,7 @@ public class CardProtocol { } throw e; } - if (mCard.encryptionMode != Tangem_Card.EncryptionMode.None) { + if (mCard.encryptionMode != TangemCard.EncryptionMode.None) { rspApdu = ResponseApdu.Decrypt(rsp, sessionKey); } else { rspApdu = new ResponseApdu(rsp); @@ -388,7 +389,7 @@ public class CardProtocol { tlvIssuerData = null; } } - if (mCard.getStatus() == Tangem_Card.Status.Loaded) { + if (mCard.getStatus() == TangemCard.Status.Loaded) { // try read offline balance data if (tlvIssuerData != null && tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination) != null && mCard.getMaxSignatures() == mCard.getRemainingSignatures()) { mCard.setOfflineBalance(tlvIssuerData.getTLV(TLV.Tag.TAG_Denomination).Value); @@ -413,13 +414,13 @@ public class CardProtocol { public void parseReadResult() throws TangemException, NoSuchProviderException, NoSuchAlgorithmException { TLV tlvStatus = readResult.getTLV(TLV.Tag.TAG_Status); - mCard.setStatus(Tangem_Card.Status.fromCode(Util.byteArrayToInt(tlvStatus.Value))); + mCard.setStatus(TangemCard.Status.fromCode(Util.byteArrayToInt(tlvStatus.Value))); TLV tlvCID = readResult.getTLV(TLV.Tag.TAG_CardID); mCard.setCID(tlvCID.Value); mCard.setManufacturer(Manufacturer.FindManufacturer(readResult.getTLV(TLV.Tag.TAG_Manufacture_ID).getAsString()), true); mCard.setHealth(readResult.getTLV(TLV.Tag.TAG_Health).getAsInt()); - if (mCard.getStatus() != Tangem_Card.Status.NotPersonalized) { + if (mCard.getStatus() != TangemCard.Status.NotPersonalized) { try { TLV tlvCardPubkicKey = readResult.getTLV(TLV.Tag.TAG_CardPublicKey); if (tlvCardPubkicKey == null) @@ -514,7 +515,7 @@ public class CardProtocol { } - if (mCard.getStatus() == Tangem_Card.Status.Loaded) { + if (mCard.getStatus() == TangemCard.Status.Loaded) { TLV tlvPublicKey = readResult.getTLV(TLV.Tag.TAG_Wallet_PublicKey); @@ -544,7 +545,7 @@ public class CardProtocol { if (mCard.getCardPublicKey() == null || readResult == null) { run_Read(); } - if (mCard.getStatus() == Tangem_Card.Status.NotPersonalized) { + if (mCard.getStatus() == TangemCard.Status.NotPersonalized) { getCard().setManufacturer(Manufacturer.Unknown, false); return null; } @@ -649,12 +650,12 @@ public class CardProtocol { if (mCard.getCardPublicKey() == null || readResult == null) { run_Read(); } - if (mCard.getStatus() == Tangem_Card.Status.NotPersonalized) { + if (mCard.getStatus() == TangemCard.Status.NotPersonalized) { getCard().setManufacturer(Manufacturer.Unknown, false); return; } - if (readResult.getTagAsInt(TLV.Tag.TAG_Status) != Tangem_Card.Status.Loaded.getCode()) { + if (readResult.getTagAsInt(TLV.Tag.TAG_Status) != TangemCard.Status.Loaded.getCode()) { throw new TangemException("Card must be loaded"); } TLVList checkResult = run_CheckWallet(); @@ -922,7 +923,7 @@ public class CardProtocol { } public void run_GetSupportedEncryption() throws Exception { - mCard.encryptionMode = Tangem_Card.EncryptionMode.None; + mCard.encryptionMode = TangemCard.EncryptionMode.None; do { CommandApdu rqApdu = StartPrepareCommand(INS.Read); Log.i(logTag, String.format("[%s]\n%s", rqApdu.getCommandName(), rqApdu.getTLVs().getParsedTLVs(" "))); @@ -930,10 +931,10 @@ public class CardProtocol { ResponseApdu rspApdu = SendAndReceive(rqApdu, false); if (rspApdu.isStatus(SW.NEED_ENCRYPTION)) { - if (mCard.encryptionMode == Tangem_Card.EncryptionMode.None) { - mCard.encryptionMode = Tangem_Card.EncryptionMode.Fast; - } else if (mCard.encryptionMode == Tangem_Card.EncryptionMode.Fast) { - mCard.encryptionMode = Tangem_Card.EncryptionMode.Strong; + if (mCard.encryptionMode == TangemCard.EncryptionMode.None) { + mCard.encryptionMode = TangemCard.EncryptionMode.Fast; + } else if (mCard.encryptionMode == TangemCard.EncryptionMode.Fast) { + mCard.encryptionMode = TangemCard.EncryptionMode.Strong; } else { throw new Exception("Can't get supported encryption methods"); } diff --git a/app/src/main/java/com/tangem/domain/cardReader/CommandApdu.java b/app/src/main/java/com/tangem/domain/cardReader/CommandApdu.java index 7d60037956..0248d65f16 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CommandApdu.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CommandApdu.java @@ -1,5 +1,7 @@ package com.tangem.domain.cardReader; +import com.tangem.util.Util; + import java.io.ByteArrayOutputStream; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; diff --git a/app/src/main/java/com/tangem/domain/cardReader/CustomCardReader.java b/app/src/main/java/com/tangem/domain/cardReader/CustomCardReader.java index 2d220ecd70..6700e75a80 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/CustomCardReader.java +++ b/app/src/main/java/com/tangem/domain/cardReader/CustomCardReader.java @@ -4,6 +4,8 @@ import android.content.Context; import android.nfc.TagLostException; import android.nfc.tech.IsoDep; +import com.tangem.util.Util; + import java.io.IOException; public class CustomCardReader implements Runnable { diff --git a/app/src/main/java/com/tangem/domain/cardReader/ResponseApdu.java b/app/src/main/java/com/tangem/domain/cardReader/ResponseApdu.java index a7bf0f4a48..2b74906c06 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/ResponseApdu.java +++ b/app/src/main/java/com/tangem/domain/cardReader/ResponseApdu.java @@ -1,5 +1,7 @@ package com.tangem.domain.cardReader; +import com.tangem.util.Util; + import java.io.ByteArrayInputStream; import java.util.Arrays; diff --git a/app/src/main/java/com/tangem/domain/cardReader/TLV.java b/app/src/main/java/com/tangem/domain/cardReader/TLV.java index 0b8721a683..40c613b890 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/TLV.java +++ b/app/src/main/java/com/tangem/domain/cardReader/TLV.java @@ -1,5 +1,7 @@ package com.tangem.domain.cardReader; +import com.tangem.util.Util; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/app/src/main/java/com/tangem/domain/cardReader/TLVList.java b/app/src/main/java/com/tangem/domain/cardReader/TLVList.java index 3393a38756..fd320ac41a 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/TLVList.java +++ b/app/src/main/java/com/tangem/domain/cardReader/TLVList.java @@ -6,6 +6,8 @@ package com.tangem.domain.cardReader; import android.support.annotation.NonNull; +import com.tangem.util.Util; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; diff --git a/app/src/main/java/com/tangem/wallet/BTCUtils.java b/app/src/main/java/com/tangem/domain/wallet/BTCUtils.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/BTCUtils.java rename to app/src/main/java/com/tangem/domain/wallet/BTCUtils.java index 39f2ad8884..0d0114262f 100644 --- a/app/src/main/java/com/tangem/wallet/BTCUtils.java +++ b/app/src/main/java/com/tangem/domain/wallet/BTCUtils.java @@ -1,488 +1,488 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ - -import android.util.Log; - -import com.tangem.domain.cardReader.Util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Stack; - -@SuppressWarnings({"WeakerAccess", "TryWithIdenticalCatches", "unused"}) -public final class BTCUtils { - static final BigInteger LARGEST_PRIVATE_KEY = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16);//SECP256K1_N - public static final long MIN_FEE_PER_KB = 10000; - public static final long MAX_ALLOWED_FEE = FormatUtil.parseValue("0.1"); - public static final long MIN_PRIORITY_FOR_NO_FEE = 57600000; - public static final long MIN_MIN_OUTPUT_VALUE_FOR_NO_FEE = 10000000L; - public static final int MAX_TX_LEN_FOR_NO_FEE = 10000; - public static final float EXPECTED_BLOCKS_PER_DAY = 144.0f;//(expected confirmations per day) - - public static long calcMinimumFee(int txLen, Collection unspentOutputInfos, long minOutput) { - if (isZeroFeeAllowed(txLen, unspentOutputInfos, minOutput)) { - return 0; - } - return MIN_FEE_PER_KB * (1 + txLen / 1000); - } - - public static boolean isZeroFeeAllowed(int txLen, Collection unspentOutputInfos, long minOutput) { - if (txLen < MAX_TX_LEN_FOR_NO_FEE && minOutput > MIN_MIN_OUTPUT_VALUE_FOR_NO_FEE) { - long priority = 0; - for (UnspentOutputInfo output : unspentOutputInfos) { - if (output.confirmations > 0) { - priority += output.confirmations * output.value; - } - } - priority /= txLen; - if (priority > MIN_PRIORITY_FOR_NO_FEE) { - return true; - } - } - return false; - } - - public static int getMaximumTxSize(Collection unspentOutputInfos, int outputsCount, boolean compressedPublicKey) throws BitcoinException { - if (unspentOutputInfos == null || unspentOutputInfos.isEmpty()) { - throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "No information about tx inputs provided"); - } - int maxInputScriptLen = 73 + (compressedPublicKey ? 33 : 65); - return 9 + unspentOutputInfos.size() * (41 + maxInputScriptLen) + outputsCount * 33; - } - - public static String publicKeyToAddress(byte[] publicKey) { - return publicKeyToAddress(false, publicKey); - } - - public static String publicKeyToAddress(boolean testNet, byte[] publicKey) { - try { - byte[] hashedPublicKey = CryptoUtil.sha256ripemd160(publicKey); - byte[] addressBytes = new byte[1 + hashedPublicKey.length + 4]; - addressBytes[0] = (byte) (testNet ? 111 : 0); - System.arraycopy(hashedPublicKey, 0, addressBytes, 1, hashedPublicKey.length); - MessageDigest digestSha = MessageDigest.getInstance("SHA-256"); - digestSha.update(addressBytes, 0, addressBytes.length - 4); - byte[] check = digestSha.digest(digestSha.digest()); - System.arraycopy(check, 0, addressBytes, hashedPublicKey.length + 1, 4); - return Base58.encodeBase58(addressBytes); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - public static String toHex(byte[] bytes) { - if (bytes == null) { - return ""; - } - final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - char[] hexChars = new char[bytes.length * 2]; - int v; - for (int j = 0; j < bytes.length; j++) { - v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - - public static byte[] buildTXForSign(String myAddress, String outputAddress, String changeAddress, ArrayList unspentOutputs, int currentInputPos, long amount, long change) throws BitcoinException, IOException { - byte[] myScript = Transaction.Script.buildOutput(myAddress).bytes; - unspentOutputs.get(currentInputPos).scriptForBuild = myScript; - int inputPos = currentInputPos; - byte[] body = buildBodyTX(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); - - ByteArrayOutputStream os = new ByteArrayOutputStream(); - os.write(body); - os.write(new byte[]{0x01, 0x00, 0x00, 0x00}); - byte[] tx = os.toByteArray(); - return tx; - } - - public static byte[] buildTXForSend(String outputAddress, String changeAddress, ArrayList unspentOutputs, long amount, long change) throws BitcoinException, IOException { - int inputPos = -1; - byte[] body = buildBodyTX(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - os.write(body); - byte[] tx = os.toByteArray(); - return tx; - } - - public static byte[] buildBodyTX(String outputAddress, String changeAddress, ArrayList unspentOutputs, int inputPos, long amount, long change) throws BitcoinException, IOException { - - //0200000000 - BitcoinOutputStream forSign = new BitcoinOutputStream(); - forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version - - //01 - byte inputCount = (byte)unspentOutputs.size(); - forSign.write(inputCount); // input count - //hex str hash prev btc - - for(int i = 0; i < inputCount; ++i) - { - UnspentOutputInfo outPut = unspentOutputs.get(i); - int outputIndex = outPut.outputIndex; - byte[] txHash = BTCUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Sha256Hash.hash(rawTxByte); - forSign.write(txHash); - forSign.writeInt32(outputIndex); //output index in prev tx - if(inputPos ==-1 || i == inputPos) - { - // hex str 1976a914....88ac - forSign.write((byte)outPut.scriptForBuild.length); - forSign.write(outPut.scriptForBuild); - } - else - { - forSign.write(0x00); - } - //ffffffff - forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence - } - - - //02 - byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount - forSign.write(outputCount); - - //8 bytes - - forSign.writeInt64(amount); //amount - byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out - //hex str 1976a914....88ac - forSign.write((byte)sendScript.length); - forSign.write(sendScript); - - if(change!=0){ - //8 bytes - forSign.writeInt64(change); // change - //hex str 1976a914....88ac - byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out - forSign.write((byte)chancheScript.length); - forSign.write(chancheScript); - - } - - //00000000 - forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); - - //forSign.write(new byte[]{0x01, 0x00, 0x00, 0x00}); - - byte[] rawData = forSign.toByteArray(); - - Log.e("Sign_TX_Body", BTCUtils.toHex(rawData)); - - return rawData; - } - - int calculateSize(int inputCount, int outputCount) - { - int size = 0; - size += 4; // header - size += 1; //inputCount - - //hex str hash prev btc - - for(int i = 0; i < inputCount; ++i) - { - size += 32; //prevtx - size += 4; //outputIndex; - size += 1; //scriptLength - // size+=script; - size += 4; //ffffffff - } - - size+=1; //outputCount - size+=8; //amount - size+=1; - // size+=script; - - if(outputCount > 1) - { - size+=8; - size+=1; - //scriptLen; - } - - size+=4; - return size; - } - - - public static byte[] buildBodyTX(String outputAddress, String changeAddress, int outputIndex, String prevID, long amount, long change, byte[] script) throws BitcoinException, IOException { - - //0200000000 - BitcoinOutputStream forSign = new BitcoinOutputStream(); - forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version - - //01 - byte inputCount = 1; - forSign.write(inputCount); // input count - //hex str hash prev btc - byte[] txHash = BTCUtils.reverse(Util.hexToBytes(prevID));//Sha256Hash.hash(rawTxByte); - forSign.write(txHash); //previos tx hash - - //00000000 - //byte indexOutput = outputIndex; - forSign.writeInt32(outputIndex/*indexOutput*/); //output index in prev tx - //forSign.write(0x00); - - // hex str 1976a914....88ac - forSign.write((byte)script.length); - forSign.write(script); - - //ffffffff - forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence - - //02 - byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount - forSign.write(outputCount); - - //8 bytes - - forSign.writeInt64(amount); //amount - byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out - //hex str 1976a914....88ac - forSign.write((byte)sendScript.length); - forSign.write(sendScript); - - if(change!=0){ - //8 bytes - forSign.writeInt64(change); // change - //hex str 1976a914....88ac - byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out - forSign.write((byte)chancheScript.length); - forSign.write(chancheScript); - - } - - //00000000 - forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); - - byte[] rawData = forSign.toByteArray(); - - //Log.e("Sign_TX_Body", BTCUtils.toHex(rawData)); - return rawData; - } - - public static ArrayList getPrevTX(String hex) throws BitcoinException { - byte[] rawTxByte = fromHex(hex); - Transaction baseTx = new Transaction(rawTxByte); - ArrayList prevHashes = new ArrayList(); - for(int i =0; i < baseTx.inputs.length; ++i) - { - Transaction.Input input = baseTx.inputs[i]; - prevHashes.add(input.outPoint.hash); - } - return prevHashes; - } - - public static boolean isInput(String myAddress, String hex) throws BitcoinException { - byte[] rawTxByte = fromHex(hex); - Transaction baseTx = new Transaction(rawTxByte); - byte[] myScript = Transaction.Script.buildOutput(myAddress).bytes; - for(int i =0; i < baseTx.inputs.length; ++i) - { - Transaction.Input input = baseTx.inputs[i]; - byte[] script = input.script.bytes; - - // find outputs - if (Arrays.equals(myScript, script)){ - return true; - } - } - return false; - } - public static ArrayList getOutputs(List rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException { - ArrayList unspentOutputs = new ArrayList<>(); - - for(Tangem_Card.UnspentTransaction current: rawTxList) - { - byte[] rawTxByte = BTCUtils.fromHex(current.Raw); - if (rawTxByte == null) - { - continue; - } - - Transaction baseTx = new Transaction(rawTxByte); - - if(baseTx.inputs.length == 0 || baseTx.outputs.length == 0) - throw new IllegalArgumentException("Unable to decode given transaction"); - - byte[] txHash = BTCUtils.reverse(CryptoUtil.doubleSha256(rawTxByte)); - String txHashForBuild = current.txID; - byte[] sign = null; - - for (int outputIndex = 0; outputIndex < baseTx.outputs.length; outputIndex++) { - Transaction.Output output = baseTx.outputs[outputIndex]; - - // find outputs - if (Arrays.equals(outputScriptWeAreAbleToSpend, output.script.bytes)) { - unspentOutputs.add(new UnspentOutputInfo(txHash, output.script, output.value, outputIndex, -1, txHashForBuild, sign)); - } - } - - } - - return unspentOutputs; - } - - public static byte[] fromHex(String s) { - if (s != null) { - try { - StringBuilder sb = new StringBuilder(s.length()); - for (int i = 0; i < s.length(); i++) { - char ch = s.charAt(i); - if (!Character.isWhitespace(ch)) { - sb.append(ch); - } - } - s = sb.toString(); - int len = s.length(); - byte[] data = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - int hi = (Character.digit(s.charAt(i), 16) << 4); - int low = Character.digit(s.charAt(i + 1), 16); - if (hi >= 256 || low < 0 || low >= 16) { - return null; - } - data[i / 2] = (byte) (hi | low); - } - return data; - } catch (Exception ignored) { - } - } - return null; - } - - public static byte[] reverse(byte[] bytes) { - byte[] result = new byte[bytes.length]; - for (int i = 0; i < bytes.length; i++) { - result[i] = bytes[bytes.length - i - 1]; - } - return result; - } - - public static byte[] reverseInPlace(byte[] bytes) { - int len = bytes.length / 2; - for (int i = 0; i < len; i++) { - byte t = bytes[i]; - bytes[i] = bytes[bytes.length - i - 1]; - bytes[bytes.length - i - 1] = t; - } - return bytes; - } - - public static int findSpendableOutput(Transaction tx, String forAddress, long minAmount) throws BitcoinException { - byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(forAddress).bytes; - int indexOfOutputToSpend = -1; - for (int indexOfOutput = 0; indexOfOutput < tx.outputs.length; indexOfOutput++) { - Transaction.Output output = tx.outputs[indexOfOutput]; - if (Arrays.equals(outputScriptWeAreAbleToSpend, output.script.bytes)) { - indexOfOutputToSpend = indexOfOutput; - break;//only one input is supported for now - } - } - if (indexOfOutputToSpend == -1) { - throw new BitcoinException(BitcoinException.ERR_NO_SPENDABLE_OUTPUTS_FOR_THE_ADDRESS, "No spendable standard outputs for " + forAddress + " have found", forAddress); - } - final long spendableOutputValue = tx.outputs[indexOfOutputToSpend].value; - if (spendableOutputValue < minAmount) { - throw new BitcoinException(BitcoinException.ERR_INSUFFICIENT_FUNDS, "Unspent amount is too small: " + spendableOutputValue, spendableOutputValue); - } - return indexOfOutputToSpend; - } - - public static void verify(Transaction.Script[] scripts, Transaction spendTx) throws Transaction.Script.ScriptInvalidException { - for (int i = 0; i < scripts.length; i++) { - Stack stack = new Stack<>(); - spendTx.inputs[i].script.run(stack);//load signature+public key - scripts[i].run(i, spendTx, stack); //verify that this transaction able to spend that output - if (Transaction.Script.verifyFails(stack)) { - throw new Transaction.Script.ScriptInvalidException("Signature is invalid"); - } - } - } - - public static class FeeChangeAndSelectedOutputs { - public final long amountForRecipient, change, fee; - public final ArrayList outputsToSpend; - - public FeeChangeAndSelectedOutputs(long fee, long change, long amountForRecipient, ArrayList outputsToSpend) { - this.fee = fee; - this.change = change; - this.amountForRecipient = amountForRecipient; - this.outputsToSpend = outputsToSpend; - } - } - - public static FeeChangeAndSelectedOutputs calcFeeChangeAndSelectOutputsToSpend(List unspentOutputs, long amountToSend, long extraFee, final boolean isPublicKeyCompressed) throws BitcoinException { - long fee = 0;//calculated below - long change = 0; - long valueOfUnspentOutputs; - ArrayList outputsToSpend = new ArrayList<>(); - if (amountToSend <= 0) { - //transfer all funds from these addresses to outputAddress - change = 0; - valueOfUnspentOutputs = 0; - for (UnspentOutputInfo outputInfo : unspentOutputs) { - outputsToSpend.add(outputInfo); - valueOfUnspentOutputs += outputInfo.value; - } - final int txLen = BTCUtils.getMaximumTxSize(unspentOutputs, 1, isPublicKeyCompressed); - fee = BTCUtils.calcMinimumFee(txLen, unspentOutputs, valueOfUnspentOutputs - MIN_FEE_PER_KB * (1 + txLen / 1000)); - amountToSend = valueOfUnspentOutputs - fee - extraFee; - } else { - valueOfUnspentOutputs = 0; - for (UnspentOutputInfo outputInfo : unspentOutputs) { - outputsToSpend.add(outputInfo); - valueOfUnspentOutputs += outputInfo.value; - long updatedFee = MIN_FEE_PER_KB; - for (int i = 0; i < 3; i++) { - fee = updatedFee; - change = valueOfUnspentOutputs - fee - extraFee - amountToSend; - final int txLen = BTCUtils.getMaximumTxSize(unspentOutputs, change > 0 ? 2 : 1, isPublicKeyCompressed); - updatedFee = BTCUtils.calcMinimumFee(txLen, unspentOutputs, change > 0 ? Math.min(amountToSend, change) : amountToSend); - if (updatedFee == fee) { - break; - } - } - fee = updatedFee; - if (valueOfUnspentOutputs >= amountToSend + fee + extraFee) { - break; - } - } - - } - if (amountToSend > valueOfUnspentOutputs - fee) { - throw new BitcoinException(BitcoinException.ERR_INSUFFICIENT_FUNDS, "Not enough funds", valueOfUnspentOutputs - fee); - } - if (outputsToSpend.isEmpty()) { - throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "No outputs to spend"); - } - if (fee + extraFee > MAX_ALLOWED_FEE) { - throw new BitcoinException(BitcoinException.ERR_FEE_IS_TOO_BIG, "Fee is too big", fee); - } - if (fee < 0 || extraFee < 0) { - throw new BitcoinException(BitcoinException.ERR_FEE_IS_LESS_THEN_ZERO, "Incorrect fee", fee); - } - if (change < 0) { - throw new BitcoinException(BitcoinException.ERR_CHANGE_IS_LESS_THEN_ZERO, "Incorrect change", change); - } - if (amountToSend < 0) { - throw new BitcoinException(BitcoinException.ERR_AMOUNT_TO_SEND_IS_LESS_THEN_ZERO, "Incorrect amount to send", amountToSend); - } - return new FeeChangeAndSelectedOutputs(fee + extraFee, change, amountToSend, outputsToSpend); - - } -} +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +import android.util.Log; + +import com.tangem.util.Util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Stack; + +@SuppressWarnings({"WeakerAccess", "TryWithIdenticalCatches", "unused"}) +public final class BTCUtils { + static final BigInteger LARGEST_PRIVATE_KEY = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16);//SECP256K1_N + public static final long MIN_FEE_PER_KB = 10000; + public static final long MAX_ALLOWED_FEE = FormatUtil.parseValue("0.1"); + public static final long MIN_PRIORITY_FOR_NO_FEE = 57600000; + public static final long MIN_MIN_OUTPUT_VALUE_FOR_NO_FEE = 10000000L; + public static final int MAX_TX_LEN_FOR_NO_FEE = 10000; + public static final float EXPECTED_BLOCKS_PER_DAY = 144.0f;//(expected confirmations per day) + + public static long calcMinimumFee(int txLen, Collection unspentOutputInfos, long minOutput) { + if (isZeroFeeAllowed(txLen, unspentOutputInfos, minOutput)) { + return 0; + } + return MIN_FEE_PER_KB * (1 + txLen / 1000); + } + + public static boolean isZeroFeeAllowed(int txLen, Collection unspentOutputInfos, long minOutput) { + if (txLen < MAX_TX_LEN_FOR_NO_FEE && minOutput > MIN_MIN_OUTPUT_VALUE_FOR_NO_FEE) { + long priority = 0; + for (UnspentOutputInfo output : unspentOutputInfos) { + if (output.confirmations > 0) { + priority += output.confirmations * output.value; + } + } + priority /= txLen; + if (priority > MIN_PRIORITY_FOR_NO_FEE) { + return true; + } + } + return false; + } + + public static int getMaximumTxSize(Collection unspentOutputInfos, int outputsCount, boolean compressedPublicKey) throws BitcoinException { + if (unspentOutputInfos == null || unspentOutputInfos.isEmpty()) { + throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "No information about tx inputs provided"); + } + int maxInputScriptLen = 73 + (compressedPublicKey ? 33 : 65); + return 9 + unspentOutputInfos.size() * (41 + maxInputScriptLen) + outputsCount * 33; + } + + public static String publicKeyToAddress(byte[] publicKey) { + return publicKeyToAddress(false, publicKey); + } + + public static String publicKeyToAddress(boolean testNet, byte[] publicKey) { + try { + byte[] hashedPublicKey = CryptoUtil.sha256ripemd160(publicKey); + byte[] addressBytes = new byte[1 + hashedPublicKey.length + 4]; + addressBytes[0] = (byte) (testNet ? 111 : 0); + System.arraycopy(hashedPublicKey, 0, addressBytes, 1, hashedPublicKey.length); + MessageDigest digestSha = MessageDigest.getInstance("SHA-256"); + digestSha.update(addressBytes, 0, addressBytes.length - 4); + byte[] check = digestSha.digest(digestSha.digest()); + System.arraycopy(check, 0, addressBytes, hashedPublicKey.length + 1, 4); + return Base58.encodeBase58(addressBytes); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static String toHex(byte[] bytes) { + if (bytes == null) { + return ""; + } + final char[] hexArray = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + char[] hexChars = new char[bytes.length * 2]; + int v; + for (int j = 0; j < bytes.length; j++) { + v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } + + + public static byte[] buildTXForSign(String myAddress, String outputAddress, String changeAddress, ArrayList unspentOutputs, int currentInputPos, long amount, long change) throws BitcoinException, IOException { + byte[] myScript = Transaction.Script.buildOutput(myAddress).bytes; + unspentOutputs.get(currentInputPos).scriptForBuild = myScript; + int inputPos = currentInputPos; + byte[] body = buildBodyTX(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write(body); + os.write(new byte[]{0x01, 0x00, 0x00, 0x00}); + byte[] tx = os.toByteArray(); + return tx; + } + + public static byte[] buildTXForSend(String outputAddress, String changeAddress, ArrayList unspentOutputs, long amount, long change) throws BitcoinException, IOException { + int inputPos = -1; + byte[] body = buildBodyTX(outputAddress, changeAddress, unspentOutputs, inputPos, amount, change); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write(body); + byte[] tx = os.toByteArray(); + return tx; + } + + public static byte[] buildBodyTX(String outputAddress, String changeAddress, ArrayList unspentOutputs, int inputPos, long amount, long change) throws BitcoinException, IOException { + + //0200000000 + BitcoinOutputStream forSign = new BitcoinOutputStream(); + forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version + + //01 + byte inputCount = (byte)unspentOutputs.size(); + forSign.write(inputCount); // input count + //hex str hash prev btc + + for(int i = 0; i < inputCount; ++i) + { + UnspentOutputInfo outPut = unspentOutputs.get(i); + int outputIndex = outPut.outputIndex; + byte[] txHash = BTCUtils.reverse(Util.hexToBytes(outPut.txHashForBuild));//Sha256Hash.hash(rawTxByte); + forSign.write(txHash); + forSign.writeInt32(outputIndex); //output index in prev tx + if(inputPos ==-1 || i == inputPos) + { + // hex str 1976a914....88ac + forSign.write((byte)outPut.scriptForBuild.length); + forSign.write(outPut.scriptForBuild); + } + else + { + forSign.write(0x00); + } + //ffffffff + forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence + } + + + //02 + byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount + forSign.write(outputCount); + + //8 bytes + + forSign.writeInt64(amount); //amount + byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out + //hex str 1976a914....88ac + forSign.write((byte)sendScript.length); + forSign.write(sendScript); + + if(change!=0){ + //8 bytes + forSign.writeInt64(change); // change + //hex str 1976a914....88ac + byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out + forSign.write((byte)chancheScript.length); + forSign.write(chancheScript); + + } + + //00000000 + forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); + + //forSign.write(new byte[]{0x01, 0x00, 0x00, 0x00}); + + byte[] rawData = forSign.toByteArray(); + + Log.e("Sign_TX_Body", BTCUtils.toHex(rawData)); + + return rawData; + } + + int calculateSize(int inputCount, int outputCount) + { + int size = 0; + size += 4; // header + size += 1; //inputCount + + //hex str hash prev btc + + for(int i = 0; i < inputCount; ++i) + { + size += 32; //prevtx + size += 4; //outputIndex; + size += 1; //scriptLength + // size+=script; + size += 4; //ffffffff + } + + size+=1; //outputCount + size+=8; //amount + size+=1; + // size+=script; + + if(outputCount > 1) + { + size+=8; + size+=1; + //scriptLen; + } + + size+=4; + return size; + } + + + public static byte[] buildBodyTX(String outputAddress, String changeAddress, int outputIndex, String prevID, long amount, long change, byte[] script) throws BitcoinException, IOException { + + //0200000000 + BitcoinOutputStream forSign = new BitcoinOutputStream(); + forSign.writeInt32(0x01);//write(new byte[]{0x02, 0x00, 0x00, 0x00}); // version + + //01 + byte inputCount = 1; + forSign.write(inputCount); // input count + //hex str hash prev btc + byte[] txHash = BTCUtils.reverse(Util.hexToBytes(prevID));//Sha256Hash.hash(rawTxByte); + forSign.write(txHash); //previos tx hash + + //00000000 + //byte indexOutput = outputIndex; + forSign.writeInt32(outputIndex/*indexOutput*/); //output index in prev tx + //forSign.write(0x00); + + // hex str 1976a914....88ac + forSign.write((byte)script.length); + forSign.write(script); + + //ffffffff + forSign.write(new byte[]{(byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff}); // sequence + + //02 + byte outputCount = (byte)((change==0) ? 1 : 2); // outputCount + forSign.write(outputCount); + + //8 bytes + + forSign.writeInt64(amount); //amount + byte[] sendScript = Transaction.Script.buildOutput(outputAddress).bytes; // build out + //hex str 1976a914....88ac + forSign.write((byte)sendScript.length); + forSign.write(sendScript); + + if(change!=0){ + //8 bytes + forSign.writeInt64(change); // change + //hex str 1976a914....88ac + byte[] chancheScript = Transaction.Script.buildOutput(changeAddress).bytes; //build out + forSign.write((byte)chancheScript.length); + forSign.write(chancheScript); + + } + + //00000000 + forSign.write(new byte[]{0x00, 0x00, 0x00, 0x00}); + + byte[] rawData = forSign.toByteArray(); + + //Log.e("Sign_TX_Body", BTCUtils.toHex(rawData)); + return rawData; + } + + public static ArrayList getPrevTX(String hex) throws BitcoinException { + byte[] rawTxByte = fromHex(hex); + Transaction baseTx = new Transaction(rawTxByte); + ArrayList prevHashes = new ArrayList(); + for(int i =0; i < baseTx.inputs.length; ++i) + { + Transaction.Input input = baseTx.inputs[i]; + prevHashes.add(input.outPoint.hash); + } + return prevHashes; + } + + public static boolean isInput(String myAddress, String hex) throws BitcoinException { + byte[] rawTxByte = fromHex(hex); + Transaction baseTx = new Transaction(rawTxByte); + byte[] myScript = Transaction.Script.buildOutput(myAddress).bytes; + for(int i =0; i < baseTx.inputs.length; ++i) + { + Transaction.Input input = baseTx.inputs[i]; + byte[] script = input.script.bytes; + + // find outputs + if (Arrays.equals(myScript, script)){ + return true; + } + } + return false; + } + public static ArrayList getOutputs(List rawTxList, byte[] outputScriptWeAreAbleToSpend) throws BitcoinException { + ArrayList unspentOutputs = new ArrayList<>(); + + for(TangemCard.UnspentTransaction current: rawTxList) + { + byte[] rawTxByte = BTCUtils.fromHex(current.Raw); + if (rawTxByte == null) + { + continue; + } + + Transaction baseTx = new Transaction(rawTxByte); + + if(baseTx.inputs.length == 0 || baseTx.outputs.length == 0) + throw new IllegalArgumentException("Unable to decode given transaction"); + + byte[] txHash = BTCUtils.reverse(CryptoUtil.doubleSha256(rawTxByte)); + String txHashForBuild = current.txID; + byte[] sign = null; + + for (int outputIndex = 0; outputIndex < baseTx.outputs.length; outputIndex++) { + Transaction.Output output = baseTx.outputs[outputIndex]; + + // find outputs + if (Arrays.equals(outputScriptWeAreAbleToSpend, output.script.bytes)) { + unspentOutputs.add(new UnspentOutputInfo(txHash, output.script, output.value, outputIndex, -1, txHashForBuild, sign)); + } + } + + } + + return unspentOutputs; + } + + public static byte[] fromHex(String s) { + if (s != null) { + try { + StringBuilder sb = new StringBuilder(s.length()); + for (int i = 0; i < s.length(); i++) { + char ch = s.charAt(i); + if (!Character.isWhitespace(ch)) { + sb.append(ch); + } + } + s = sb.toString(); + int len = s.length(); + byte[] data = new byte[len / 2]; + for (int i = 0; i < len; i += 2) { + int hi = (Character.digit(s.charAt(i), 16) << 4); + int low = Character.digit(s.charAt(i + 1), 16); + if (hi >= 256 || low < 0 || low >= 16) { + return null; + } + data[i / 2] = (byte) (hi | low); + } + return data; + } catch (Exception ignored) { + } + } + return null; + } + + public static byte[] reverse(byte[] bytes) { + byte[] result = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) { + result[i] = bytes[bytes.length - i - 1]; + } + return result; + } + + public static byte[] reverseInPlace(byte[] bytes) { + int len = bytes.length / 2; + for (int i = 0; i < len; i++) { + byte t = bytes[i]; + bytes[i] = bytes[bytes.length - i - 1]; + bytes[bytes.length - i - 1] = t; + } + return bytes; + } + + public static int findSpendableOutput(Transaction tx, String forAddress, long minAmount) throws BitcoinException { + byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(forAddress).bytes; + int indexOfOutputToSpend = -1; + for (int indexOfOutput = 0; indexOfOutput < tx.outputs.length; indexOfOutput++) { + Transaction.Output output = tx.outputs[indexOfOutput]; + if (Arrays.equals(outputScriptWeAreAbleToSpend, output.script.bytes)) { + indexOfOutputToSpend = indexOfOutput; + break;//only one input is supported for now + } + } + if (indexOfOutputToSpend == -1) { + throw new BitcoinException(BitcoinException.ERR_NO_SPENDABLE_OUTPUTS_FOR_THE_ADDRESS, "No spendable standard outputs for " + forAddress + " have found", forAddress); + } + final long spendableOutputValue = tx.outputs[indexOfOutputToSpend].value; + if (spendableOutputValue < minAmount) { + throw new BitcoinException(BitcoinException.ERR_INSUFFICIENT_FUNDS, "Unspent amount is too small: " + spendableOutputValue, spendableOutputValue); + } + return indexOfOutputToSpend; + } + + public static void verify(Transaction.Script[] scripts, Transaction spendTx) throws Transaction.Script.ScriptInvalidException { + for (int i = 0; i < scripts.length; i++) { + Stack stack = new Stack<>(); + spendTx.inputs[i].script.run(stack);//load signature+public key + scripts[i].run(i, spendTx, stack); //verify that this transaction able to spend that output + if (Transaction.Script.verifyFails(stack)) { + throw new Transaction.Script.ScriptInvalidException("Signature is invalid"); + } + } + } + + public static class FeeChangeAndSelectedOutputs { + public final long amountForRecipient, change, fee; + public final ArrayList outputsToSpend; + + public FeeChangeAndSelectedOutputs(long fee, long change, long amountForRecipient, ArrayList outputsToSpend) { + this.fee = fee; + this.change = change; + this.amountForRecipient = amountForRecipient; + this.outputsToSpend = outputsToSpend; + } + } + + public static FeeChangeAndSelectedOutputs calcFeeChangeAndSelectOutputsToSpend(List unspentOutputs, long amountToSend, long extraFee, final boolean isPublicKeyCompressed) throws BitcoinException { + long fee = 0;//calculated below + long change = 0; + long valueOfUnspentOutputs; + ArrayList outputsToSpend = new ArrayList<>(); + if (amountToSend <= 0) { + //transfer all funds from these addresses to outputAddress + change = 0; + valueOfUnspentOutputs = 0; + for (UnspentOutputInfo outputInfo : unspentOutputs) { + outputsToSpend.add(outputInfo); + valueOfUnspentOutputs += outputInfo.value; + } + final int txLen = BTCUtils.getMaximumTxSize(unspentOutputs, 1, isPublicKeyCompressed); + fee = BTCUtils.calcMinimumFee(txLen, unspentOutputs, valueOfUnspentOutputs - MIN_FEE_PER_KB * (1 + txLen / 1000)); + amountToSend = valueOfUnspentOutputs - fee - extraFee; + } else { + valueOfUnspentOutputs = 0; + for (UnspentOutputInfo outputInfo : unspentOutputs) { + outputsToSpend.add(outputInfo); + valueOfUnspentOutputs += outputInfo.value; + long updatedFee = MIN_FEE_PER_KB; + for (int i = 0; i < 3; i++) { + fee = updatedFee; + change = valueOfUnspentOutputs - fee - extraFee - amountToSend; + final int txLen = BTCUtils.getMaximumTxSize(unspentOutputs, change > 0 ? 2 : 1, isPublicKeyCompressed); + updatedFee = BTCUtils.calcMinimumFee(txLen, unspentOutputs, change > 0 ? Math.min(amountToSend, change) : amountToSend); + if (updatedFee == fee) { + break; + } + } + fee = updatedFee; + if (valueOfUnspentOutputs >= amountToSend + fee + extraFee) { + break; + } + } + + } + if (amountToSend > valueOfUnspentOutputs - fee) { + throw new BitcoinException(BitcoinException.ERR_INSUFFICIENT_FUNDS, "Not enough funds", valueOfUnspentOutputs - fee); + } + if (outputsToSpend.isEmpty()) { + throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "No outputs to spend"); + } + if (fee + extraFee > MAX_ALLOWED_FEE) { + throw new BitcoinException(BitcoinException.ERR_FEE_IS_TOO_BIG, "Fee is too big", fee); + } + if (fee < 0 || extraFee < 0) { + throw new BitcoinException(BitcoinException.ERR_FEE_IS_LESS_THEN_ZERO, "Incorrect fee", fee); + } + if (change < 0) { + throw new BitcoinException(BitcoinException.ERR_CHANGE_IS_LESS_THEN_ZERO, "Incorrect change", change); + } + if (amountToSend < 0) { + throw new BitcoinException(BitcoinException.ERR_AMOUNT_TO_SEND_IS_LESS_THEN_ZERO, "Incorrect amount to send", amountToSend); + } + return new FeeChangeAndSelectedOutputs(fee + extraFee, change, amountToSend, outputsToSpend); + + } +} diff --git a/app/src/main/java/com/tangem/wallet/Base58.java b/app/src/main/java/com/tangem/domain/wallet/Base58.java similarity index 97% rename from app/src/main/java/com/tangem/wallet/Base58.java rename to app/src/main/java/com/tangem/domain/wallet/Base58.java index 1bb1bef3df..1cfeb7c019 100644 --- a/app/src/main/java/com/tangem/wallet/Base58.java +++ b/app/src/main/java/com/tangem/domain/wallet/Base58.java @@ -1,115 +1,115 @@ -package com.tangem.wallet; - -import java.math.BigInteger; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class Base58 { - private static final char[] BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); - - private static final int BASE58_CHUNK_DIGITS = 10;//how many base 58 digits fits in long - private static final BigInteger BASE58_CHUNK_MOD = BigInteger.valueOf(0x5fa8624c7fba400L); //58^BASE58_CHUNK_DIGITS - private static final byte[] BASE58_VALUES = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, - -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, - -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, - 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - - public static byte[] decodeBase58(String input) { - if (input == null) { - return null; - } - input = input.trim(); - if (input.length() == 0) { - return new byte[0]; - } - BigInteger resultNum = BigInteger.ZERO; - int nLeadingZeros = 0; - while (nLeadingZeros < input.length() && input.charAt(nLeadingZeros) == BASE58[0]) { - nLeadingZeros++; - } - long acc = 0; - int nDigits = 0; - int p = nLeadingZeros; - while (p < input.length()) { - int v = BASE58_VALUES[input.charAt(p) & 0xff]; - if (v >= 0) { - acc *= 58; - acc += v; - nDigits++; - if (nDigits == BASE58_CHUNK_DIGITS) { - resultNum = resultNum.multiply(BASE58_CHUNK_MOD).add(BigInteger.valueOf(acc)); - acc = 0; - nDigits = 0; - } - p++; - } else { - break; - } - } - if (nDigits > 0) { - long mul = 58; - while (--nDigits > 0) { - mul *= 58; - } - resultNum = resultNum.multiply(BigInteger.valueOf(mul)).add(BigInteger.valueOf(acc)); - } - final int BASE58_SPACE = -2; - while (p < input.length() && BASE58_VALUES[input.charAt(p) & 0xff] == BASE58_SPACE) { - p++; - } - if (p < input.length()) { - return null; - } - byte[] plainNumber = resultNum.toByteArray(); - int plainNumbersOffs = plainNumber[0] == 0 ? 1 : 0; - byte[] result = new byte[nLeadingZeros + plainNumber.length - plainNumbersOffs]; - System.arraycopy(plainNumber, plainNumbersOffs, result, nLeadingZeros, plainNumber.length - plainNumbersOffs); - return result; - } - - public static String encodeBase58(byte[] input) { - if (input == null) { - return null; - } - StringBuilder str = new StringBuilder((input.length * 350) / 256 + 1); - BigInteger bn = new BigInteger(1, input); - long rem; - while (true) { - BigInteger[] divideAndRemainder = bn.divideAndRemainder(BASE58_CHUNK_MOD); - bn = divideAndRemainder[0]; - rem = divideAndRemainder[1].longValue(); - if (bn.compareTo(BigInteger.ZERO) == 0) { - break; - } - for (int i = 0; i < BASE58_CHUNK_DIGITS; i++) { - str.append(BASE58[(int) (rem % 58)]); - rem /= 58; - } - } - while (rem != 0) { - str.append(BASE58[(int) (rem % 58)]); - rem /= 58; - } - str.reverse(); - int nLeadingZeros = 0; - while (nLeadingZeros < input.length && input[nLeadingZeros] == 0) { - str.insert(0, BASE58[0]); - nLeadingZeros++; - } - return str.toString(); - } +package com.tangem.domain.wallet; + +import java.math.BigInteger; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class Base58 { + private static final char[] BASE58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray(); + + private static final int BASE58_CHUNK_DIGITS = 10;//how many base 58 digits fits in long + private static final BigInteger BASE58_CHUNK_MOD = BigInteger.valueOf(0x5fa8624c7fba400L); //58^BASE58_CHUNK_DIGITS + private static final byte[] BASE58_VALUES = new byte[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -2, -2, -2, -2, -2, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, + -1, 9, 10, 11, 12, 13, 14, 15, 16, -1, 17, 18, 19, 20, 21, -1, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, + -1, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; + + public static byte[] decodeBase58(String input) { + if (input == null) { + return null; + } + input = input.trim(); + if (input.length() == 0) { + return new byte[0]; + } + BigInteger resultNum = BigInteger.ZERO; + int nLeadingZeros = 0; + while (nLeadingZeros < input.length() && input.charAt(nLeadingZeros) == BASE58[0]) { + nLeadingZeros++; + } + long acc = 0; + int nDigits = 0; + int p = nLeadingZeros; + while (p < input.length()) { + int v = BASE58_VALUES[input.charAt(p) & 0xff]; + if (v >= 0) { + acc *= 58; + acc += v; + nDigits++; + if (nDigits == BASE58_CHUNK_DIGITS) { + resultNum = resultNum.multiply(BASE58_CHUNK_MOD).add(BigInteger.valueOf(acc)); + acc = 0; + nDigits = 0; + } + p++; + } else { + break; + } + } + if (nDigits > 0) { + long mul = 58; + while (--nDigits > 0) { + mul *= 58; + } + resultNum = resultNum.multiply(BigInteger.valueOf(mul)).add(BigInteger.valueOf(acc)); + } + final int BASE58_SPACE = -2; + while (p < input.length() && BASE58_VALUES[input.charAt(p) & 0xff] == BASE58_SPACE) { + p++; + } + if (p < input.length()) { + return null; + } + byte[] plainNumber = resultNum.toByteArray(); + int plainNumbersOffs = plainNumber[0] == 0 ? 1 : 0; + byte[] result = new byte[nLeadingZeros + plainNumber.length - plainNumbersOffs]; + System.arraycopy(plainNumber, plainNumbersOffs, result, nLeadingZeros, plainNumber.length - plainNumbersOffs); + return result; + } + + public static String encodeBase58(byte[] input) { + if (input == null) { + return null; + } + StringBuilder str = new StringBuilder((input.length * 350) / 256 + 1); + BigInteger bn = new BigInteger(1, input); + long rem; + while (true) { + BigInteger[] divideAndRemainder = bn.divideAndRemainder(BASE58_CHUNK_MOD); + bn = divideAndRemainder[0]; + rem = divideAndRemainder[1].longValue(); + if (bn.compareTo(BigInteger.ZERO) == 0) { + break; + } + for (int i = 0; i < BASE58_CHUNK_DIGITS; i++) { + str.append(BASE58[(int) (rem % 58)]); + rem /= 58; + } + } + while (rem != 0) { + str.append(BASE58[(int) (rem % 58)]); + rem /= 58; + } + str.reverse(); + int nLeadingZeros = 0; + while (nLeadingZeros < input.length && input[nLeadingZeros] == 0) { + str.insert(0, BASE58[0]); + nLeadingZeros++; + } + return str.toString(); + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/BitcoinException.java b/app/src/main/java/com/tangem/domain/wallet/BitcoinException.java similarity index 95% rename from app/src/main/java/com/tangem/wallet/BitcoinException.java rename to app/src/main/java/com/tangem/domain/wallet/BitcoinException.java index 0d3f52c547..3e5ee174ae 100644 --- a/app/src/main/java/com/tangem/wallet/BitcoinException.java +++ b/app/src/main/java/com/tangem/domain/wallet/BitcoinException.java @@ -1,35 +1,35 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ - -@SuppressWarnings("WeakerAccess") -public final class BitcoinException extends Exception { - public static final int ERR_NO_SPENDABLE_OUTPUTS_FOR_THE_ADDRESS = 0; - public static final int ERR_INSUFFICIENT_FUNDS = 1; - public static final int ERR_WRONG_TYPE = 2; - public static final int ERR_BAD_FORMAT = 3; - public static final int ERR_INCORRECT_PASSWORD = 4; - public static final int ERR_MEANINGLESS_OPERATION = 5; - public static final int ERR_NO_INPUT = 6; - public static final int ERR_FEE_IS_TOO_BIG = 7; - public static final int ERR_FEE_IS_LESS_THEN_ZERO = 8; - public static final int ERR_CHANGE_IS_LESS_THEN_ZERO = 9; - public static final int ERR_AMOUNT_TO_SEND_IS_LESS_THEN_ZERO = 10; - public static final int ERR_UNSUPPORTED = 11; - - public final int errorCode; - @SuppressWarnings({"WeakerAccess", "unused"}) - public final Object extraInformation; - - public BitcoinException(int errorCode, String detailMessage, Object extraInformation) { - super(detailMessage); - this.errorCode = errorCode; - this.extraInformation = extraInformation; - } - - public BitcoinException(int errorCode, String detailMessage) { - this(errorCode, detailMessage, null); - } -} +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +@SuppressWarnings("WeakerAccess") +public final class BitcoinException extends Exception { + public static final int ERR_NO_SPENDABLE_OUTPUTS_FOR_THE_ADDRESS = 0; + public static final int ERR_INSUFFICIENT_FUNDS = 1; + public static final int ERR_WRONG_TYPE = 2; + public static final int ERR_BAD_FORMAT = 3; + public static final int ERR_INCORRECT_PASSWORD = 4; + public static final int ERR_MEANINGLESS_OPERATION = 5; + public static final int ERR_NO_INPUT = 6; + public static final int ERR_FEE_IS_TOO_BIG = 7; + public static final int ERR_FEE_IS_LESS_THEN_ZERO = 8; + public static final int ERR_CHANGE_IS_LESS_THEN_ZERO = 9; + public static final int ERR_AMOUNT_TO_SEND_IS_LESS_THEN_ZERO = 10; + public static final int ERR_UNSUPPORTED = 11; + + public final int errorCode; + @SuppressWarnings({"WeakerAccess", "unused"}) + public final Object extraInformation; + + public BitcoinException(int errorCode, String detailMessage, Object extraInformation) { + super(detailMessage); + this.errorCode = errorCode; + this.extraInformation = extraInformation; + } + + public BitcoinException(int errorCode, String detailMessage) { + this(errorCode, detailMessage, null); + } +} diff --git a/app/src/main/java/com/tangem/wallet/BitcoinInputStream.java b/app/src/main/java/com/tangem/domain/wallet/BitcoinInputStream.java similarity index 91% rename from app/src/main/java/com/tangem/wallet/BitcoinInputStream.java rename to app/src/main/java/com/tangem/domain/wallet/BitcoinInputStream.java index 4c66f81044..4a71269ac7 100644 --- a/app/src/main/java/com/tangem/wallet/BitcoinInputStream.java +++ b/app/src/main/java/com/tangem/domain/wallet/BitcoinInputStream.java @@ -1,69 +1,69 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ - -import java.io.ByteArrayInputStream; -import java.io.EOFException; -import java.io.IOException; - -@SuppressWarnings("WeakerAccess") -public class BitcoinInputStream extends ByteArrayInputStream { - public BitcoinInputStream(byte[] buf) { - super(buf); - } - - @SuppressWarnings("unused") - public BitcoinInputStream(byte[] buf, int offset, int length) { - super(buf, offset, length); - } - - public int readInt16() throws EOFException { - return (readByte() & 0xff) | ((readByte() & 0xff) << 8); - } - - public int readInt32() throws EOFException { - return (readByte() & 0xff) | ((readByte() & 0xff) << 8) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 24); - } - - public long readInt64() throws EOFException { - return (readInt32() & 0xFFFFFFFFL )| ((readInt32() & 0xFFFFFFFFL) << 32); - } - - public int readByte() throws EOFException { - int readedByte = super.read(); - if (readedByte == -1) { - throw new EOFException(); - } - return readedByte; - } - - public long readVarInt() throws EOFException { - int readedByte = readByte(); - if (readedByte < 0xfd) { - return readedByte; - } else if (readedByte == 0xfd) { - return readInt16(); - } else if (readedByte == 0xfe) { - return readInt32(); - } else { - return readInt64(); - } - } - - public byte[] readChars(final int count) throws IOException { - byte[] buf = new byte[count]; - int off = 0; - while (off != count) { - int bytesReadCurr = read(buf, off, count - off); - if (bytesReadCurr == -1) { - throw new EOFException(); - } else { - off += bytesReadCurr; - } - } - return buf; - } - -} +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +import java.io.ByteArrayInputStream; +import java.io.EOFException; +import java.io.IOException; + +@SuppressWarnings("WeakerAccess") +public class BitcoinInputStream extends ByteArrayInputStream { + public BitcoinInputStream(byte[] buf) { + super(buf); + } + + @SuppressWarnings("unused") + public BitcoinInputStream(byte[] buf, int offset, int length) { + super(buf, offset, length); + } + + public int readInt16() throws EOFException { + return (readByte() & 0xff) | ((readByte() & 0xff) << 8); + } + + public int readInt32() throws EOFException { + return (readByte() & 0xff) | ((readByte() & 0xff) << 8) | ((readByte() & 0xff) << 16) | ((readByte() & 0xff) << 24); + } + + public long readInt64() throws EOFException { + return (readInt32() & 0xFFFFFFFFL) | ((readInt32() & 0xFFFFFFFFL) << 32); + } + + public int readByte() throws EOFException { + int readedByte = super.read(); + if (readedByte == -1) { + throw new EOFException(); + } + return readedByte; + } + + public long readVarInt() throws EOFException { + int readedByte = readByte(); + if (readedByte < 0xfd) { + return readedByte; + } else if (readedByte == 0xfd) { + return readInt16(); + } else if (readedByte == 0xfe) { + return readInt32(); + } else { + return readInt64(); + } + } + + public byte[] readChars(final int count) throws IOException { + byte[] buf = new byte[count]; + int off = 0; + while (off != count) { + int bytesReadCurr = read(buf, off, count - off); + if (bytesReadCurr == -1) { + throw new EOFException(); + } else { + off += bytesReadCurr; + } + } + return buf; + } + +} diff --git a/app/src/main/java/com/tangem/wallet/BitcoinOutputStream.java b/app/src/main/java/com/tangem/domain/wallet/BitcoinOutputStream.java similarity index 93% rename from app/src/main/java/com/tangem/wallet/BitcoinOutputStream.java rename to app/src/main/java/com/tangem/domain/wallet/BitcoinOutputStream.java index baa5985b59..5f5c283ab1 100644 --- a/app/src/main/java/com/tangem/wallet/BitcoinOutputStream.java +++ b/app/src/main/java/com/tangem/domain/wallet/BitcoinOutputStream.java @@ -1,42 +1,43 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ -import java.io.ByteArrayOutputStream; - -@SuppressWarnings("WeakerAccess") -public final class BitcoinOutputStream extends ByteArrayOutputStream { - - public void writeInt16(int value) { - write(value & 0xff); - write((value >> 8) & 0xff); - } - - public void writeInt32(int value) { - write(value & 0xff); - write((value >> 8) & 0xff); - write((value >> 16) & 0xff); - write((value >>> 24) & 0xff); - } - - public void writeInt64(long value) { - writeInt32((int) (value & 0xFFFFFFFFL)); - writeInt32((int) ((value >>> 32) & 0xFFFFFFFFL)); - } - - public void writeVarInt(long value) { - if (value < 0xfd) { - write((int) (value & 0xff)); - } else if (value < 0xffff) { - write(0xfd); - writeInt16((int) value); - } else if (value < 0xffffffffL) { - write(0xfe); - writeInt32((int) value); - } else { - write(0xff); - writeInt64(value); - } - } +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +import java.io.ByteArrayOutputStream; + +@SuppressWarnings("WeakerAccess") +public final class BitcoinOutputStream extends ByteArrayOutputStream { + + public void writeInt16(int value) { + write(value & 0xff); + write((value >> 8) & 0xff); + } + + public void writeInt32(int value) { + write(value & 0xff); + write((value >> 8) & 0xff); + write((value >> 16) & 0xff); + write((value >>> 24) & 0xff); + } + + public void writeInt64(long value) { + writeInt32((int) (value & 0xFFFFFFFFL)); + writeInt32((int) ((value >>> 32) & 0xFFFFFFFFL)); + } + + public void writeVarInt(long value) { + if (value < 0xfd) { + write((int) (value & 0xff)); + } else if (value < 0xffff) { + write(0xfd); + writeInt16((int) value); + } else if (value < 0xffffffffL) { + write(0xfe); + writeInt32((int) value); + } else { + write(0xff); + writeInt64(value); + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/Blockchain.java b/app/src/main/java/com/tangem/domain/wallet/Blockchain.java similarity index 91% rename from app/src/main/java/com/tangem/wallet/Blockchain.java rename to app/src/main/java/com/tangem/domain/wallet/Blockchain.java index b92f1339c0..8982aaa044 100644 --- a/app/src/main/java/com/tangem/wallet/Blockchain.java +++ b/app/src/main/java/com/tangem/domain/wallet/Blockchain.java @@ -1,86 +1,87 @@ -package com.tangem.wallet; - -import com.google.common.base.Strings; - -/** - * Created by dvol on 06.08.2017. - */ -public enum Blockchain { - Unknown("", "", 1.0, R.drawable.ic_logo_small, ""), - Bitcoin("BTC", "BTC", 100000000.0, R.drawable.bitcoins, "Bitcoin"), - BitcoinTestNet("BTC/test", "BTC", 100000000.0, R.drawable.bitcoins_testnet, "Bitcoin Testnet"), - Ethereum("ETH", "ETH", 1.0, R.drawable.ethereum, "Ethereum"), - EthereumTestNet("ETH/test", "ETH", 1.0, R.drawable.ethereum_testnet, "Ethereum Testnet"), - Token("ETH\\XTZ", "BAT", 1.0, R.drawable.bat_token, "Ethereum"), - BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.bitcoin_cash, "Bitcoin Cash"), - BitcoinCashTestNet("BCH/test", "BTC", 100000000.0, R.drawable.bitcoin_cash, "Bitcoin Cash Testnet"); - - - Blockchain(String ID, String Currency, double Multiplier, int ImageResource, String officialName) { - mID = ID; - mCurrency = Currency; - mMultiplier = Multiplier; - mImageResource = ImageResource; - mOfficialName = officialName; - } - - private String mID, mOfficialName; - private double mMultiplier; - private String mCurrency; - private int mImageResource; - - public String getID() { - return mID; - } - - public String getOfficialName() { - return mOfficialName; - } - - public double getMultiplier() { - return mMultiplier; - } - - public String getCurrency() { - return mCurrency; - } - - public static Blockchain fromId(String id) { - for (Blockchain blockchain : values()) { - if (blockchain.getID().equals(id)) return blockchain; - } - return null; - } - - public static Blockchain fromCurrency(String currency) { - for (Blockchain blockchain : values()) { - if (blockchain.getCurrency() == currency) return blockchain; - } - return null; - } - - public static String[] getCurrencies() { - String[] result = new String[values().length - 1]; - for (int i = 0; i < result.length - 1; i++) { - result[i] = values()[i + 1].getCurrency(); - } - return result; - } - - public int getImageResource() { - return mImageResource; - } - - public int getImageResource(android.content.Context context, String name) { - if(Strings.isNullOrEmpty(name)) - return getImageResource(); - - name = name.toLowerCase(); - - int resourceId = context.getResources().getIdentifier(name+"_token", "drawable", context.getPackageName()); - - if(resourceId <= 0) - return R.drawable.ethereum; - return resourceId; - } -} +package com.tangem.domain.wallet; + +import com.google.common.base.Strings; +import com.tangem.wallet.R; + +/** + * Created by dvol on 06.08.2017. + */ +public enum Blockchain { + Unknown("", "", 1.0, R.drawable.ic_logo_small, ""), + Bitcoin("BTC", "BTC", 100000000.0, R.drawable.bitcoins, "Bitcoin"), + BitcoinTestNet("BTC/test", "BTC", 100000000.0, R.drawable.bitcoins_testnet, "Bitcoin Testnet"), + Ethereum("ETH", "ETH", 1.0, R.drawable.ethereum, "Ethereum"), + EthereumTestNet("ETH/test", "ETH", 1.0, R.drawable.ethereum_testnet, "Ethereum Testnet"), + Token("ETH\\XTZ", "BAT", 1.0, R.drawable.bat_token, "Ethereum"), + BitcoinCash("BCH", "BCH", 100000000.0, R.drawable.bitcoin_cash, "Bitcoin Cash"), + BitcoinCashTestNet("BCH/test", "BTC", 100000000.0, R.drawable.bitcoin_cash, "Bitcoin Cash Testnet"); + + + Blockchain(String ID, String Currency, double Multiplier, int ImageResource, String officialName) { + mID = ID; + mCurrency = Currency; + mMultiplier = Multiplier; + mImageResource = ImageResource; + mOfficialName = officialName; + } + + private String mID, mOfficialName; + private double mMultiplier; + private String mCurrency; + private int mImageResource; + + public String getID() { + return mID; + } + + public String getOfficialName() { + return mOfficialName; + } + + public double getMultiplier() { + return mMultiplier; + } + + public String getCurrency() { + return mCurrency; + } + + public static Blockchain fromId(String id) { + for (Blockchain blockchain : values()) { + if (blockchain.getID().equals(id)) return blockchain; + } + return null; + } + + public static Blockchain fromCurrency(String currency) { + for (Blockchain blockchain : values()) { + if (blockchain.getCurrency() == currency) return blockchain; + } + return null; + } + + public static String[] getCurrencies() { + String[] result = new String[values().length - 1]; + for (int i = 0; i < result.length - 1; i++) { + result[i] = values()[i + 1].getCurrency(); + } + return result; + } + + public int getImageResource() { + return mImageResource; + } + + public int getImageResource(android.content.Context context, String name) { + if (Strings.isNullOrEmpty(name)) + return getImageResource(); + + name = name.toLowerCase(); + + int resourceId = context.getResources().getIdentifier(name + "_token", "drawable", context.getPackageName()); + + if (resourceId <= 0) + return R.drawable.ethereum; + return resourceId; + } +} diff --git a/app/src/main/java/com/tangem/wallet/BtcCashEngine.java b/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java similarity index 63% rename from app/src/main/java/com/tangem/wallet/BtcCashEngine.java rename to app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java index b0b3fdaa56..5101b09051 100644 --- a/app/src/main/java/com/tangem/wallet/BtcCashEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/BtcCashEngine.java @@ -1,428 +1,389 @@ -package com.tangem.wallet; - -import android.net.Uri; - -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; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; - -import static com.tangem.wallet.FormatUtil.GetDecimalFormat; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class BtcCashEngine extends CoinEngine{ - public String GetNextNode(Tangem_Card mCard) - { - - return "35.157.238.5"; - } - public int GetNextNodePort(Tangem_Card mCard) - { - - return 51001; - } - public String GetNode(Tangem_Card mCard) - { - return "35.157.238.5"; - } - public int GetNodePort(Tangem_Card mCard) - { - return 51001; - } - - public void SwitchNode(Tangem_Card mCard) - { - } - - public boolean InOutPutVisible() - { - return true; - } - - public boolean AwaitingConfirmation(Tangem_Card card) - { - return card.getBalanceUnconfirmed()!=0; - } - - public String GetBalanceWithAlter(Tangem_Card mCard) - { - return GetBalance(mCard); - } - - public boolean IsBalanceAlterNotZero(Tangem_Card card) - { - return true; - } - - public Long GetBalanceLong(Tangem_Card mCard) - { - return mCard.getBalance(); - } - - public boolean IsBalanceNotZero(Tangem_Card card) - { - return card.getBalance() > 0; - } - - public boolean CheckAmount(Tangem_Card card, String amount) throws Exception - { - DecimalFormat decimalFormat = GetDecimalFormat(); - BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); - - // Convert Balance to BigDecimal - BigDecimal maxValue = new BigDecimal(GetBalanceValue(card)); - maxValue = maxValue.divide(new BigDecimal(1000)); - - //if (use_mCurrency) { - amountValue = amountValue.divide(new BigDecimal(1000)); - //} - - if (amountValue.compareTo(maxValue) > 0) { - return false; - } - - return true; - } - - public boolean HasBalanceInfo(Tangem_Card card) - { - return card.hasBalanceInfo(); - } - - public String GetBalanceCurrency(Tangem_Card card) - { - return "mBCH"; - } - - public boolean CheckUnspentTransaction(Tangem_Card mCard) - { - return mCard.getUnspentTransactions().size() != 0; - } - - public String GetFeeCurrency() - { - return "mBCH"; - } - - public boolean ValdateAddress(String address, Tangem_Card card){ - if(address == null || address.isEmpty()) - { - return false; - } - - if(address.length() < 25) - { - return false; - } - - if(address.length() > 35) - { - return false; - } - - if(!address.startsWith("1") && !address.startsWith("2") && !address.startsWith("3") && !address.startsWith("n") && !address.startsWith("m")) - { - return false; - } - - byte[] decAddress = Base58.decodeBase58(address); - - if(decAddress == null || decAddress.length == 0) - { - return false; - } - - byte[] rip = new byte[21]; - for(int i =0; i < 21; ++i) - { - rip[i] = decAddress[i]; - } - - byte[] kcv = CryptoUtil.doubleSha256(rip); - - for(int i =0; i < 4; ++i) - { - if(kcv[i] != decAddress[21+i]) - return false; - } - - if(card.getBlockchain()!=Blockchain.BitcoinCashTestNet && card.getBlockchain()!=Blockchain.BitcoinCash) - { - return false; - } - - if(card.getBlockchain()==Blockchain.BitcoinCashTestNet && (address.startsWith("1") || address.startsWith("3"))) - { - return false; - } - - return true; - } - - - public int GetTokenDecimals(Tangem_Card card) - { - return 0; - } - - public String GetContractAddress(Tangem_Card card) - { - return ""; - } - - public boolean IsNeedCheckNode() - { - return true; - } - - public Uri getShareWalletURIExplorer(Tangem_Card mCard) - { - return Uri.parse((mCard.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + mCard.getWallet()); - } - public Uri getShareWalletURI(Tangem_Card mCard) - { - return Uri.parse("bitcoincash:" + mCard.getWallet()); - } - public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) - { - Long fee = null; - Long amount = null; - try { - amount = mCard.InternalUnitsFromString(amountValue); - fee = mCard.InternalUnitsFromString(feeValue); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - - if(fee == null || amount == null) - return false; - - if(fee == 0 || amount ==0) - return false; - - if(fee > amount) - return false; - - if(fee < minFeeInInternalUnits) - return false; - - return true; - } - - public String EvaluteFeeEquivalent(Tangem_Card mCard, String fee) - { - return GetAmountEqualentDescriptor(mCard, fee); - } - - @Override - public String GetBalanceEquivalent(Tangem_Card mCard) { - Double balance = Double.NaN; - try{ - Long val = mCard.getBalance(); - balance = mCard.AmountFromInternalUnits(val); - } - catch(Exception ex) - { - mCard.setRate(0); - } - - return mCard.getAmountEquivalentDescription(balance); - } - - public String GetBalance(Tangem_Card mCard) - { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.AmountFromInternalUnits(mCard.getBalance()); - return mCard.getAmountDescription(balance); - } else { - return "-- -- -- " + mCard.getBlockchain().getCurrency(); - } - } - - public String GetBalanceValue(Tangem_Card mCard) - { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.getBalance() / (mCard.getBlockchain().getMultiplier() / 1000.0); - - String output = FormatUtil.DoubleToString(balance); - //String pattern = "#0.000"; // If you like 4 zeros - //DecimalFormat myFormatter = new DecimalFormat(pattern); - //String output = myFormatter.format(balance); - return output; - - //return Double.toString(balance); - } - else - { - return "0"; - } - } - - public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { - - byte netSelectionByte; - switch (mCard.getBlockchain()) { - case BitcoinCash: - netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet - break; - default : - netSelectionByte = (byte) 0x6f; //0 - MainNet 0x6f - TestNet - break; - } - - byte hash1[] = Util.calculateSHA256(pkUncompressed); - byte hash2[] = Util.calculateRIPEMD160(hash1); - - ByteBuffer BB = ByteBuffer.allocate(hash2.length + 1); - - BB.put(netSelectionByte); - BB.put(hash2); - - byte hash3[] = Util.calculateSHA256(BB.array()); - byte hash4[] = Util.calculateSHA256(hash3); - - BB = ByteBuffer.allocate(hash2.length + 5); - BB.put(netSelectionByte); //BB.put((byte) 0x6f); - BB.put(hash2); - BB.put(hash4[0]); - BB.put(hash4[1]); - BB.put(hash4[2]); - BB.put(hash4[3]); - - return org.bitcoinj.core.Base58.encode(BB.array()); - - } - - @Override - public String ConvertByteArrayToAmount(Tangem_Card mCard, byte[] bytes) throws Exception { - byte[] reversed=new byte[bytes.length]; - for(int i=0; i 0) { - return String.format("≈ USD %.2f", amount * rate); - } else { - return "≈ USD  ---"; - } - } - - public String GetAmountEqualentDescriptor(Tangem_Card mCard, String value) - { - return getAmountEquivalentDescriptionBTC(Double.parseDouble(value)/1000.0, mCard.getRate()); - } - - public byte[] Sign(String feeValue, String amountValue, String toValue, Tangem_Card mCard, CardProtocol protocol) throws Exception { - - String myAddress = mCard.getWallet(); - byte[] pbKey = mCard.getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY - String outputAddress = toValue; - String changeAddress = myAddress; - - // Build script for our address - List rawTxList = mCard.getUnspentTransactions(); - byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; - - // Collect unspent - ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); - - long fullAmount = 0; - for (int i = 0; i < unspentOutputs.size(); ++i) { - fullAmount += unspentOutputs.get(i).value; - } - - - long fees = FormatUtil.ConvertStringToLong(feeValue); - long amount = FormatUtil.ConvertStringToLong(amountValue); - amount = amount - fees; - - long change = fullAmount - fees - amount; - - if (amount + fees > fullAmount) { - throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)); - } - - byte[][] dataForSign = new byte[unspentOutputs.size()][]; - - for (int i = 0; i < unspentOutputs.size(); ++i) { - byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change); - - byte[] hashData = Util.calculateSHA256(newTX); - byte[] doubleHashData = Util.calculateSHA256(hashData); - - unspentOutputs.get(i).bodyDoubleHash = doubleHashData; - unspentOutputs.get(i).bodyHash = hashData; - - if(mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw || mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw_Validated_By_Issuer) - { - dataForSign[i] = newTX; - } - else - { - dataForSign[i] = doubleHashData; - } - - } - - byte[] signFromCard = null; - if(mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw || mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw_Validated_By_Issuer) - { - ByteArrayOutputStream bs = new ByteArrayOutputStream(); - if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); - for (int i = 0; i < dataForSign.length; i++) { - if (i != 0 && dataForSign[0].length != dataForSign[i].length) - throw new Exception("Hashes length must be identical!"); - bs.write(dataForSign[i]); - } - signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; - } - else { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer, null, mCard.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; - // TODO slice signFromCard to hashes.length parts - } - - LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); - - - for (int i = 0; i < unspentOutputs.size(); ++i) { - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); - BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); - s = CryptoUtil.toCanonicalised(s); - byte[] encodingSign = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); - - unspentOutputs.get(i).scriptForBuild = encodingSign; - } - - byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); - return realTX; - } -} +package com.tangem.domain.wallet; + +import android.net.Uri; + +import com.tangem.domain.cardReader.CardProtocol; +import com.tangem.domain.cardReader.TLV; +import com.tangem.util.Util; + +import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static com.tangem.domain.wallet.FormatUtil.GetDecimalFormat; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class BtcCashEngine extends CoinEngine { + public String GetNextNode(TangemCard mCard) { + + return "35.157.238.5"; + } + + public int GetNextNodePort(TangemCard mCard) { + + return 51001; + } + + public String GetNode(TangemCard mCard) { + return "35.157.238.5"; + } + + public int GetNodePort(TangemCard mCard) { + return 51001; + } + + public void SwitchNode(TangemCard mCard) { + } + + public boolean InOutPutVisible() { + return true; + } + + public boolean AwaitingConfirmation(TangemCard card) { + return card.getBalanceUnconfirmed() != 0; + } + + public String GetBalanceWithAlter(TangemCard mCard) { + return GetBalance(mCard); + } + + public boolean IsBalanceAlterNotZero(TangemCard card) { + return true; + } + + public Long GetBalanceLong(TangemCard mCard) { + return mCard.getBalance(); + } + + public boolean IsBalanceNotZero(TangemCard card) { + return card.getBalance() > 0; + } + + public boolean CheckAmount(TangemCard card, String amount) throws Exception { + DecimalFormat decimalFormat = GetDecimalFormat(); + BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); + + // Convert Balance to BigDecimal + BigDecimal maxValue = new BigDecimal(GetBalanceValue(card)); + maxValue = maxValue.divide(new BigDecimal(1000)); + + //if (use_mCurrency) { + amountValue = amountValue.divide(new BigDecimal(1000)); + //} + + if (amountValue.compareTo(maxValue) > 0) { + return false; + } + + return true; + } + + public boolean HasBalanceInfo(TangemCard card) { + return card.hasBalanceInfo(); + } + + public String GetBalanceCurrency(TangemCard card) { + return "mBCH"; + } + + public boolean CheckUnspentTransaction(TangemCard mCard) { + return mCard.getUnspentTransactions().size() != 0; + } + + public String GetFeeCurrency() { + return "mBCH"; + } + + public boolean ValdateAddress(String address, TangemCard card) { + if (address == null || address.isEmpty()) { + return false; + } + + if (address.length() < 25) { + return false; + } + + if (address.length() > 35) { + return false; + } + + if (!address.startsWith("1") && !address.startsWith("2") && !address.startsWith("3") && !address.startsWith("n") && !address.startsWith("m")) { + return false; + } + + byte[] decAddress = Base58.decodeBase58(address); + + if (decAddress == null || decAddress.length == 0) { + return false; + } + + byte[] rip = new byte[21]; + for (int i = 0; i < 21; ++i) { + rip[i] = decAddress[i]; + } + + byte[] kcv = CryptoUtil.doubleSha256(rip); + + for (int i = 0; i < 4; ++i) { + if (kcv[i] != decAddress[21 + i]) + return false; + } + + if (card.getBlockchain() != Blockchain.BitcoinCashTestNet && card.getBlockchain() != Blockchain.BitcoinCash) { + return false; + } + + if (card.getBlockchain() == Blockchain.BitcoinCashTestNet && (address.startsWith("1") || address.startsWith("3"))) { + return false; + } + + return true; + } + + + public int GetTokenDecimals(TangemCard card) { + return 0; + } + + public String GetContractAddress(TangemCard card) { + return ""; + } + + public boolean IsNeedCheckNode() { + return true; + } + + public Uri getShareWalletURIExplorer(TangemCard mCard) { + return Uri.parse((mCard.getBlockchain() == Blockchain.BitcoinCash ? "https://bitcoincash.blockexplorer.com/address/" : "https://testnet.blockexplorer.com/address/") + mCard.getWallet()); + } + + public Uri getShareWalletURI(TangemCard mCard) { + return Uri.parse("bitcoincash:" + mCard.getWallet()); + } + + public boolean CheckAmountValie(TangemCard mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) { + Long fee = null; + Long amount = null; + try { + amount = mCard.InternalUnitsFromString(amountValue); + fee = mCard.InternalUnitsFromString(feeValue); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + if (fee == null || amount == null) + return false; + + if (fee == 0 || amount == 0) + return false; + + if (fee > amount) + return false; + + if (fee < minFeeInInternalUnits) + return false; + + return true; + } + + public String EvaluteFeeEquivalent(TangemCard mCard, String fee) { + return GetAmountEqualentDescriptor(mCard, fee); + } + + @Override + public String GetBalanceEquivalent(TangemCard mCard) { + Double balance = Double.NaN; + try { + Long val = mCard.getBalance(); + balance = mCard.AmountFromInternalUnits(val); + } catch (Exception ex) { + mCard.setRate(0); + } + + return mCard.getAmountEquivalentDescription(balance); + } + + public String GetBalance(TangemCard mCard) { + if (mCard.hasBalanceInfo()) { + Double balance = mCard.AmountFromInternalUnits(mCard.getBalance()); + return mCard.getAmountDescription(balance); + } else { + return "-- -- -- " + mCard.getBlockchain().getCurrency(); + } + } + + public String GetBalanceValue(TangemCard mCard) { + if (mCard.hasBalanceInfo()) { + Double balance = mCard.getBalance() / (mCard.getBlockchain().getMultiplier() / 1000.0); + + String output = FormatUtil.DoubleToString(balance); + //String pattern = "#0.000"; // If you like 4 zeros + //DecimalFormat myFormatter = new DecimalFormat(pattern); + //String output = myFormatter.format(balance); + return output; + + //return Double.toString(balance); + } else { + return "0"; + } + } + + public String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + + byte netSelectionByte; + switch (mCard.getBlockchain()) { + case BitcoinCash: + netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet + break; + default: + netSelectionByte = (byte) 0x6f; //0 - MainNet 0x6f - TestNet + break; + } + + byte hash1[] = Util.calculateSHA256(pkUncompressed); + byte hash2[] = Util.calculateRIPEMD160(hash1); + + ByteBuffer BB = ByteBuffer.allocate(hash2.length + 1); + + BB.put(netSelectionByte); + BB.put(hash2); + + byte hash3[] = Util.calculateSHA256(BB.array()); + byte hash4[] = Util.calculateSHA256(hash3); + + BB = ByteBuffer.allocate(hash2.length + 5); + BB.put(netSelectionByte); //BB.put((byte) 0x6f); + BB.put(hash2); + BB.put(hash4[0]); + BB.put(hash4[1]); + BB.put(hash4[2]); + BB.put(hash4[3]); + + return org.bitcoinj.core.Base58.encode(BB.array()); + + } + + @Override + public String ConvertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception { + byte[] reversed = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; + return FormatUtil.DoubleToString(1000.0 * mCard.AmountFromInternalUnits(Util.byteArrayToLong(reversed))); + } + + @Override + public byte[] ConvertAmountToByteArray(TangemCard mCard, String amount) throws Exception { + byte[] bytes = Util.longToByteArray(mCard.InternalUnitsFromString(amount)); + byte[] reversed = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; + return reversed; + } + + @Override + public String GetAmountDescription(TangemCard mCard, String amount) throws Exception { + return mCard.getAmountDescription(Double.parseDouble(amount) / 1000.0); + } + + public static String getAmountEquivalentDescriptionBTC(Double amount, float rate) { + if (rate > 0) { + return String.format("≈ USD %.2f", amount * rate); + } else { + return "≈ USD  ---"; + } + } + + public String GetAmountEqualentDescriptor(TangemCard mCard, String value) { + return getAmountEquivalentDescriptionBTC(Double.parseDouble(value) / 1000.0, mCard.getRate()); + } + + public byte[] Sign(String feeValue, String amountValue, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { + + String myAddress = mCard.getWallet(); + byte[] pbKey = mCard.getWalletPublicKeyRar(); //ALWAYS USING COMPRESS KEY + String outputAddress = toValue; + String changeAddress = myAddress; + + // Build script for our address + List rawTxList = mCard.getUnspentTransactions(); + byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; + + // Collect unspent + ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); + + long fullAmount = 0; + for (int i = 0; i < unspentOutputs.size(); ++i) { + fullAmount += unspentOutputs.get(i).value; + } + + + long fees = FormatUtil.ConvertStringToLong(feeValue); + long amount = FormatUtil.ConvertStringToLong(amountValue); + amount = amount - fees; + + long change = fullAmount - fees - amount; + + if (amount + fees > fullAmount) { + throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)); + } + + byte[][] dataForSign = new byte[unspentOutputs.size()][]; + + for (int i = 0; i < unspentOutputs.size(); ++i) { + byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change); + + byte[] hashData = Util.calculateSHA256(newTX); + byte[] doubleHashData = Util.calculateSHA256(hashData); + + unspentOutputs.get(i).bodyDoubleHash = doubleHashData; + unspentOutputs.get(i).bodyHash = hashData; + + if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + dataForSign[i] = newTX; + } else { + dataForSign[i] = doubleHashData; + } + + } + + byte[] signFromCard = null; + if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); + for (int i = 0; i < dataForSign.length; i++) { + if (i != 0 && dataForSign[0].length != dataForSign[i].length) + throw new Exception("Hashes length must be identical!"); + bs.write(dataForSign[i]); + } + signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; + } else { + signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, mCard.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; + // TODO slice signFromCard to hashes.length parts + } + + LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); + + + for (int i = 0; i < unspentOutputs.size(); ++i) { + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); + BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); + s = CryptoUtil.toCanonicalised(s); + byte[] encodingSign = DerEncodingUtil.packSignDerBitcoinCash(r, s, pbKey); + + unspentOutputs.get(i).scriptForBuild = encodingSign; + } + + byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); + return realTX; + } +} diff --git a/app/src/main/java/com/tangem/wallet/BtcEngine.java b/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java similarity index 67% rename from app/src/main/java/com/tangem/wallet/BtcEngine.java rename to app/src/main/java/com/tangem/domain/wallet/BtcEngine.java index 2e6a4a1029..ed7d84fbdf 100644 --- a/app/src/main/java/com/tangem/wallet/BtcEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/BtcEngine.java @@ -1,564 +1,524 @@ -package com.tangem.wallet; - -import android.net.Uri; - -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; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Random; - -import static com.tangem.wallet.FormatUtil.GetDecimalFormat; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class BtcEngine extends CoinEngine{ - public String GetNextNode(Tangem_Card mCard) - { - return getNextServiceHost(mCard); - } - public int GetNextNodePort(Tangem_Card mCard) - { - return getNextServicePort(mCard); - } - public String GetNode(Tangem_Card mCard) - { - return getServiceHost(mCard); - } - public int GetNodePort(Tangem_Card mCard) - { - return getServicePort(mCard); - } - - public void SwitchNode(Tangem_Card mCard) - { - SelectNextBitconServiceIndex(); - } - - public static String[] GetBitcoinServiceHosts() { - return new String[]{"vps.hsmiths.com", "tardis.bauerj.eu" /*"arihancckjge66iv.onion"*/, "electrumx.bot.nu","electrumx.hopto.org"/* "btc.asis.io"*/, "e-x.not.fyi", "electrum.backplanedns.org", "helicarrier.bauerj.eu", "electrum.vom-stausee.de", "electrum0.snel.it", "kirsche.emzy.de"}; - } - - public static String[] GetBitcoinTestNetServiceHosts() { - return new String[]{/*"testnetnode.arihanc.com"*/"testnet.hsmiths.com", "testnet.qtornado.com", "testnet1.bauerj.eu"}; - } - - public static Integer[] GetBitcoinServicePorts() { - return new Integer[]{8080,50001/* 8080*/, 50001, 50001, 50001, 50001, 50001, 50001, 50001, 50001}; - } - - public static Integer[] GetBitcoinTestNetServicePorts() { - return new Integer[]{/*51001*/53011, 51001, 50001}; - } - - static int serviceIndex = GetNextBitconMainNetServiceIndex(); - - static int dynamicIndex = GetNextBitconMainNetServiceIndex(); - - static int serviceIndexTestNet = GetNextBitconTestNetServiceIndex(); - - static int dynamicTestNetIndex = GetNextBitconTestNetServiceIndex(); - - static long lastChangeServiceIndex = 0; - - public static int GetNextBitconMainNetServiceIndex() { - Random r = new Random(); - return r.nextInt(GetBitcoinServiceHosts().length); - } - - public static void SelectNextBitconMainNetServiceIndex() { - //serviceIndex = GetNextBitconMainNetServiceIndex(); - serviceIndex++; - if (serviceIndex > GetBitcoinServiceHosts().length - 1) serviceIndex = 0; - } - - public static int GetNextBitconTestNetServiceIndex() { - Random r = new Random(); - return r.nextInt(GetBitcoinTestNetServiceHosts().length); - } - - public static void SelectNextBitconTestNetServiceIndex() { - //serviceIndexTestNet = GetNextBitconTestNetServiceIndex(); - - serviceIndexTestNet++; - if (serviceIndexTestNet > GetBitcoinTestNetServiceHosts().length - 1) serviceIndexTestNet = 0; - } - - public static void setNextDynamicIndex() { - //dynamicIndex = GetNextBitconMainNetServiceIndex(); - dynamicIndex++; - if (dynamicIndex > GetBitcoinServiceHosts().length - 1) dynamicIndex = 0; - } - - public static void setNextDynamicTestNet() { - //dynamicTestNetIndex = GetNextBitconTestNetServiceIndex(); - dynamicTestNetIndex++; - if (dynamicTestNetIndex > GetBitcoinTestNetServiceHosts().length - 1) dynamicTestNetIndex = 0; - - } - - public static void SelectNextBitconServiceIndex() { - long unixTime = System.currentTimeMillis() / 1000L; - long nextStampOffset = 5; - if(lastChangeServiceIndex == 0) - { - lastChangeServiceIndex = unixTime; - } - else if(lastChangeServiceIndex + nextStampOffset > unixTime ) - { - return; - } - - lastChangeServiceIndex = unixTime; - - SelectNextBitconMainNetServiceIndex(); - SelectNextBitconTestNetServiceIndex(); - } - - public static String getServiceHost(Tangem_Card mCard) { - switch (mCard.getBlockchain()) { - case Bitcoin: - return GetBitcoinServiceHosts()[serviceIndex]; //"hsmiths.changeip.net"; - case BitcoinTestNet: - return GetBitcoinTestNetServiceHosts()[serviceIndexTestNet]; //"testnetnode.arihanc.com"; - } - return null; - } - - public static String getNextServiceHost(Tangem_Card mCard) { - switch (mCard.getBlockchain()) { - case Bitcoin: { - setNextDynamicIndex(); - return GetBitcoinServiceHosts()[dynamicIndex]; - } - case BitcoinTestNet: { - setNextDynamicTestNet(); - return GetBitcoinTestNetServiceHosts()[dynamicTestNetIndex]; //"testnetnode.arihanc.com"; - } - //case BitcoinCash: - //{ - // return GetBitcoinCashServiceHosts()[0]; - //} - //case BitcoinCashTestNet: { - // return GetBitcoinCashTestNetServiceHosts()[0]; - //} - } - return null; - } - - public static int getNextServicePort(Tangem_Card mCard) { - switch (mCard.getBlockchain()) { - case Bitcoin: { - setNextDynamicIndex(); - return GetBitcoinServicePorts()[dynamicIndex];//8080; - } - case BitcoinTestNet: { - setNextDynamicTestNet(); - return GetBitcoinTestNetServicePorts()[dynamicTestNetIndex];//51001; - } - } - return 8080; - } - - public static int getServicePort(Tangem_Card mCard) { - switch (mCard.getBlockchain()) { - case Bitcoin: - return GetBitcoinServicePorts()[serviceIndex];//8080; - case BitcoinTestNet: - return GetBitcoinTestNetServicePorts()[serviceIndexTestNet];//51001; - } - return 8080; - } - - - public boolean InOutPutVisible() - { - return true; - } - - public boolean AwaitingConfirmation(Tangem_Card card) - { - return card.getBalanceUnconfirmed()!=0; - } - - public String GetBalanceWithAlter(Tangem_Card mCard) - { - return GetBalance(mCard); - } - - public boolean IsBalanceAlterNotZero(Tangem_Card card) - { - return true; - } - - public Long GetBalanceLong(Tangem_Card mCard) - { - return mCard.getBalance(); - } - - public boolean IsBalanceNotZero(Tangem_Card card) - { - return card.getBalance() > 0; - } - - public boolean CheckAmount(Tangem_Card card, String amount) throws Exception - { - DecimalFormat decimalFormat = GetDecimalFormat(); - BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); - - // Convert Balance to BigDecimal - BigDecimal maxValue = new BigDecimal(GetBalanceValue(card)); - maxValue = maxValue.divide(new BigDecimal(1000)); - - //if (use_mCurrency) { - amountValue = amountValue.divide(new BigDecimal(1000)); - //} - - if (amountValue.compareTo(maxValue) > 0) { - return false; - } - - return true; - } - - public boolean HasBalanceInfo(Tangem_Card card) - { - return card.hasBalanceInfo(); - } - - public String GetBalanceCurrency(Tangem_Card card) - { - return "mBTC"; - } - - public boolean CheckUnspentTransaction(Tangem_Card mCard) - { - return mCard.getUnspentTransactions().size() != 0; - } - - public String GetFeeCurrency() - { - return "mBTC"; - } - - public boolean ValdateAddress(String address, Tangem_Card card){ - if(address == null || address.isEmpty()) - { - return false; - } - - if(address.length() < 25) - { - return false; - } - - if(address.length() > 35) - { - return false; - } - - if(!address.startsWith("1") && !address.startsWith("2") && !address.startsWith("3") && !address.startsWith("n") && !address.startsWith("m")) - { - return false; - } - - byte[] decAddress = Base58.decodeBase58(address); - - if(decAddress == null || decAddress.length == 0) - { - return false; - } - - byte[] rip = new byte[21]; - for(int i =0; i < 21; ++i) - { - rip[i] = decAddress[i]; - } - - byte[] kcv = CryptoUtil.doubleSha256(rip); - - for(int i =0; i < 4; ++i) - { - if(kcv[i] != decAddress[21+i]) - return false; - } - - if(card.getBlockchain()!=Blockchain.BitcoinTestNet && card.getBlockchain()!=Blockchain.Bitcoin) - { - return false; - } - - if(card.getBlockchain()==Blockchain.BitcoinTestNet && (address.startsWith("1") || address.startsWith("3"))) - { - return false; - } - - return true; - } - - - public int GetTokenDecimals(Tangem_Card card) - { - return 0; - } - - public String GetContractAddress(Tangem_Card card) - { - return ""; - } - - public boolean IsNeedCheckNode() - { - return true; - } - - public Uri getShareWalletURIExplorer(Tangem_Card mCard) - { - return Uri.parse((mCard.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + mCard.getWallet()); - } - public Uri getShareWalletURI(Tangem_Card mCard) - { - return Uri.parse("bitcoin:" + mCard.getWallet()); - } - public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) - { - Long fee = null; - Long amount = null; - try { - amount = mCard.InternalUnitsFromString(amountValue); - fee = mCard.InternalUnitsFromString(feeValue); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - - if(fee == null || amount == null) - return false; - - if(fee == 0 || amount ==0) - return false; - - if(fee > amount) - return false; - - if(fee < minFeeInInternalUnits) - return false; - - return true; - } - - public String EvaluteFeeEquivalent(Tangem_Card mCard, String fee) - { - return GetAmountEqualentDescriptor(mCard, fee); - } - - @Override - public String GetBalanceEquivalent(Tangem_Card mCard) { - Double balance = Double.NaN; - try{ - Long val = mCard.getBalance(); - balance = mCard.AmountFromInternalUnits(val); - } - catch(Exception ex) - { - mCard.setRate(0); - } - - return mCard.getAmountEquivalentDescription(balance); - } - - public String GetBalance(Tangem_Card mCard) - { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.AmountFromInternalUnits(mCard.getBalance()); - return mCard.getAmountDescription(balance); - } else { - return "-- -- -- " + mCard.getBlockchain().getCurrency(); - } - } - - public String GetBalanceValue(Tangem_Card mCard) - { - if (mCard.hasBalanceInfo()) { - Double balance = mCard.getBalance() / (mCard.getBlockchain().getMultiplier() / 1000.0); - - String output = FormatUtil.DoubleToString(balance); - //String pattern = "#0.000"; // If you like 4 zeros - //DecimalFormat myFormatter = new DecimalFormat(pattern); - //String output = myFormatter.format(balance); - return output; - - //return Double.toString(balance); - } - else - { - return "0"; - } - } - - public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { - - byte netSelectionByte; - switch (mCard.getBlockchain()) { - case Bitcoin: - netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet - break; - default : - netSelectionByte = (byte) 0x6f; //0 - MainNet 0x6f - TestNet - break; - } - - byte hash1[] = Util.calculateSHA256(pkUncompressed); - byte hash2[] = Util.calculateRIPEMD160(hash1); - - ByteBuffer BB = ByteBuffer.allocate(hash2.length + 1); - - BB.put(netSelectionByte); - BB.put(hash2); - - byte hash3[] = Util.calculateSHA256(BB.array()); - byte hash4[] = Util.calculateSHA256(hash3); - - BB = ByteBuffer.allocate(hash2.length + 5); - BB.put(netSelectionByte); //BB.put((byte) 0x6f); - BB.put(hash2); - BB.put(hash4[0]); - BB.put(hash4[1]); - BB.put(hash4[2]); - BB.put(hash4[3]); - - return org.bitcoinj.core.Base58.encode(BB.array()); - - } - - @Override - public String ConvertByteArrayToAmount(Tangem_Card mCard, byte[] bytes) throws Exception { - byte[] reversed=new byte[bytes.length]; - for(int i=0; i 0) { - return String.format("≈ USD %.2f", amount * rate); - } else { - return "≈ USD  ---"; - } - } - - public String GetAmountEqualentDescriptor(Tangem_Card mCard, String value) - { - return getAmountEquivalentDescriptionBTC(Double.parseDouble(value)/1000.0, mCard.getRate()); - } - - public byte[] Sign(String feeValue, String amountValue, String toValue, Tangem_Card mCard, CardProtocol protocol) throws Exception { - - String myAddress = mCard.getWallet(); - byte[] pbKey = mCard.getWalletPublicKey(); - String outputAddress = toValue; - String changeAddress = myAddress; - - // Build script for our address - List rawTxList = mCard.getUnspentTransactions(); - byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; - - // Collect unspent - ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); - - long fullAmount = 0; - for (int i = 0; i < unspentOutputs.size(); ++i) { - fullAmount += unspentOutputs.get(i).value; - } - - - long fees = FormatUtil.ConvertStringToLong(feeValue); - long amount = FormatUtil.ConvertStringToLong(amountValue); - amount = amount - fees; - - long change = fullAmount - fees - amount; - - if (amount + fees > fullAmount) { - throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)); - } - - byte[][] dataForSign = new byte[unspentOutputs.size()][]; - - for (int i = 0; i < unspentOutputs.size(); ++i) { - byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change); - - byte[] hashData = Util.calculateSHA256(newTX); - byte[] doubleHashData = Util.calculateSHA256(hashData); - - unspentOutputs.get(i).bodyDoubleHash = doubleHashData; - unspentOutputs.get(i).bodyHash = hashData; - - if(mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw || mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw_Validated_By_Issuer) - { - dataForSign[i] = newTX; - } - else - { - dataForSign[i] = doubleHashData; - } - - } - - byte[] signFromCard = null; - if(mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw || mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Raw_Validated_By_Issuer) - { - ByteArrayOutputStream bs = new ByteArrayOutputStream(); - if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); - for (int i = 0; i < dataForSign.length; i++) { - if (i != 0 && dataForSign[0].length != dataForSign[i].length) - throw new Exception("Hashes length must be identical!"); - bs.write(dataForSign[i]); - } - signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; - } - else { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer, null, mCard.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; - // TODO slice signFromCard to hashes.length parts - } - - LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); - - - for (int i = 0; i < unspentOutputs.size(); ++i) { - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); - BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); - s = CryptoUtil.toCanonicalised(s); - byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey); - - unspentOutputs.get(i).scriptForBuild = encodingSign; - } - - byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); - return realTX; - } -} +package com.tangem.domain.wallet; + +import android.net.Uri; + +import com.tangem.domain.cardReader.CardProtocol; +import com.tangem.domain.cardReader.TLV; +import com.tangem.util.Util; + +import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Random; + +import static com.tangem.domain.wallet.FormatUtil.GetDecimalFormat; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class BtcEngine extends CoinEngine { + public String GetNextNode(TangemCard mCard) { + return getNextServiceHost(mCard); + } + + public int GetNextNodePort(TangemCard mCard) { + return getNextServicePort(mCard); + } + + public String GetNode(TangemCard mCard) { + return getServiceHost(mCard); + } + + public int GetNodePort(TangemCard mCard) { + return getServicePort(mCard); + } + + public void SwitchNode(TangemCard mCard) { + SelectNextBitconServiceIndex(); + } + + public static String[] GetBitcoinServiceHosts() { + return new String[]{"vps.hsmiths.com", "tardis.bauerj.eu" /*"arihancckjge66iv.onion"*/, "electrumx.bot.nu", "electrumx.hopto.org"/* "btc.asis.io"*/, "e-x.not.fyi", "electrum.backplanedns.org", "helicarrier.bauerj.eu", "electrum.vom-stausee.de", "electrum0.snel.it", "kirsche.emzy.de"}; + } + + public static String[] GetBitcoinTestNetServiceHosts() { + return new String[]{/*"testnetnode.arihanc.com"*/"testnet.hsmiths.com", "testnet.qtornado.com", "testnet1.bauerj.eu"}; + } + + public static Integer[] GetBitcoinServicePorts() { + return new Integer[]{8080, 50001/* 8080*/, 50001, 50001, 50001, 50001, 50001, 50001, 50001, 50001}; + } + + public static Integer[] GetBitcoinTestNetServicePorts() { + return new Integer[]{/*51001*/53011, 51001, 50001}; + } + + static int serviceIndex = GetNextBitconMainNetServiceIndex(); + + static int dynamicIndex = GetNextBitconMainNetServiceIndex(); + + static int serviceIndexTestNet = GetNextBitconTestNetServiceIndex(); + + static int dynamicTestNetIndex = GetNextBitconTestNetServiceIndex(); + + static long lastChangeServiceIndex = 0; + + public static int GetNextBitconMainNetServiceIndex() { + Random r = new Random(); + return r.nextInt(GetBitcoinServiceHosts().length); + } + + public static void SelectNextBitconMainNetServiceIndex() { + //serviceIndex = GetNextBitconMainNetServiceIndex(); + serviceIndex++; + if (serviceIndex > GetBitcoinServiceHosts().length - 1) serviceIndex = 0; + } + + public static int GetNextBitconTestNetServiceIndex() { + Random r = new Random(); + return r.nextInt(GetBitcoinTestNetServiceHosts().length); + } + + public static void SelectNextBitconTestNetServiceIndex() { + //serviceIndexTestNet = GetNextBitconTestNetServiceIndex(); + + serviceIndexTestNet++; + if (serviceIndexTestNet > GetBitcoinTestNetServiceHosts().length - 1) + serviceIndexTestNet = 0; + } + + public static void setNextDynamicIndex() { + //dynamicIndex = GetNextBitconMainNetServiceIndex(); + dynamicIndex++; + if (dynamicIndex > GetBitcoinServiceHosts().length - 1) dynamicIndex = 0; + } + + public static void setNextDynamicTestNet() { + //dynamicTestNetIndex = GetNextBitconTestNetServiceIndex(); + dynamicTestNetIndex++; + if (dynamicTestNetIndex > GetBitcoinTestNetServiceHosts().length - 1) + dynamicTestNetIndex = 0; + + } + + public static void SelectNextBitconServiceIndex() { + long unixTime = System.currentTimeMillis() / 1000L; + long nextStampOffset = 5; + if (lastChangeServiceIndex == 0) { + lastChangeServiceIndex = unixTime; + } else if (lastChangeServiceIndex + nextStampOffset > unixTime) { + return; + } + + lastChangeServiceIndex = unixTime; + + SelectNextBitconMainNetServiceIndex(); + SelectNextBitconTestNetServiceIndex(); + } + + public static String getServiceHost(TangemCard mCard) { + switch (mCard.getBlockchain()) { + case Bitcoin: + return GetBitcoinServiceHosts()[serviceIndex]; //"hsmiths.changeip.net"; + case BitcoinTestNet: + return GetBitcoinTestNetServiceHosts()[serviceIndexTestNet]; //"testnetnode.arihanc.com"; + } + return null; + } + + public static String getNextServiceHost(TangemCard mCard) { + switch (mCard.getBlockchain()) { + case Bitcoin: { + setNextDynamicIndex(); + return GetBitcoinServiceHosts()[dynamicIndex]; + } + case BitcoinTestNet: { + setNextDynamicTestNet(); + return GetBitcoinTestNetServiceHosts()[dynamicTestNetIndex]; //"testnetnode.arihanc.com"; + } + //case BitcoinCash: + //{ + // return GetBitcoinCashServiceHosts()[0]; + //} + //case BitcoinCashTestNet: { + // return GetBitcoinCashTestNetServiceHosts()[0]; + //} + } + return null; + } + + public static int getNextServicePort(TangemCard mCard) { + switch (mCard.getBlockchain()) { + case Bitcoin: { + setNextDynamicIndex(); + return GetBitcoinServicePorts()[dynamicIndex];//8080; + } + case BitcoinTestNet: { + setNextDynamicTestNet(); + return GetBitcoinTestNetServicePorts()[dynamicTestNetIndex];//51001; + } + } + return 8080; + } + + public static int getServicePort(TangemCard mCard) { + switch (mCard.getBlockchain()) { + case Bitcoin: + return GetBitcoinServicePorts()[serviceIndex];//8080; + case BitcoinTestNet: + return GetBitcoinTestNetServicePorts()[serviceIndexTestNet];//51001; + } + return 8080; + } + + + public boolean InOutPutVisible() { + return true; + } + + public boolean AwaitingConfirmation(TangemCard card) { + return card.getBalanceUnconfirmed() != 0; + } + + public String GetBalanceWithAlter(TangemCard mCard) { + return GetBalance(mCard); + } + + public boolean IsBalanceAlterNotZero(TangemCard card) { + return true; + } + + public Long GetBalanceLong(TangemCard mCard) { + return mCard.getBalance(); + } + + public boolean IsBalanceNotZero(TangemCard card) { + return card.getBalance() > 0; + } + + public boolean CheckAmount(TangemCard card, String amount) throws Exception { + DecimalFormat decimalFormat = GetDecimalFormat(); + BigDecimal amountValue = (BigDecimal) decimalFormat.parse(amount); + + // Convert Balance to BigDecimal + BigDecimal maxValue = new BigDecimal(GetBalanceValue(card)); + maxValue = maxValue.divide(new BigDecimal(1000)); + + //if (use_mCurrency) { + amountValue = amountValue.divide(new BigDecimal(1000)); + //} + + if (amountValue.compareTo(maxValue) > 0) { + return false; + } + + return true; + } + + public boolean HasBalanceInfo(TangemCard card) { + return card.hasBalanceInfo(); + } + + public String GetBalanceCurrency(TangemCard card) { + return "mBTC"; + } + + public boolean CheckUnspentTransaction(TangemCard mCard) { + return mCard.getUnspentTransactions().size() != 0; + } + + public String GetFeeCurrency() { + return "mBTC"; + } + + public boolean ValdateAddress(String address, TangemCard card) { + if (address == null || address.isEmpty()) { + return false; + } + + if (address.length() < 25) { + return false; + } + + if (address.length() > 35) { + return false; + } + + if (!address.startsWith("1") && !address.startsWith("2") && !address.startsWith("3") && !address.startsWith("n") && !address.startsWith("m")) { + return false; + } + + byte[] decAddress = Base58.decodeBase58(address); + + if (decAddress == null || decAddress.length == 0) { + return false; + } + + byte[] rip = new byte[21]; + for (int i = 0; i < 21; ++i) { + rip[i] = decAddress[i]; + } + + byte[] kcv = CryptoUtil.doubleSha256(rip); + + for (int i = 0; i < 4; ++i) { + if (kcv[i] != decAddress[21 + i]) + return false; + } + + if (card.getBlockchain() != Blockchain.BitcoinTestNet && card.getBlockchain() != Blockchain.Bitcoin) { + return false; + } + + if (card.getBlockchain() == Blockchain.BitcoinTestNet && (address.startsWith("1") || address.startsWith("3"))) { + return false; + } + + return true; + } + + + public int GetTokenDecimals(TangemCard card) { + return 0; + } + + public String GetContractAddress(TangemCard card) { + return ""; + } + + public boolean IsNeedCheckNode() { + return true; + } + + public Uri getShareWalletURIExplorer(TangemCard mCard) { + return Uri.parse((mCard.getBlockchain() == Blockchain.Bitcoin ? "https://blockchain.info/address/" : "https://testnet.blockchain.info/address/") + mCard.getWallet()); + } + + public Uri getShareWalletURI(TangemCard mCard) { + return Uri.parse("bitcoin:" + mCard.getWallet()); + } + + public boolean CheckAmountValie(TangemCard mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) { + Long fee = null; + Long amount = null; + try { + amount = mCard.InternalUnitsFromString(amountValue); + fee = mCard.InternalUnitsFromString(feeValue); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + if (fee == null || amount == null) + return false; + + if (fee == 0 || amount == 0) + return false; + + if (fee > amount) + return false; + + if (fee < minFeeInInternalUnits) + return false; + + return true; + } + + public String EvaluteFeeEquivalent(TangemCard mCard, String fee) { + return GetAmountEqualentDescriptor(mCard, fee); + } + + @Override + public String GetBalanceEquivalent(TangemCard mCard) { + Double balance = Double.NaN; + try { + Long val = mCard.getBalance(); + balance = mCard.AmountFromInternalUnits(val); + } catch (Exception ex) { + mCard.setRate(0); + } + + return mCard.getAmountEquivalentDescription(balance); + } + + public String GetBalance(TangemCard mCard) { + if (mCard.hasBalanceInfo()) { + Double balance = mCard.AmountFromInternalUnits(mCard.getBalance()); + return mCard.getAmountDescription(balance); + } else { + return "-- -- -- " + mCard.getBlockchain().getCurrency(); + } + } + + public String GetBalanceValue(TangemCard mCard) { + if (mCard.hasBalanceInfo()) { + Double balance = mCard.getBalance() / (mCard.getBlockchain().getMultiplier() / 1000.0); + + String output = FormatUtil.DoubleToString(balance); + //String pattern = "#0.000"; // If you like 4 zeros + //DecimalFormat myFormatter = new DecimalFormat(pattern); + //String output = myFormatter.format(balance); + return output; + + //return Double.toString(balance); + } else { + return "0"; + } + } + + public String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + + byte netSelectionByte; + switch (mCard.getBlockchain()) { + case Bitcoin: + netSelectionByte = (byte) 0x00; //0 - MainNet 0x6f - TestNet + break; + default: + netSelectionByte = (byte) 0x6f; //0 - MainNet 0x6f - TestNet + break; + } + + byte hash1[] = Util.calculateSHA256(pkUncompressed); + byte hash2[] = Util.calculateRIPEMD160(hash1); + + ByteBuffer BB = ByteBuffer.allocate(hash2.length + 1); + + BB.put(netSelectionByte); + BB.put(hash2); + + byte hash3[] = Util.calculateSHA256(BB.array()); + byte hash4[] = Util.calculateSHA256(hash3); + + BB = ByteBuffer.allocate(hash2.length + 5); + BB.put(netSelectionByte); //BB.put((byte) 0x6f); + BB.put(hash2); + BB.put(hash4[0]); + BB.put(hash4[1]); + BB.put(hash4[2]); + BB.put(hash4[3]); + + return org.bitcoinj.core.Base58.encode(BB.array()); + + } + + @Override + public String ConvertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception { + byte[] reversed = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; + return FormatUtil.DoubleToString(1000.0 * mCard.AmountFromInternalUnits(Util.byteArrayToLong(reversed))); + } + + @Override + public byte[] ConvertAmountToByteArray(TangemCard mCard, String amount) throws Exception { + byte[] bytes = Util.longToByteArray(mCard.InternalUnitsFromString(amount)); + byte[] reversed = new byte[bytes.length]; + for (int i = 0; i < bytes.length; i++) reversed[i] = bytes[bytes.length - i - 1]; + return reversed; + } + + @Override + public String GetAmountDescription(TangemCard mCard, String amount) throws Exception { + return mCard.getAmountDescription(Double.parseDouble(amount) / 1000.0); + } + + public static String getAmountEquivalentDescriptionBTC(Double amount, float rate) { + if (rate > 0) { + return String.format("≈ USD %.2f", amount * rate); + } else { + return "≈ USD  ---"; + } + } + + public String GetAmountEqualentDescriptor(TangemCard mCard, String value) { + return getAmountEquivalentDescriptionBTC(Double.parseDouble(value) / 1000.0, mCard.getRate()); + } + + public byte[] Sign(String feeValue, String amountValue, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { + + String myAddress = mCard.getWallet(); + byte[] pbKey = mCard.getWalletPublicKey(); + String outputAddress = toValue; + String changeAddress = myAddress; + + // Build script for our address + List rawTxList = mCard.getUnspentTransactions(); + byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; + + // Collect unspent + ArrayList unspentOutputs = BTCUtils.getOutputs(rawTxList, outputScriptWeAreAbleToSpend); + + long fullAmount = 0; + for (int i = 0; i < unspentOutputs.size(); ++i) { + fullAmount += unspentOutputs.get(i).value; + } + + + long fees = FormatUtil.ConvertStringToLong(feeValue); + long amount = FormatUtil.ConvertStringToLong(amountValue); + amount = amount - fees; + + long change = fullAmount - fees - amount; + + if (amount + fees > fullAmount) { + throw new Exception(String.format("Balance (%d) < amount (%d) + (%d)", fullAmount, change, amount)); + } + + byte[][] dataForSign = new byte[unspentOutputs.size()][]; + + for (int i = 0; i < unspentOutputs.size(); ++i) { + byte[] newTX = BTCUtils.buildTXForSign(myAddress, outputAddress, changeAddress, unspentOutputs, i, amount, change); + + byte[] hashData = Util.calculateSHA256(newTX); + byte[] doubleHashData = Util.calculateSHA256(hashData); + + unspentOutputs.get(i).bodyDoubleHash = doubleHashData; + unspentOutputs.get(i).bodyHash = hashData; + + if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + dataForSign[i] = newTX; + } else { + dataForSign[i] = doubleHashData; + } + + } + + byte[] signFromCard = null; + if (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw || mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Raw_Validated_By_Issuer) { + ByteArrayOutputStream bs = new ByteArrayOutputStream(); + if (dataForSign.length > 10) throw new Exception("To much hashes in one transaction!"); + for (int i = 0; i < dataForSign.length; i++) { + if (i != 0 && dataForSign[0].length != dataForSign[i].length) + throw new Exception("Hashes length must be identical!"); + bs.write(dataForSign[i]); + } + signFromCard = protocol.run_SignRaw(PINStorage.getPIN2(), bs.toByteArray()).getTLV(TLV.Tag.TAG_Signature).Value; + } else { + signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), dataForSign, mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer, null, mCard.getIssuer()).getTLV(TLV.Tag.TAG_Signature).Value; + // TODO slice signFromCard to hashes.length parts + } + + LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); + + + for (int i = 0; i < unspentOutputs.size(); ++i) { + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0 + i * 64, 32 + i * 64)); + BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32 + i * 64, 64 + i * 64)); + s = CryptoUtil.toCanonicalised(s); + byte[] encodingSign = DerEncodingUtil.packSignDer(r, s, pbKey); + + unspentOutputs.get(i).scriptForBuild = encodingSign; + } + + byte[] realTX = BTCUtils.buildTXForSend(outputAddress, changeAddress, unspentOutputs, amount, change); + return realTX; + } +} diff --git a/app/src/main/java/com/tangem/wallet/ByteUtil.java b/app/src/main/java/com/tangem/domain/wallet/ByteUtil.java similarity index 94% rename from app/src/main/java/com/tangem/wallet/ByteUtil.java rename to app/src/main/java/com/tangem/domain/wallet/ByteUtil.java index d96cb2687a..db05472029 100644 --- a/app/src/main/java/com/tangem/wallet/ByteUtil.java +++ b/app/src/main/java/com/tangem/domain/wallet/ByteUtil.java @@ -1,39 +1,39 @@ -package com.tangem.wallet; - -public class ByteUtil { - - public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; - public static byte[] and(byte[] b1, byte[] b2) { - if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); - byte[] ret = new byte[b1.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = (byte) (b1[i] & b2[i]); - } - return ret; - } - - public static byte[] or(byte[] b1, byte[] b2) { - if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); - byte[] ret = new byte[b1.length]; - for (int i = 0; i < ret.length; i++) { - ret[i] = (byte) (b1[i] | b2[i]); - } - return ret; - } - - public static boolean isNullOrZeroArray(byte[] array){ - return (array == null) || (array.length == 0); - } - - public static boolean isSingleZero(byte[] array){ - return (array.length == 1 && array[0] == 0); - } - - public static int length(byte[]... bytes) { - int result = 0; - for (byte[] array : bytes) { - result += (array == null) ? 0 : array.length; - } - return result; - } +package com.tangem.domain.wallet; + +public class ByteUtil { + + public static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + public static byte[] and(byte[] b1, byte[] b2) { + if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); + byte[] ret = new byte[b1.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = (byte) (b1[i] & b2[i]); + } + return ret; + } + + public static byte[] or(byte[] b1, byte[] b2) { + if (b1.length != b2.length) throw new RuntimeException("Array sizes differ"); + byte[] ret = new byte[b1.length]; + for (int i = 0; i < ret.length; i++) { + ret[i] = (byte) (b1[i] | b2[i]); + } + return ret; + } + + public static boolean isNullOrZeroArray(byte[] array){ + return (array == null) || (array.length == 0); + } + + public static boolean isSingleZero(byte[] array){ + return (array.length == 1 && array[0] == 0); + } + + public static int length(byte[]... bytes) { + int result = 0; + for (byte[] array : bytes) { + result += (array == null) ? 0 : array.length; + } + return result; + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java new file mode 100644 index 0000000000..a6eb2e82d9 --- /dev/null +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngine.java @@ -0,0 +1,82 @@ +package com.tangem.domain.wallet; + +import android.net.Uri; + +import com.tangem.domain.cardReader.CardProtocol; + +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; + +/** + * Created by Ilia on 15.02.2018. + */ + +public abstract class CoinEngine { + + public abstract String GetNextNode(TangemCard mCard); + + public abstract int GetNextNodePort(TangemCard mCard); + + public abstract String GetNode(TangemCard mCard); + + public abstract int GetNodePort(TangemCard mCard); + + public abstract void SwitchNode(TangemCard mCard); + + public abstract boolean AwaitingConfirmation(TangemCard card); + + public abstract boolean HasBalanceInfo(TangemCard card); + + public abstract boolean IsBalanceNotZero(TangemCard card); + + public abstract boolean IsBalanceAlterNotZero(TangemCard card); + + public abstract boolean CheckAmount(TangemCard card, String amount) throws Exception; + + public abstract int GetTokenDecimals(TangemCard card); + + public abstract String GetContractAddress(TangemCard card); + + public abstract byte[] Sign(String feeValue, String amountValue, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception; + + public abstract boolean CheckUnspentTransaction(TangemCard mCard); + + public abstract Uri getShareWalletURIExplorer(TangemCard mCard); + + public abstract Long GetBalanceLong(TangemCard mCard); + + public abstract Uri getShareWalletURI(TangemCard mCard); + + public abstract String EvaluteFeeEquivalent(TangemCard mCard, String fee); + + public abstract boolean CheckAmountValie(TangemCard mCard, String amount, String fee, Long minFeeInInternalUnits); + + public abstract boolean InOutPutVisible(); + + public abstract String GetBalance(TangemCard mCard); + + public abstract String GetBalanceWithAlter(TangemCard mCard); + + public abstract String GetBalanceCurrency(TangemCard card); + + public abstract String GetFeeCurrency(); + + public abstract boolean IsNeedCheckNode(); + + public abstract String GetBalanceEquivalent(TangemCard mCard); + + public abstract String GetBalanceValue(TangemCard mCard); + + public abstract String GetAmountDescription(TangemCard mCard, String amount) throws Exception; + + public abstract String GetAmountEqualentDescriptor(TangemCard mCard, String value); + + public abstract boolean ValdateAddress(String address, TangemCard catd); + + public abstract String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException; + + public abstract String ConvertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception; + + public abstract byte[] ConvertAmountToByteArray(TangemCard mCard, String amount) throws Exception; + +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/CoinEngineFactory.java b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java similarity index 93% rename from app/src/main/java/com/tangem/wallet/CoinEngineFactory.java rename to app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java index e1d7f8ca90..0b3a62d796 100644 --- a/app/src/main/java/com/tangem/wallet/CoinEngineFactory.java +++ b/app/src/main/java/com/tangem/domain/wallet/CoinEngineFactory.java @@ -1,21 +1,21 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class CoinEngineFactory { - public static CoinEngine Create(Blockchain chain) { - if (Blockchain.BitcoinCash == chain || Blockchain.BitcoinCashTestNet == chain) { - return new BtcCashEngine(); - } else if (Blockchain.Bitcoin == chain || Blockchain.BitcoinTestNet == chain) { - return new BtcEngine(); //TODO: ВРЕМЕНГГО!!!! - } else if (Blockchain.Ethereum == chain || Blockchain.EthereumTestNet == chain) { - return new EthEngine(); - } else if (Blockchain.Token == chain) { - return new TokenEngine(); - } else { - return null; - } - } -} +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class CoinEngineFactory { + public static CoinEngine Create(Blockchain chain) { + if (Blockchain.BitcoinCash == chain || Blockchain.BitcoinCashTestNet == chain) { + return new BtcCashEngine(); + } else if (Blockchain.Bitcoin == chain || Blockchain.BitcoinTestNet == chain) { + return new BtcEngine(); //TODO: ВРЕМЕНГГО!!!! + } else if (Blockchain.Ethereum == chain || Blockchain.EthereumTestNet == chain) { + return new EthEngine(); + } else if (Blockchain.Token == chain) { + return new TokenEngine(); + } else { + return null; + } + } +} diff --git a/app/src/main/java/com/tangem/wallet/CryptoUtil.java b/app/src/main/java/com/tangem/domain/wallet/CryptoUtil.java similarity index 97% rename from app/src/main/java/com/tangem/wallet/CryptoUtil.java rename to app/src/main/java/com/tangem/domain/wallet/CryptoUtil.java index bc09335f4c..a80374a3de 100644 --- a/app/src/main/java/com/tangem/wallet/CryptoUtil.java +++ b/app/src/main/java/com/tangem/domain/wallet/CryptoUtil.java @@ -1,270 +1,270 @@ -package com.tangem.wallet; - -import android.util.Log; - -import com.tangem.domain.cardReader.Util; - -import org.spongycastle.asn1.ASN1EncodableVector; -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.DERSequence; -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.ECPublicKeySpec; -import org.spongycastle.math.ec.ECAlgorithms; -import org.spongycastle.math.ec.ECCurve; -import org.spongycastle.math.ec.ECPoint; - -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.util.Arrays; - -import static org.bitcoinj.core.ECKey.CURVE; -import static org.bitcoinj.core.ECKey.HALF_CURVE_ORDER; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class CryptoUtil { - - public static boolean checkHashSign2(byte[] pub, byte[] hash, BigInteger r, BigInteger s) - { - ECDSASigner signer = new ECDSASigner(); - - ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE); - signer.init(false, params); - return signer.verifySignature(hash, r, s); - } - - public static boolean isCanonical(BigInteger s) { - 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. - if(!isCanonical(s)) { - BigInteger canon = CURVE.getN().subtract(s); - Log.e("TX_SIGN", "non Canonical S"); - return canon; - } - - return s; - - } - - private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { - X9IntegerConverter x9 = new X9IntegerConverter(); - byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve())); - compEnc[0] = (byte) (yBit ? 0x03 : 0x02); - return CURVE.getCurve().decodePoint(compEnc); - } - - public static byte[] recoverPubBytesFromSignature(int recId, ECDSASignature_ETH sig, byte[] messageHash) { - // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) - // 1.1 Let x = r + jn - - X9ECParameters params = SECNamedCurves.getByName("secp256k1"); - ECDomainParameters CURVE2 = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); - - BigInteger n = CURVE2.getN(); // Curve order. - BigInteger i = BigInteger.valueOf((long) recId / 2); - BigInteger x = sig.r.add(i.multiply(n)); - // 1.2. Convert the integer x to an octet string X of length mlen using the conversion routine - // specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉. - // 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the - // conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then - // do another iteration of Step 1. - // - // More concisely, what these points mean is to use X as a compressed public key. - ECCurve.Fp curve = (ECCurve.Fp) CURVE2.getCurve(); - BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent about the letter it uses for the prime. - if (x.compareTo(prime) >= 0) { - // Cannot have point co-ordinates larger than this as everything takes place modulo Q. - return null; - } - // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities. - // So it's encoded in the recId. - ECPoint R = decompressKey(x, (recId & 1) == 1); - // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility). - if (!R.multiply(n).isInfinity()) - return null; - // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. - BigInteger e = new BigInteger(1, messageHash); - // 1.6. For k from 1 to 2 do the following. (loop is outside this function via iterating recId) - // 1.6.1. Compute a candidate public key as: - // Q = mi(r) * (sR - eG) - // - // Where mi(x) is the modular multiplicative inverse. We transform this into the following: - // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) - // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation - // ** is point multiplication and + is point addition (the EC group operator). - // - // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive - // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8. - BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); - BigInteger rInv = sig.r.modInverse(n); - BigInteger srInv = rInv.multiply(sig.s).mod(n); - BigInteger eInvrInv = rInv.multiply(eInv).mod(n); - ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE2.getG(), eInvrInv, R, srInv); - return q.getEncoded(/* compressed */ false); - } - - public static byte[] calcSign(byte[] priv, byte[] hash) - { - ECDSASigner signer = new ECDSASigner(); - BigInteger d = new BigInteger(priv); - ECPrivateKeyParameters params = new ECPrivateKeyParameters(d, CURVE); - signer.init(true, params); - BigInteger[] rs = signer.generateSignature(hash); - byte[] r = rs[0].toByteArray(); - byte[] s = rs[1].toByteArray(); - byte[] sign = new byte[64]; - for(int i = 0; i < 32; ++i) - { - sign[i] = r[i]; - sign[i+32] = s[i]; - } - return sign; - - } - - public static boolean isEncodingCanonical(byte[] signature) { - // See Bitcoin Core's IsCanonicalSignature, https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 - // A canonical signature exists of: <30> <02> <02> - // Where R and S are not negative (their first byte has its highest bit not set), and not - // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, - // in which case a single 0 byte is necessary and even required). - if (signature.length < 9 || signature.length > 73) - return false; - - int hashType = (signature[signature.length-1] & 0xff) & ~0x80; // mask the byte to prevent sign-extension hurting us - if (hashType < 1 || hashType > 3) - return false; - - // "wrong type" "wrong length marker" - if ((signature[0] & 0xff) != 0x30 || (signature[1] & 0xff) != signature.length-3) - return false; - - int lenR = signature[3] & 0xff; - if (5 + lenR >= signature.length || lenR == 0) - return false; - int lenS = signature[5+lenR] & 0xff; - if (lenR + lenS + 7 != signature.length || lenS == 0) - return false; - - // R value type mismatch R value negative - if (signature[4-2] != 0x02 || (signature[4] & 0x80) == 0x80) - return false; - if (lenR > 1 && signature[4] == 0x00 && (signature[4+1] & 0x80) != 0x80) - return false; // R value excessively padded - - // S value type mismatch S value negative - if (signature[6 + lenR - 2] != 0x02 || (signature[6 + lenR] & 0x80) == 0x80) - return false; - if (lenS > 1 && signature[6 + lenR] == 0x00 && (signature[6 + lenR + 1] & 0x80) != 0x80) - return false; // S value excessively padded - - return true; - } - - - public static boolean VerifySign(byte[] tlvPublicKey, byte[] data, byte[] tlvSignature) throws IOException, SignatureException, InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException { - Signature signature = Signature.getInstance("SHA256withECDSA"); - ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1"); - KeyFactory factory = KeyFactory.getInstance("EC", "SC"); - - ECPoint p1 = spec.getCurve().decodePoint(tlvPublicKey); - ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec); - - PublicKey publicKey = factory.generatePublic(keySpec); - signature.initVerify(publicKey); - signature.update(data); - - ASN1EncodableVector v = new ASN1EncodableVector(); - int size = tlvSignature.length / 2; - v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(tlvSignature, 0, size)))); - v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(tlvSignature, size, size * 2)))); - byte[] sigDer = new DERSequence(v).getEncoded(); - - return signature.verify(sigDer); - } - - private static byte[] leaderZero(byte[] s) - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - if (s[0] > 0x7f) { - baos.write((byte) 0x00); - } - for(int i = 0; i < 32; ++i) - baos.write(s[i]); - - return baos.toByteArray(); - } - public static boolean checkHashSign(byte[] pub, byte[] hash, byte[] sign) - { - byte[] rtmp = new byte[32]; - byte[] stmp = new byte[32]; - - for(int i = 0; i< 32; ++i) - { - rtmp[i] = sign[i]; - stmp[i] = sign[i+32]; - } - - leaderZero(rtmp); - byte[] r2 = leaderZero(rtmp); - byte[] s2 = leaderZero(stmp); - - BigInteger r = new BigInteger(r2); - BigInteger s = new BigInteger(s2); - ECDSASigner signer = new ECDSASigner(); - - ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE); - signer.init(false, params); - return signer.verifySignature(hash, r, s); - } - public static byte[] doubleSha256(byte[] bytes) { - try { - MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); - return sha256.digest(sha256.digest(bytes)); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } - } - - public static byte[] sha256ripemd160(byte[] publicKey) { - try { - MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); - byte[] sha256hash = sha256.digest(publicKey); - byte[] hashedPublicKey = Util.calculateRIPEMD160(sha256hash); - return hashedPublicKey; - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (NoSuchProviderException e) { - e.printStackTrace(); - } - return null; - } -} +package com.tangem.domain.wallet; + +import android.util.Log; + +import com.tangem.util.Util; + +import org.spongycastle.asn1.ASN1EncodableVector; +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERSequence; +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.ECPublicKeySpec; +import org.spongycastle.math.ec.ECAlgorithms; +import org.spongycastle.math.ec.ECCurve; +import org.spongycastle.math.ec.ECPoint; + +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.util.Arrays; + +import static org.bitcoinj.core.ECKey.CURVE; +import static org.bitcoinj.core.ECKey.HALF_CURVE_ORDER; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class CryptoUtil { + + public static boolean checkHashSign2(byte[] pub, byte[] hash, BigInteger r, BigInteger s) + { + ECDSASigner signer = new ECDSASigner(); + + ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE); + signer.init(false, params); + return signer.verifySignature(hash, r, s); + } + + public static boolean isCanonical(BigInteger s) { + 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. + if(!isCanonical(s)) { + BigInteger canon = CURVE.getN().subtract(s); + Log.e("TX_SIGN", "non Canonical S"); + return canon; + } + + return s; + + } + + private static ECPoint decompressKey(BigInteger xBN, boolean yBit) { + X9IntegerConverter x9 = new X9IntegerConverter(); + byte[] compEnc = x9.integerToBytes(xBN, 1 + x9.getByteLength(CURVE.getCurve())); + compEnc[0] = (byte) (yBit ? 0x03 : 0x02); + return CURVE.getCurve().decodePoint(compEnc); + } + + public static byte[] recoverPubBytesFromSignature(int recId, ECDSASignature_ETH sig, byte[] messageHash) { + // 1.0 For j from 0 to h (h == recId here and the loop is outside this function) + // 1.1 Let x = r + jn + + X9ECParameters params = SECNamedCurves.getByName("secp256k1"); + ECDomainParameters CURVE2 = new ECDomainParameters(params.getCurve(), params.getG(), params.getN(), params.getH()); + + BigInteger n = CURVE2.getN(); // Curve order. + BigInteger i = BigInteger.valueOf((long) recId / 2); + BigInteger x = sig.r.add(i.multiply(n)); + // 1.2. Convert the integer x to an octet string X of length mlen using the conversion routine + // specified in Section 2.3.7, where mlen = ⌈(log2 p)/8⌉ or mlen = ⌈m/8⌉. + // 1.3. Convert the octet string (16 set binary digits)||X to an elliptic curve point R using the + // conversion routine specified in Section 2.3.4. If this conversion routine outputs “invalid”, then + // do another iteration of Step 1. + // + // More concisely, what these points mean is to use X as a compressed public key. + ECCurve.Fp curve = (ECCurve.Fp) CURVE2.getCurve(); + BigInteger prime = curve.getQ(); // Bouncy Castle is not consistent about the letter it uses for the prime. + if (x.compareTo(prime) >= 0) { + // Cannot have point co-ordinates larger than this as everything takes place modulo Q. + return null; + } + // Compressed keys require you to know an extra bit of data about the y-coord as there are two possibilities. + // So it's encoded in the recId. + ECPoint R = decompressKey(x, (recId & 1) == 1); + // 1.4. If nR != point at infinity, then do another iteration of Step 1 (callers responsibility). + if (!R.multiply(n).isInfinity()) + return null; + // 1.5. Compute e from M using Steps 2 and 3 of ECDSA signature verification. + BigInteger e = new BigInteger(1, messageHash); + // 1.6. For k from 1 to 2 do the following. (loop is outside this function via iterating recId) + // 1.6.1. Compute a candidate public key as: + // Q = mi(r) * (sR - eG) + // + // Where mi(x) is the modular multiplicative inverse. We transform this into the following: + // Q = (mi(r) * s ** R) + (mi(r) * -e ** G) + // Where -e is the modular additive inverse of e, that is z such that z + e = 0 (mod n). In the above equation + // ** is point multiplication and + is point addition (the EC group operator). + // + // We can find the additive inverse by subtracting e from zero then taking the mod. For example the additive + // inverse of 3 modulo 11 is 8 because 3 + 8 mod 11 = 0, and -3 mod 11 = 8. + BigInteger eInv = BigInteger.ZERO.subtract(e).mod(n); + BigInteger rInv = sig.r.modInverse(n); + BigInteger srInv = rInv.multiply(sig.s).mod(n); + BigInteger eInvrInv = rInv.multiply(eInv).mod(n); + ECPoint.Fp q = (ECPoint.Fp) ECAlgorithms.sumOfTwoMultiplies(CURVE2.getG(), eInvrInv, R, srInv); + return q.getEncoded(/* compressed */ false); + } + + public static byte[] calcSign(byte[] priv, byte[] hash) + { + ECDSASigner signer = new ECDSASigner(); + BigInteger d = new BigInteger(priv); + ECPrivateKeyParameters params = new ECPrivateKeyParameters(d, CURVE); + signer.init(true, params); + BigInteger[] rs = signer.generateSignature(hash); + byte[] r = rs[0].toByteArray(); + byte[] s = rs[1].toByteArray(); + byte[] sign = new byte[64]; + for(int i = 0; i < 32; ++i) + { + sign[i] = r[i]; + sign[i+32] = s[i]; + } + return sign; + + } + + public static boolean isEncodingCanonical(byte[] signature) { + // See Bitcoin Core's IsCanonicalSignature, https://bitcointalk.org/index.php?topic=8392.msg127623#msg127623 + // A canonical signature exists of: <30> <02> <02> + // Where R and S are not negative (their first byte has its highest bit not set), and not + // excessively padded (do not start with a 0 byte, unless an otherwise negative number follows, + // in which case a single 0 byte is necessary and even required). + if (signature.length < 9 || signature.length > 73) + return false; + + int hashType = (signature[signature.length-1] & 0xff) & ~0x80; // mask the byte to prevent sign-extension hurting us + if (hashType < 1 || hashType > 3) + return false; + + // "wrong type" "wrong length marker" + if ((signature[0] & 0xff) != 0x30 || (signature[1] & 0xff) != signature.length-3) + return false; + + int lenR = signature[3] & 0xff; + if (5 + lenR >= signature.length || lenR == 0) + return false; + int lenS = signature[5+lenR] & 0xff; + if (lenR + lenS + 7 != signature.length || lenS == 0) + return false; + + // R value type mismatch R value negative + if (signature[4-2] != 0x02 || (signature[4] & 0x80) == 0x80) + return false; + if (lenR > 1 && signature[4] == 0x00 && (signature[4+1] & 0x80) != 0x80) + return false; // R value excessively padded + + // S value type mismatch S value negative + if (signature[6 + lenR - 2] != 0x02 || (signature[6 + lenR] & 0x80) == 0x80) + return false; + if (lenS > 1 && signature[6 + lenR] == 0x00 && (signature[6 + lenR + 1] & 0x80) != 0x80) + return false; // S value excessively padded + + return true; + } + + + public static boolean VerifySign(byte[] tlvPublicKey, byte[] data, byte[] tlvSignature) throws IOException, SignatureException, InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException, NoSuchProviderException { + Signature signature = Signature.getInstance("SHA256withECDSA"); + ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1"); + KeyFactory factory = KeyFactory.getInstance("EC", "SC"); + + ECPoint p1 = spec.getCurve().decodePoint(tlvPublicKey); + ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec); + + PublicKey publicKey = factory.generatePublic(keySpec); + signature.initVerify(publicKey); + signature.update(data); + + ASN1EncodableVector v = new ASN1EncodableVector(); + int size = tlvSignature.length / 2; + v.add(/*r*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(tlvSignature, 0, size)))); + v.add(/*s*/new ASN1Integer(new BigInteger(1, Arrays.copyOfRange(tlvSignature, size, size * 2)))); + byte[] sigDer = new DERSequence(v).getEncoded(); + + return signature.verify(sigDer); + } + + private static byte[] leaderZero(byte[] s) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + if (s[0] > 0x7f) { + baos.write((byte) 0x00); + } + for(int i = 0; i < 32; ++i) + baos.write(s[i]); + + return baos.toByteArray(); + } + public static boolean checkHashSign(byte[] pub, byte[] hash, byte[] sign) + { + byte[] rtmp = new byte[32]; + byte[] stmp = new byte[32]; + + for(int i = 0; i< 32; ++i) + { + rtmp[i] = sign[i]; + stmp[i] = sign[i+32]; + } + + leaderZero(rtmp); + byte[] r2 = leaderZero(rtmp); + byte[] s2 = leaderZero(stmp); + + BigInteger r = new BigInteger(r2); + BigInteger s = new BigInteger(s2); + ECDSASigner signer = new ECDSASigner(); + + ECPublicKeyParameters params = new ECPublicKeyParameters(CURVE.getCurve().decodePoint(pub), CURVE); + signer.init(false, params); + return signer.verifySignature(hash, r, s); + } + public static byte[] doubleSha256(byte[] bytes) { + try { + MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); + return sha256.digest(sha256.digest(bytes)); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + public static byte[] sha256ripemd160(byte[] publicKey) { + try { + MessageDigest sha256 = MessageDigest.getInstance("SHA-256"); + byte[] sha256hash = sha256.digest(publicKey); + byte[] hashedPublicKey = Util.calculateRIPEMD160(sha256hash); + return hashedPublicKey; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (NoSuchProviderException e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/app/src/main/java/com/tangem/wallet/DerEncodingUtil.java b/app/src/main/java/com/tangem/domain/wallet/DerEncodingUtil.java similarity index 95% rename from app/src/main/java/com/tangem/wallet/DerEncodingUtil.java rename to app/src/main/java/com/tangem/domain/wallet/DerEncodingUtil.java index 7584345701..9cdf0d824b 100644 --- a/app/src/main/java/com/tangem/wallet/DerEncodingUtil.java +++ b/app/src/main/java/com/tangem/domain/wallet/DerEncodingUtil.java @@ -1,130 +1,132 @@ -package com.tangem.wallet; - -import org.spongycastle.asn1.ASN1Integer; -import org.spongycastle.asn1.DERSequenceGenerator; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigInteger; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class DerEncodingUtil { - - public static byte[] PackInteger(byte[] s) - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write((byte)0x02); - - byte length = (byte)s.length; - if (s[0] > 0x7f) { - baos.write((byte)(length+1)); - baos.write((byte) 0x00); - } - else { - baos.write((byte)length); - } - - for(int i = 0; i < length; ++i) - baos.write(s[i]); - - return baos.toByteArray(); - } - - public static byte[] packSignDer(BigInteger r, BigInteger s, byte[] pubKey) throws IOException - { - byte[] signDer = DerEncoding(r, s); - BitcoinOutputStream packKey = new BitcoinOutputStream(); - - packKey.write((byte)0x41); - packKey.write(pubKey); - - byte[] keyArray = packKey.toByteArray(); - - BitcoinOutputStream result = new BitcoinOutputStream(); - result.write((byte)(signDer.length+1)); - result.write(signDer); - result.write((byte)0x1); - - result.write(keyArray); - - return result.toByteArray(); - - } - - public static byte[] packSignDerBitcoinCash(BigInteger r, BigInteger s, byte[] pubKey) throws IOException - { - byte[] signDer = DerEncoding(r, s); - BitcoinOutputStream packKey = new BitcoinOutputStream(); - - packKey.write((byte)0x21); //compress key - packKey.write(pubKey); - - byte[] keyArray = packKey.toByteArray(); - - BitcoinOutputStream result = new BitcoinOutputStream(); - result.write((byte)(signDer.length+1)); - result.write(signDer); - result.write((byte)0x41); - - result.write(keyArray); - - return result.toByteArray(); - - } - - - public static byte[] DerEncoding(BigInteger r, BigInteger s) throws IOException { - ByteArrayOutputStream bos = new ByteArrayOutputStream(72); - DERSequenceGenerator seq = new DERSequenceGenerator(bos); - seq.addObject(new ASN1Integer(r)); - seq.addObject(new ASN1Integer(s)); - seq.close(); - return bos.toByteArray(); - } - - public static byte[] DerEncoding(byte[] sign) - { - byte[] r = sign; - byte[] s = new byte[32]; - for(int i =0; i < 32; ++i) - { - s[i] = sign[i+32]; - } - - byte[] newR = PackInteger(r); - byte[] newS = PackInteger(s); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - baos.write((byte)(newR.length+newS.length+2)); - baos.write((byte)newR.length); - baos.write(newR, 0, newR.length); - baos.write((byte)newS.length); - baos.write(newS, 0, newS.length); - - return baos.toByteArray(); - } - - public static byte[] DerEncodingBI(BigInteger[] sign) - { - byte[] r = sign[0].toByteArray(); - byte[] s = sign[1].toByteArray(); - - byte[] newR = PackInteger(r); - byte[] newS = PackInteger(s); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - baos.write((byte)(newR.length+newS.length+2)); - - baos.write((byte)newR.length); - baos.write(newR, 0, newR.length); - - baos.write((byte)newS.length); - baos.write(newS, 0, newS.length); - - return baos.toByteArray(); - } -} +package com.tangem.domain.wallet; + +import com.tangem.domain.wallet.BitcoinOutputStream; + +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.DERSequenceGenerator; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class DerEncodingUtil { + + public static byte[] PackInteger(byte[] s) + { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write((byte)0x02); + + byte length = (byte)s.length; + if (s[0] > 0x7f) { + baos.write((byte)(length+1)); + baos.write((byte) 0x00); + } + else { + baos.write((byte)length); + } + + for(int i = 0; i < length; ++i) + baos.write(s[i]); + + return baos.toByteArray(); + } + + public static byte[] packSignDer(BigInteger r, BigInteger s, byte[] pubKey) throws IOException + { + byte[] signDer = DerEncoding(r, s); + BitcoinOutputStream packKey = new BitcoinOutputStream(); + + packKey.write((byte)0x41); + packKey.write(pubKey); + + byte[] keyArray = packKey.toByteArray(); + + BitcoinOutputStream result = new BitcoinOutputStream(); + result.write((byte)(signDer.length+1)); + result.write(signDer); + result.write((byte)0x1); + + result.write(keyArray); + + return result.toByteArray(); + + } + + public static byte[] packSignDerBitcoinCash(BigInteger r, BigInteger s, byte[] pubKey) throws IOException + { + byte[] signDer = DerEncoding(r, s); + BitcoinOutputStream packKey = new BitcoinOutputStream(); + + packKey.write((byte)0x21); //compress key + packKey.write(pubKey); + + byte[] keyArray = packKey.toByteArray(); + + BitcoinOutputStream result = new BitcoinOutputStream(); + result.write((byte)(signDer.length+1)); + result.write(signDer); + result.write((byte)0x41); + + result.write(keyArray); + + return result.toByteArray(); + + } + + + public static byte[] DerEncoding(BigInteger r, BigInteger s) throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(72); + DERSequenceGenerator seq = new DERSequenceGenerator(bos); + seq.addObject(new ASN1Integer(r)); + seq.addObject(new ASN1Integer(s)); + seq.close(); + return bos.toByteArray(); + } + + public static byte[] DerEncoding(byte[] sign) + { + byte[] r = sign; + byte[] s = new byte[32]; + for(int i =0; i < 32; ++i) + { + s[i] = sign[i+32]; + } + + byte[] newR = PackInteger(r); + byte[] newS = PackInteger(s); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write((byte)(newR.length+newS.length+2)); + baos.write((byte)newR.length); + baos.write(newR, 0, newR.length); + baos.write((byte)newS.length); + baos.write(newS, 0, newS.length); + + return baos.toByteArray(); + } + + public static byte[] DerEncodingBI(BigInteger[] sign) + { + byte[] r = sign[0].toByteArray(); + byte[] s = sign[1].toByteArray(); + + byte[] newR = PackInteger(r); + byte[] newS = PackInteger(s); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + baos.write((byte)(newR.length+newS.length+2)); + + baos.write((byte)newR.length); + baos.write(newR, 0, newR.length); + + baos.write((byte)newS.length); + baos.write(newS, 0, newS.length); + + return baos.toByteArray(); + } +} diff --git a/app/src/main/java/com/tangem/wallet/DeviceNFCAntennaLocation.java b/app/src/main/java/com/tangem/domain/wallet/DeviceNFCAntennaLocation.java similarity index 93% rename from app/src/main/java/com/tangem/wallet/DeviceNFCAntennaLocation.java rename to app/src/main/java/com/tangem/domain/wallet/DeviceNFCAntennaLocation.java index c7d5070437..88e3aecd52 100644 --- a/app/src/main/java/com/tangem/wallet/DeviceNFCAntennaLocation.java +++ b/app/src/main/java/com/tangem/domain/wallet/DeviceNFCAntennaLocation.java @@ -1,25 +1,25 @@ -package com.tangem.wallet; - -import android.os.Build; - -public class DeviceNFCAntennaLocation { - - public float X; - public float Y; - public boolean OnBackSide; - public float Strength; - - public void getAntennaLocation() { - String device = DeviceName.getDeviceName(); - String model = Build.DEVICE; - this.X = 0.5f; - this.Y = 0.33f; - this.OnBackSide = true; - this.Strength = 1.0f; - // Samsung -// if (model.contains("Samsung")) {this.Y = 0.33; this.Strength = 0.5; } -// if (model.contains("Sony")) {this.Y = 0.33; this.Strength = 0.5; } -// if (device == "Galaxy J5") {this.Y = 0.4; this.Strength = 0.5; } - if (device == "P10 lite") {this.Y = 0.03f; this.Strength = 0.8f; } - } -} +package com.tangem.domain.wallet; + +import android.os.Build; + +public class DeviceNFCAntennaLocation { + + public float X; + public float Y; + public boolean OnBackSide; + public float Strength; + + public void getAntennaLocation() { + String device = DeviceName.getDeviceName(); + String model = Build.DEVICE; + this.X = 0.5f; + this.Y = 0.33f; + this.OnBackSide = true; + this.Strength = 1.0f; + // Samsung +// if (model.contains("Samsung")) {this.Y = 0.33; this.Strength = 0.5; } +// if (model.contains("Sony")) {this.Y = 0.33; this.Strength = 0.5; } +// if (device == "Galaxy J5") {this.Y = 0.4; this.Strength = 0.5; } + if (device == "P10 lite") {this.Y = 0.03f; this.Strength = 0.8f; } + } +} diff --git a/app/src/main/java/com/tangem/wallet/DeviceName.java b/app/src/main/java/com/tangem/domain/wallet/DeviceName.java similarity index 97% rename from app/src/main/java/com/tangem/wallet/DeviceName.java rename to app/src/main/java/com/tangem/domain/wallet/DeviceName.java index 15bf9c1456..ef9ecf81d1 100644 --- a/app/src/main/java/com/tangem/wallet/DeviceName.java +++ b/app/src/main/java/com/tangem/domain/wallet/DeviceName.java @@ -1,2091 +1,2091 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 20.04.2018. - */ -/* - * Copyright (C) 2017 Jared Rummler - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - import android.Manifest; - import android.content.Context; - import android.content.SharedPreferences; - import android.content.pm.PackageManager; - import android.net.ConnectivityManager; - import android.net.NetworkInfo; - import android.os.Build; - import android.os.Handler; - import android.os.Looper; - import android.support.annotation.WorkerThread; - import android.text.TextUtils; - import java.io.BufferedReader; - import java.io.IOException; - import java.io.InputStreamReader; - import java.net.HttpURLConnection; - import java.net.URL; - import java.util.Locale; - import org.json.JSONArray; - import org.json.JSONException; - import org.json.JSONObject; - -// @formatter:off -/** - *

Get the consumer friendly name of an Android device.

- * - *

On many popular devices the market name of the device is not available. For example, on the - * Samsung Galaxy S6 the value of {@link Build#MODEL} could be "SM-G920F", "SM-G920I", "SM-G920W8", - * etc.

- * - *

See the usages below to get the consumer friends name of a device:

- * - *

Get the name of the current device:

- * - *
- * String deviceName = DeviceName.getDeviceName();
- * 
- * - *

The above code will get the correct device name for the top 600 Android devices. If the - * device is unrecognized, then Build.MODEL is returned.

- * - *

Get the name of a device using the device's codename:

- * - *
- * // Retruns "Moto X Style"
- * DeviceName.getDeviceName("clark", "Unknown device");
- * 
- * - *

Get information about the device:

- * - *
- * DeviceName.with(context).request(new DeviceName.Callback() {
- *
- *   @Override public void onFinished(DeviceName.DeviceInfo info, Exception error) {
- *     String manufacturer = info.manufacturer;  // "Samsung"
- *     String name = info.marketName;            // "Galaxy S6 Edge"
- *     String model = info.model;                // "SM-G925I"
- *     String codename = info.codename;          // "zerolte"
- *     String deviceName = info.getName();       // "Galaxy S6 Edge"
- *     // FYI: We are on the UI thread.
- *   }
- * });
- * 
- * - *

The above code loads JSON from a generated list of device names based on Google's maintained - * list. It will be up-to-date with Google's supported device list so that you will get the correct - * name for new or unknown devices. This supports over 10,000 devices.

- * - *

This will only make a network call once. The value is saved to SharedPreferences for future - * calls.

- */ - -public class DeviceName { - - // @formatter:on - - // JSON which is derived from Google's PDF document which contains all devices on Google Play. - // To get the URL to the JSON file which contains information about the device name: - // String url = String.format(DEVICE_JSON_URL, Build.DEVICE); - private static final String DEVICE_JSON_URL = - "https://raw.githubusercontent.com/jaredrummler/AndroidDeviceNames/master/json/devices/%s.json"; - - // Preference filename for storing device info so we don't need to download it again. - private static final String SHARED_PREF_NAME = "device_names"; - - /** - * Create a new request to get information about a device. - * - * @param context - * the application context - * @return a new Request instance. - */ - public static Request with(Context context) { - return new Request(context.getApplicationContext()); - } - - /** - * Get the consumer friendly name of the device. - * - * @return the market name of the current device. - * @see #getDeviceName(String, String) - */ - public static String getDeviceName() { - return getDeviceName(Build.DEVICE, Build.MODEL, capitalize(Build.MODEL)); - } - - /** - * Get the consumer friendly name of a device. - * - * @param codename - * the value of the system property "ro.product.device" ({@link Build#DEVICE}) - * or - * the value of the system property "ro.product.model" ({@link Build#MODEL}) - * @param fallback - * the fallback name if the device is unknown. Usually the value of the system property - * "ro.product.model" ({@link Build#MODEL}) - * @return the market name of a device or {@code fallback} if the device is unknown. - */ - public static String getDeviceName(String codename, String fallback) { - return getDeviceName(codename, codename, fallback); - } - - /** - * Get the consumer friendly name of a device. - * - * @param codename - * the value of the system property "ro.product.device" ({@link Build#DEVICE}). - * @param model - * the value of the system property "ro.product.model" ({@link Build#MODEL}). - * @param fallback - * the fallback name if the device is unknown. Usually the value of the system property - * "ro.product.model" ({@link Build#MODEL}) - * @return the market name of a device or {@code fallback} if the device is unknown. - */ - public static String getDeviceName(String codename, String model, String fallback) { - // ---------------------------------------------------------------------------- - // Acer - if ((codename != null && codename.equals("acer_S57")) - || (model != null && model.equals("S57"))) { - return "Liquid Jade Z"; - } - if ((codename != null && codename.equals("acer_t08")) - || (model != null && model.equals("T08"))) { - return "Liquid Zest Plus"; - } - // ---------------------------------------------------------------------------- - // Asus - if ((codename != null && (codename.equals("grouper") - || codename.equals("tilapia")))) { - return "Nexus 7 (2012)"; - } - if ((codename != null && (codename.equals("deb") - || codename.equals("flo")))) { - return "Nexus 7 (2013)"; - } - // ---------------------------------------------------------------------------- - // Google - if ((codename != null && codename.equals("sailfish"))) { - return "Pixel"; - } - if ((codename != null && codename.equals("walleye"))) { - return "Pixel 2"; - } - if ((codename != null && codename.equals("taimen"))) { - return "Pixel 2 XL"; - } - if ((codename != null && codename.equals("dragon"))) { - return "Pixel C"; - } - if ((codename != null && codename.equals("marlin"))) { - return "Pixel XL"; - } - // ---------------------------------------------------------------------------- - // HTC - if ((codename != null && codename.equals("flounder"))) { - return "Nexus 9"; - } - // ---------------------------------------------------------------------------- - // Huawei - if ((codename != null && (codename.equals("HWBND-H"))) - || (model != null && (model.equals("BND-L21") - || model.equals("BND-L24")))) { - return "Honor 7X"; - } - if (model != null && model.contains("WAS-LX")) { - return "P10 lite"; - } - if ((codename != null && codename.equals("HWBKL")) - || (model != null && model.equals("BKL-L09"))) { - return "Honor View 10"; - } - if ((codename != null && (codename.equals("HWALP"))) - || (model != null && (model.equals("ALP-AL00") - || model.equals("ALP-L09") - || model.equals("ALP-L29") - || model.equals("ALP-TL00")))) { - return "Mate 10"; - } - if ((codename != null && (codename.equals("HWMHA"))) - || (model != null && (model.equals("MHA-AL00") - || model.equals("MHA-L09") - || model.equals("MHA-L29") - || model.equals("MHA-TL00")))) { - return "Mate 9"; - } - if ((codename != null && codename.equals("angler"))) { - return "Nexus 6P"; - } - // ---------------------------------------------------------------------------- - // LGE - if ((codename != null && (codename.equals("g2"))) - || (model != null && (model.equals("LG-D800") - || model.equals("LG-D801") - || model.equals("LG-D802") - || model.equals("LG-D802T") - || model.equals("LG-D802TR") - || model.equals("LG-D803") - || model.equals("LG-D805") - || model.equals("LG-D806") - || model.equals("LG-F320K") - || model.equals("LG-F320L") - || model.equals("LG-F320S") - || model.equals("LG-LS980") - || model.equals("VS980 4G")))) { - return "LG G2"; - } - if ((codename != null && (codename.equals("g3"))) - || (model != null && (model.equals("AS985") - || model.equals("LG-AS990") - || model.equals("LG-D850") - || model.equals("LG-D851") - || model.equals("LG-D852") - || model.equals("LG-D852G") - || model.equals("LG-D855") - || model.equals("LG-D856") - || model.equals("LG-D857") - || model.equals("LG-D858") - || model.equals("LG-D858HK") - || model.equals("LG-D859") - || model.equals("LG-F400K") - || model.equals("LG-F400L") - || model.equals("LG-F400S") - || model.equals("LGL24") - || model.equals("LGLS990") - || model.equals("LGUS990") - || model.equals("LGV31") - || model.equals("VS985 4G")))) { - return "LG G3"; - } - if ((codename != null && (codename.equals("p1"))) - || (model != null && (model.equals("AS986") - || model.equals("LG-AS811") - || model.equals("LG-AS991") - || model.equals("LG-F500K") - || model.equals("LG-F500L") - || model.equals("LG-F500S") - || model.equals("LG-H810") - || model.equals("LG-H811") - || model.equals("LG-H812") - || model.equals("LG-H815") - || model.equals("LG-H818") - || model.equals("LG-H819") - || model.equals("LGLS991") - || model.equals("LGUS991") - || model.equals("LGV32") - || model.equals("VS986")))) { - return "LG G4"; - } - if ((codename != null && (codename.equals("h1"))) - || (model != null && (model.equals("LG-F700K") - || model.equals("LG-F700L") - || model.equals("LG-F700S") - || model.equals("LG-H820") - || model.equals("LG-H820PR") - || model.equals("LG-H830") - || model.equals("LG-H831") - || model.equals("LG-H850") - || model.equals("LG-H858") - || model.equals("LG-H860") - || model.equals("LG-H868") - || model.equals("LGAS992") - || model.equals("LGLS992") - || model.equals("LGUS992") - || model.equals("RS988") - || model.equals("VS987")))) { - return "LG G5"; - } - if ((codename != null && (codename.equals("lucye"))) - || (model != null && (model.equals("LG-AS993") - || model.equals("LG-H870") - || model.equals("LG-H870AR") - || model.equals("LG-H870DS") - || model.equals("LG-H870I") - || model.equals("LG-H870S") - || model.equals("LG-H871") - || model.equals("LG-H872") - || model.equals("LG-H872PR") - || model.equals("LG-H873") - || model.equals("LG-LS993") - || model.equals("LGM-G600K") - || model.equals("LGM-G600L") - || model.equals("LGM-G600S") - || model.equals("LGUS997") - || model.equals("VS988")))) { - return "LG G6"; - } - if ((codename != null && codename.equals("mako"))) { - return "Nexus 4"; - } - if ((codename != null && codename.equals("hammerhead"))) { - return "Nexus 5"; - } - if ((codename != null && codename.equals("bullhead"))) { - return "Nexus 5X"; - } - // ---------------------------------------------------------------------------- - // Motorola - if ((codename != null && codename.equals("shamu"))) { - return "Nexus 6"; - } - // ---------------------------------------------------------------------------- - // OnePlus - if ((codename != null && codename.equals("OnePlus3")) - || (model != null && model.equals("ONEPLUS A3000"))) { - return "OnePlus3"; - } - if ((codename != null && codename.equals("OnePlus3T")) - || (model != null && model.equals("ONEPLUS A3000"))) { - return "OnePlus3T"; - } - if ((codename != null && codename.equals("OnePlus5")) - || (model != null && model.equals("ONEPLUS A5000"))) { - return "OnePlus5"; - } - if ((codename != null && codename.equals("OnePlus5T")) - || (model != null && model.equals("ONEPLUS A5010"))) { - return "OnePlus5T"; - } - // ---------------------------------------------------------------------------- - // Samsung - if ((codename != null && (codename.equals("a53g") - || codename.equals("a5lte") - || codename.equals("a5ltechn") - || codename.equals("a5ltectc") - || codename.equals("a5ltezh") - || codename.equals("a5ltezt") - || codename.equals("a5ulte") - || codename.equals("a5ultebmc") - || codename.equals("a5ultektt") - || codename.equals("a5ultelgt") - || codename.equals("a5ulteskt"))) - || (model != null && (model.equals("SM-A5000") - || model.equals("SM-A5009") - || model.equals("SM-A500F") - || model.equals("SM-A500F1") - || model.equals("SM-A500FU") - || model.equals("SM-A500G") - || model.equals("SM-A500H") - || model.equals("SM-A500K") - || model.equals("SM-A500L") - || model.equals("SM-A500M") - || model.equals("SM-A500S") - || model.equals("SM-A500W") - || model.equals("SM-A500X") - || model.equals("SM-A500XZ") - || model.equals("SM-A500Y") - || model.equals("SM-A500YZ")))) { - return "Galaxy A5"; - } - if ((codename != null && (codename.equals("vivaltods5m"))) - || (model != null && (model.equals("SM-G313HU") - || model.equals("SM-G313HY") - || model.equals("SM-G313M") - || model.equals("SM-G313MY")))) { - return "Galaxy Ace 4"; - } - if ((codename != null && (codename.equals("GT-S6352") - || codename.equals("GT-S6802") - || codename.equals("GT-S6802B") - || codename.equals("SCH-I579") - || codename.equals("SCH-I589") - || codename.equals("SCH-i579") - || codename.equals("SCH-i589"))) - || (model != null && (model.equals("GT-S6352") - || model.equals("GT-S6802") - || model.equals("GT-S6802B") - || model.equals("SCH-I589") - || model.equals("SCH-i579") - || model.equals("SCH-i589")))) { - return "Galaxy Ace Duos"; - } - if ((codename != null && (codename.equals("GT-S7500") - || codename.equals("GT-S7500L") - || codename.equals("GT-S7500T") - || codename.equals("GT-S7500W") - || codename.equals("GT-S7508"))) - || (model != null && (model.equals("GT-S7500") - || model.equals("GT-S7500L") - || model.equals("GT-S7500T") - || model.equals("GT-S7500W") - || model.equals("GT-S7508")))) { - return "Galaxy Ace Plus"; - } - if ((codename != null && (codename.equals("heat3gtfnvzw") - || codename.equals("heatnfc3g") - || codename.equals("heatqlte"))) - || (model != null && (model.equals("SM-G310HN") - || model.equals("SM-G357FZ") - || model.equals("SM-S765C") - || model.equals("SM-S766C")))) { - return "Galaxy Ace Style"; - } - if ((codename != null && (codename.equals("vivalto3g") - || codename.equals("vivalto3mve3g") - || codename.equals("vivalto5mve3g") - || codename.equals("vivaltolte") - || codename.equals("vivaltonfc3g"))) - || (model != null && (model.equals("SM-G313F") - || model.equals("SM-G313HN") - || model.equals("SM-G313ML") - || model.equals("SM-G313MU") - || model.equals("SM-G316H") - || model.equals("SM-G316HU") - || model.equals("SM-G316M") - || model.equals("SM-G316MY")))) { - return "Galaxy Ace4"; - } - if ((codename != null && (codename.equals("core33g") - || codename.equals("coreprimelte") - || codename.equals("coreprimelteaio") - || codename.equals("coreprimeltelra") - || codename.equals("coreprimeltespr") - || codename.equals("coreprimeltetfnvzw") - || codename.equals("coreprimeltevzw") - || codename.equals("coreprimeve3g") - || codename.equals("coreprimevelte") - || codename.equals("cprimeltemtr") - || codename.equals("cprimeltetmo") - || codename.equals("rossalte") - || codename.equals("rossaltectc") - || codename.equals("rossaltexsa"))) - || (model != null && (model.equals("SAMSUNG-SM-G360AZ") - || model.equals("SM-G3606") - || model.equals("SM-G3608") - || model.equals("SM-G3609") - || model.equals("SM-G360F") - || model.equals("SM-G360FY") - || model.equals("SM-G360GY") - || model.equals("SM-G360H") - || model.equals("SM-G360HU") - || model.equals("SM-G360M") - || model.equals("SM-G360P") - || model.equals("SM-G360R6") - || model.equals("SM-G360T") - || model.equals("SM-G360T1") - || model.equals("SM-G360V") - || model.equals("SM-G361F") - || model.equals("SM-G361H") - || model.equals("SM-G361HU") - || model.equals("SM-G361M") - || model.equals("SM-S820L")))) { - return "Galaxy Core Prime"; - } - if ((codename != null && (codename.equals("kanas") - || codename.equals("kanas3g") - || codename.equals("kanas3gcmcc") - || codename.equals("kanas3gctc") - || codename.equals("kanas3gnfc"))) - || (model != null && (model.equals("SM-G3556D") - || model.equals("SM-G3558") - || model.equals("SM-G3559") - || model.equals("SM-G355H") - || model.equals("SM-G355HN") - || model.equals("SM-G355HQ") - || model.equals("SM-G355M")))) { - return "Galaxy Core2"; - } - if ((codename != null && (codename.equals("e53g") - || codename.equals("e5lte") - || codename.equals("e5ltetfnvzw") - || codename.equals("e5ltetw"))) - || (model != null && (model.equals("SM-E500F") - || model.equals("SM-E500H") - || model.equals("SM-E500M") - || model.equals("SM-E500YZ") - || model.equals("SM-S978L")))) { - return "Galaxy E5"; - } - if ((codename != null && (codename.equals("e73g") - || codename.equals("e7lte") - || codename.equals("e7ltechn") - || codename.equals("e7ltectc") - || codename.equals("e7ltehktw"))) - || (model != null && (model.equals("SM-E7000") - || model.equals("SM-E7009") - || model.equals("SM-E700F") - || model.equals("SM-E700H") - || model.equals("SM-E700M")))) { - return "Galaxy E7"; - } - if ((codename != null && (codename.equals("SCH-I629") - || codename.equals("nevis") - || codename.equals("nevis3g") - || codename.equals("nevis3gcmcc") - || codename.equals("nevisds") - || codename.equals("nevisnvess") - || codename.equals("nevisp") - || codename.equals("nevisvess") - || codename.equals("nevisw"))) - || (model != null && (model.equals("GT-S6790") - || model.equals("GT-S6790E") - || model.equals("GT-S6790L") - || model.equals("GT-S6790N") - || model.equals("GT-S6810") - || model.equals("GT-S6810B") - || model.equals("GT-S6810E") - || model.equals("GT-S6810L") - || model.equals("GT-S6810M") - || model.equals("GT-S6810P") - || model.equals("GT-S6812") - || model.equals("GT-S6812B") - || model.equals("GT-S6812C") - || model.equals("GT-S6812i") - || model.equals("GT-S6818") - || model.equals("GT-S6818V") - || model.equals("SCH-I629")))) { - return "Galaxy Fame"; - } - if ((codename != null && codename.equals("grandprimelteatt")) - || (model != null && model.equals("SAMSUNG-SM-G530A"))) { - return "Galaxy Go Prime"; - } - if ((codename != null && (codename.equals("baffinlite") - || codename.equals("baffinlitedtv") - || codename.equals("baffinq3g"))) - || (model != null && (model.equals("GT-I9060") - || model.equals("GT-I9060L") - || model.equals("GT-I9063T") - || model.equals("GT-I9082C") - || model.equals("GT-I9168") - || model.equals("GT-I9168I")))) { - return "Galaxy Grand Neo"; - } - if ((codename != null && (codename.equals("fortuna3g") - || codename.equals("fortuna3gdtv") - || codename.equals("fortunalte") - || codename.equals("fortunaltectc") - || codename.equals("fortunaltezh") - || codename.equals("fortunaltezt") - || codename.equals("fortunave3g") - || codename.equals("gprimelteacg") - || codename.equals("gprimeltecan") - || codename.equals("gprimeltemtr") - || codename.equals("gprimeltespr") - || codename.equals("gprimeltetfnvzw") - || codename.equals("gprimeltetmo") - || codename.equals("gprimelteusc") - || codename.equals("grandprimelte") - || codename.equals("grandprimelteaio") - || codename.equals("grandprimeve3g") - || codename.equals("grandprimeve3gdtv") - || codename.equals("grandprimevelte") - || codename.equals("grandprimevelteltn") - || codename.equals("grandprimeveltezt"))) - || (model != null && (model.equals("SAMSUNG-SM-G530AZ") - || model.equals("SM-G5306W") - || model.equals("SM-G5308W") - || model.equals("SM-G5309W") - || model.equals("SM-G530BT") - || model.equals("SM-G530F") - || model.equals("SM-G530FZ") - || model.equals("SM-G530H") - || model.equals("SM-G530M") - || model.equals("SM-G530MU") - || model.equals("SM-G530P") - || model.equals("SM-G530R4") - || model.equals("SM-G530R7") - || model.equals("SM-G530T") - || model.equals("SM-G530T1") - || model.equals("SM-G530W") - || model.equals("SM-G530Y") - || model.equals("SM-G531BT") - || model.equals("SM-G531F") - || model.equals("SM-G531H") - || model.equals("SM-G531M") - || model.equals("SM-G531Y") - || model.equals("SM-S920L") - || model.equals("gprimelteacg")))) { - return "Galaxy Grand Prime"; - } - if ((codename != null && (codename.equals("ms013g") - || codename.equals("ms013gdtv") - || codename.equals("ms013gss") - || codename.equals("ms01lte") - || codename.equals("ms01ltektt") - || codename.equals("ms01ltelgt") - || codename.equals("ms01lteskt"))) - || (model != null && (model.equals("SM-G710") - || model.equals("SM-G7102") - || model.equals("SM-G7102T") - || model.equals("SM-G7105") - || model.equals("SM-G7105H") - || model.equals("SM-G7105L") - || model.equals("SM-G7106") - || model.equals("SM-G7108") - || model.equals("SM-G7109") - || model.equals("SM-G710K") - || model.equals("SM-G710L") - || model.equals("SM-G710S")))) { - return "Galaxy Grand2"; - } - if ((codename != null && (codename.equals("j13g") - || codename.equals("j13gtfnvzw") - || codename.equals("j1lte") - || codename.equals("j1nlte") - || codename.equals("j1qltevzw") - || codename.equals("j1xlte") - || codename.equals("j1xlteaio") - || codename.equals("j1xlteatt") - || codename.equals("j1xltecan") - || codename.equals("j1xqltespr") - || codename.equals("j1xqltetfnvzw"))) - || (model != null && (model.equals("SAMSUNG-SM-J120A") - || model.equals("SAMSUNG-SM-J120AZ") - || model.equals("SM-J100F") - || model.equals("SM-J100FN") - || model.equals("SM-J100G") - || model.equals("SM-J100H") - || model.equals("SM-J100M") - || model.equals("SM-J100ML") - || model.equals("SM-J100MU") - || model.equals("SM-J100VPP") - || model.equals("SM-J100Y") - || model.equals("SM-J120F") - || model.equals("SM-J120FN") - || model.equals("SM-J120M") - || model.equals("SM-J120P") - || model.equals("SM-J120W") - || model.equals("SM-S120VL") - || model.equals("SM-S777C")))) { - return "Galaxy J1"; - } - if ((codename != null && (codename.equals("j1acelte") - || codename.equals("j1acelteltn") - || codename.equals("j1acevelte") - || codename.equals("j1pop3g"))) - || (model != null && (model.equals("SM-J110F") - || model.equals("SM-J110G") - || model.equals("SM-J110H") - || model.equals("SM-J110L") - || model.equals("SM-J110M") - || model.equals("SM-J111F") - || model.equals("SM-J111M")))) { - return "Galaxy J1 Ace"; - } - if ((codename != null && (codename.equals("j53g") - || codename.equals("j5lte") - || codename.equals("j5ltechn") - || codename.equals("j5ltekx") - || codename.equals("j5nlte") - || codename.equals("j5ylte"))) - || (model != null && (model.equals("SM-J5007") - || model.equals("SM-J5008") - || model.equals("SM-J500F") - || model.equals("SM-J500FN") - || model.equals("SM-J500G") - || model.equals("SM-J500H") - || model.equals("SM-J500M") - || model.equals("SM-J500N0") - || model.equals("SM-J500Y")))) { - return "Galaxy J5"; - } - if ((codename != null && (codename.equals("j75ltektt") - || codename.equals("j7e3g") - || codename.equals("j7elte") - || codename.equals("j7ltechn"))) - || (model != null && (model.equals("SM-J7008") - || model.equals("SM-J700F") - || model.equals("SM-J700H") - || model.equals("SM-J700K") - || model.equals("SM-J700M")))) { - return "Galaxy J7"; - } - if ((codename != null && (codename.equals("maguro") - || codename.equals("toro") - || codename.equals("toroplus"))) - || (model != null && (model.equals("Galaxy X")))) { - return "Galaxy Nexus"; - } - if ((codename != null && (codename.equals("lt033g") - || codename.equals("lt03ltektt") - || codename.equals("lt03ltelgt") - || codename.equals("lt03lteskt") - || codename.equals("p4notelte") - || codename.equals("p4noteltektt") - || codename.equals("p4noteltelgt") - || codename.equals("p4notelteskt") - || codename.equals("p4noteltespr") - || codename.equals("p4notelteusc") - || codename.equals("p4noteltevzw") - || codename.equals("p4noterf") - || codename.equals("p4noterfktt") - || codename.equals("p4notewifi") - || codename.equals("p4notewifi43241any") - || codename.equals("p4notewifiany") - || codename.equals("p4notewifiktt") - || codename.equals("p4notewifiww"))) - || (model != null && (model.equals("GT-N8000") - || model.equals("GT-N8005") - || model.equals("GT-N8010") - || model.equals("GT-N8013") - || model.equals("GT-N8020") - || model.equals("SCH-I925") - || model.equals("SCH-I925U") - || model.equals("SHV-E230K") - || model.equals("SHV-E230L") - || model.equals("SHV-E230S") - || model.equals("SHW-M480K") - || model.equals("SHW-M480W") - || model.equals("SHW-M485W") - || model.equals("SHW-M486W") - || model.equals("SM-P601") - || model.equals("SM-P602") - || model.equals("SM-P605K") - || model.equals("SM-P605L") - || model.equals("SM-P605S") - || model.equals("SPH-P600")))) { - return "Galaxy Note 10.1"; - } - if ((codename != null && (codename.equals("SC-01G") - || codename.equals("SCL24") - || codename.equals("tbeltektt") - || codename.equals("tbeltelgt") - || codename.equals("tbelteskt") - || codename.equals("tblte") - || codename.equals("tblteatt") - || codename.equals("tbltecan") - || codename.equals("tbltechn") - || codename.equals("tbltespr") - || codename.equals("tbltetmo") - || codename.equals("tblteusc") - || codename.equals("tbltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-N915A") - || model.equals("SC-01G") - || model.equals("SCL24") - || model.equals("SM-N9150") - || model.equals("SM-N915F") - || model.equals("SM-N915FY") - || model.equals("SM-N915G") - || model.equals("SM-N915K") - || model.equals("SM-N915L") - || model.equals("SM-N915P") - || model.equals("SM-N915R4") - || model.equals("SM-N915S") - || model.equals("SM-N915T") - || model.equals("SM-N915T3") - || model.equals("SM-N915V") - || model.equals("SM-N915W8") - || model.equals("SM-N915X")))) { - return "Galaxy Note Edge"; - } - if ((codename != null && (codename.equals("v1a3g") - || codename.equals("v1awifi") - || codename.equals("v1awifikx") - || codename.equals("viennalte") - || codename.equals("viennalteatt") - || codename.equals("viennaltekx") - || codename.equals("viennaltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-P907A") - || model.equals("SM-P900") - || model.equals("SM-P901") - || model.equals("SM-P905") - || model.equals("SM-P905F0") - || model.equals("SM-P905M") - || model.equals("SM-P905V")))) { - return "Galaxy Note Pro 12.2"; - } - if ((codename != null && (codename.equals("tre3caltektt") - || codename.equals("tre3caltelgt") - || codename.equals("tre3calteskt") - || codename.equals("tre3g") - || codename.equals("trelte") - || codename.equals("treltektt") - || codename.equals("treltelgt") - || codename.equals("trelteskt") - || codename.equals("trhplte") - || codename.equals("trlte") - || codename.equals("trlteatt") - || codename.equals("trltecan") - || codename.equals("trltechn") - || codename.equals("trltechnzh") - || codename.equals("trltespr") - || codename.equals("trltetmo") - || codename.equals("trlteusc") - || codename.equals("trltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-N910A") - || model.equals("SM-N9100") - || model.equals("SM-N9106W") - || model.equals("SM-N9108V") - || model.equals("SM-N9109W") - || model.equals("SM-N910C") - || model.equals("SM-N910F") - || model.equals("SM-N910G") - || model.equals("SM-N910H") - || model.equals("SM-N910K") - || model.equals("SM-N910L") - || model.equals("SM-N910P") - || model.equals("SM-N910R4") - || model.equals("SM-N910S") - || model.equals("SM-N910T") - || model.equals("SM-N910T2") - || model.equals("SM-N910T3") - || model.equals("SM-N910U") - || model.equals("SM-N910V") - || model.equals("SM-N910W8") - || model.equals("SM-N910X") - || model.equals("SM-N916K") - || model.equals("SM-N916L") - || model.equals("SM-N916S")))) { - return "Galaxy Note4"; - } - if ((codename != null && (codename.equals("noblelte") - || codename.equals("noblelteacg") - || codename.equals("noblelteatt") - || codename.equals("nobleltebmc") - || codename.equals("nobleltechn") - || codename.equals("nobleltecmcc") - || codename.equals("nobleltehk") - || codename.equals("nobleltektt") - || codename.equals("nobleltelgt") - || codename.equals("nobleltelra") - || codename.equals("noblelteskt") - || codename.equals("nobleltespr") - || codename.equals("nobleltetmo") - || codename.equals("noblelteusc") - || codename.equals("nobleltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-N920A") - || model.equals("SM-N9200") - || model.equals("SM-N9208") - || model.equals("SM-N920C") - || model.equals("SM-N920F") - || model.equals("SM-N920G") - || model.equals("SM-N920I") - || model.equals("SM-N920K") - || model.equals("SM-N920L") - || model.equals("SM-N920P") - || model.equals("SM-N920R4") - || model.equals("SM-N920R6") - || model.equals("SM-N920R7") - || model.equals("SM-N920S") - || model.equals("SM-N920T") - || model.equals("SM-N920V") - || model.equals("SM-N920W8") - || model.equals("SM-N920X")))) { - return "Galaxy Note5"; - } - if ((codename != null && (codename.equals("SC-01J") - || codename.equals("SCV34") - || codename.equals("gracelte") - || codename.equals("graceltektt") - || codename.equals("graceltelgt") - || codename.equals("gracelteskt") - || codename.equals("graceqlteacg") - || codename.equals("graceqlteatt") - || codename.equals("graceqltebmc") - || codename.equals("graceqltechn") - || codename.equals("graceqltedcm") - || codename.equals("graceqltelra") - || codename.equals("graceqltespr") - || codename.equals("graceqltetfnvzw") - || codename.equals("graceqltetmo") - || codename.equals("graceqlteue") - || codename.equals("graceqlteusc") - || codename.equals("graceqltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-N930A") - || model.equals("SC-01J") - || model.equals("SCV34") - || model.equals("SGH-N037") - || model.equals("SM-N9300") - || model.equals("SM-N930F") - || model.equals("SM-N930K") - || model.equals("SM-N930L") - || model.equals("SM-N930P") - || model.equals("SM-N930R4") - || model.equals("SM-N930R6") - || model.equals("SM-N930R7") - || model.equals("SM-N930S") - || model.equals("SM-N930T") - || model.equals("SM-N930U") - || model.equals("SM-N930V") - || model.equals("SM-N930VL") - || model.equals("SM-N930W8") - || model.equals("SM-N930X")))) { - return "Galaxy Note7"; - } - if ((codename != null && (codename.equals("SC-01K") - || codename.equals("SCV37") - || codename.equals("greatlte") - || codename.equals("greatlteks") - || codename.equals("greatqlte") - || codename.equals("greatqltechn") - || codename.equals("greatqltecmcc") - || codename.equals("greatqltecs") - || codename.equals("greatqlteue"))) - || (model != null && (model.equals("SC-01K") - || model.equals("SCV37") - || model.equals("SM-N9500") - || model.equals("SM-N9508") - || model.equals("SM-N950F") - || model.equals("SM-N950N") - || model.equals("SM-N950U") - || model.equals("SM-N950U1") - || model.equals("SM-N950W") - || model.equals("SM-N950XN")))) { - return "Galaxy Note8"; - } - if ((codename != null && (codename.equals("o5lte") - || codename.equals("o5ltechn") - || codename.equals("o5prolte") - || codename.equals("on5ltemtr") - || codename.equals("on5ltetfntmo") - || codename.equals("on5ltetmo"))) - || (model != null && (model.equals("SM-G5500") - || model.equals("SM-G550FY") - || model.equals("SM-G550T") - || model.equals("SM-G550T1") - || model.equals("SM-G550T2") - || model.equals("SM-S550TL")))) { - return "Galaxy On5"; - } - if ((codename != null && (codename.equals("o7lte") - || codename.equals("o7ltechn") - || codename.equals("on7elte"))) - || (model != null && (model.equals("SM-G6000") - || model.equals("SM-G600F") - || model.equals("SM-G600FY")))) { - return "Galaxy On7"; - } - if ((codename != null && (codename.equals("GT-I9000") - || codename.equals("GT-I9000B") - || codename.equals("GT-I9000M") - || codename.equals("GT-I9000T") - || codename.equals("GT-I9003") - || codename.equals("GT-I9003L") - || codename.equals("GT-I9008L") - || codename.equals("GT-I9010") - || codename.equals("GT-I9018") - || codename.equals("GT-I9050") - || codename.equals("SC-02B") - || codename.equals("SCH-I500") - || codename.equals("SCH-S950C") - || codename.equals("SCH-i909") - || codename.equals("SGH-I897") - || codename.equals("SGH-T959V") - || codename.equals("SGH-T959W") - || codename.equals("SHW-M110S") - || codename.equals("SHW-M190S") - || codename.equals("SPH-D700") - || codename.equals("loganlte"))) - || (model != null && (model.equals("GT-I9000") - || model.equals("GT-I9000B") - || model.equals("GT-I9000M") - || model.equals("GT-I9000T") - || model.equals("GT-I9003") - || model.equals("GT-I9003L") - || model.equals("GT-I9008L") - || model.equals("GT-I9010") - || model.equals("GT-I9018") - || model.equals("GT-I9050") - || model.equals("GT-S7275") - || model.equals("SAMSUNG-SGH-I897") - || model.equals("SC-02B") - || model.equals("SCH-I500") - || model.equals("SCH-S950C") - || model.equals("SCH-i909") - || model.equals("SGH-T959V") - || model.equals("SGH-T959W") - || model.equals("SHW-M110S") - || model.equals("SHW-M190S") - || model.equals("SPH-D700")))) { - return "Galaxy S"; - } - if ((codename != null && (codename.equals("kylechn") - || codename.equals("kyleopen") - || codename.equals("kyletdcmcc"))) - || (model != null && (model.equals("GT-S7562") - || model.equals("GT-S7568")))) { - return "Galaxy S Duos"; - } - if ((codename != null && (codename.equals("kyleprods"))) - || (model != null && (model.equals("GT-S7582") - || model.equals("GT-S7582L")))) { - return "Galaxy S Duos2"; - } - if ((codename != null && codename.equals("vivalto3gvn")) - || (model != null && model.equals("SM-G313HZ"))) { - return "Galaxy S Duos3"; - } - if ((codename != null && (codename.equals("SC-03E") - || codename.equals("c1att") - || codename.equals("c1ktt") - || codename.equals("c1lgt") - || codename.equals("c1skt") - || codename.equals("d2att") - || codename.equals("d2can") - || codename.equals("d2cri") - || codename.equals("d2dcm") - || codename.equals("d2lteMetroPCS") - || codename.equals("d2lterefreshspr") - || codename.equals("d2ltetmo") - || codename.equals("d2mtr") - || codename.equals("d2spi") - || codename.equals("d2spr") - || codename.equals("d2tfnspr") - || codename.equals("d2tfnvzw") - || codename.equals("d2tmo") - || codename.equals("d2usc") - || codename.equals("d2vmu") - || codename.equals("d2vzw") - || codename.equals("d2xar") - || codename.equals("m0") - || codename.equals("m0apt") - || codename.equals("m0chn") - || codename.equals("m0cmcc") - || codename.equals("m0ctc") - || codename.equals("m0ctcduos") - || codename.equals("m0skt") - || codename.equals("m3") - || codename.equals("m3dcm"))) - || (model != null && (model.equals("GT-I9300") - || model.equals("GT-I9300T") - || model.equals("GT-I9305") - || model.equals("GT-I9305N") - || model.equals("GT-I9305T") - || model.equals("GT-I9308") - || model.equals("Gravity") - || model.equals("GravityQuad") - || model.equals("SAMSUNG-SGH-I747") - || model.equals("SC-03E") - || model.equals("SC-06D") - || model.equals("SCH-I535") - || model.equals("SCH-I535PP") - || model.equals("SCH-I939") - || model.equals("SCH-I939D") - || model.equals("SCH-L710") - || model.equals("SCH-R530C") - || model.equals("SCH-R530M") - || model.equals("SCH-R530U") - || model.equals("SCH-R530X") - || model.equals("SCH-S960L") - || model.equals("SCH-S968C") - || model.equals("SGH-I747M") - || model.equals("SGH-I748") - || model.equals("SGH-T999") - || model.equals("SGH-T999L") - || model.equals("SGH-T999N") - || model.equals("SGH-T999V") - || model.equals("SHV-E210K") - || model.equals("SHV-E210L") - || model.equals("SHV-E210S") - || model.equals("SHW-M440S") - || model.equals("SPH-L710") - || model.equals("SPH-L710T")))) { - return "Galaxy S3"; - } - if ((codename != null && (codename.equals("golden") - || codename.equals("goldenlteatt") - || codename.equals("goldenltebmc") - || codename.equals("goldenltevzw") - || codename.equals("goldenve3g"))) - || (model != null && (model.equals("GT-I8190") - || model.equals("GT-I8190L") - || model.equals("GT-I8190N") - || model.equals("GT-I8190T") - || model.equals("GT-I8200L") - || model.equals("SAMSUNG-SM-G730A") - || model.equals("SM-G730V") - || model.equals("SM-G730W8")))) { - return "Galaxy S3 Mini"; - } - if ((codename != null && (codename.equals("goldenve3g") - || codename.equals("goldenvess3g"))) - || (model != null && (model.equals("GT-I8200") - || model.equals("GT-I8200N") - || model.equals("GT-I8200Q")))) { - return "Galaxy S3 Mini Value Edition"; - } - if ((codename != null && (codename.equals("s3ve3g") - || codename.equals("s3ve3gdd") - || codename.equals("s3ve3gds") - || codename.equals("s3ve3gdsdd"))) - || (model != null && (model.equals("GT-I9300I") - || model.equals("GT-I9301I") - || model.equals("GT-I9301Q")))) { - return "Galaxy S3 Neo"; - } - if ((codename != null && (codename.equals("SC-04E") - || codename.equals("ja3g") - || codename.equals("ja3gduosctc") - || codename.equals("jaltektt") - || codename.equals("jaltelgt") - || codename.equals("jalteskt") - || codename.equals("jflte") - || codename.equals("jflteMetroPCS") - || codename.equals("jflteaio") - || codename.equals("jflteatt") - || codename.equals("jfltecan") - || codename.equals("jfltecri") - || codename.equals("jfltecsp") - || codename.equals("jfltelra") - || codename.equals("jflterefreshspr") - || codename.equals("jfltespr") - || codename.equals("jfltetfnatt") - || codename.equals("jfltetfntmo") - || codename.equals("jfltetmo") - || codename.equals("jflteusc") - || codename.equals("jfltevzw") - || codename.equals("jfltevzwpp") - || codename.equals("jftdd") - || codename.equals("jfvelte") - || codename.equals("jfwifi") - || codename.equals("jsglte") - || codename.equals("ks01lte") - || codename.equals("ks01ltektt") - || codename.equals("ks01ltelgt"))) - || (model != null && (model.equals("GT-I9500") - || model.equals("GT-I9505") - || model.equals("GT-I9505X") - || model.equals("GT-I9506") - || model.equals("GT-I9507") - || model.equals("GT-I9507V") - || model.equals("GT-I9508") - || model.equals("GT-I9508C") - || model.equals("GT-I9508V") - || model.equals("GT-I9515") - || model.equals("GT-I9515L") - || model.equals("SAMSUNG-SGH-I337") - || model.equals("SAMSUNG-SGH-I337Z") - || model.equals("SC-04E") - || model.equals("SCH-I545") - || model.equals("SCH-I545L") - || model.equals("SCH-I545PP") - || model.equals("SCH-I959") - || model.equals("SCH-R970") - || model.equals("SCH-R970C") - || model.equals("SCH-R970X") - || model.equals("SGH-I337M") - || model.equals("SGH-M919") - || model.equals("SGH-M919N") - || model.equals("SGH-M919V") - || model.equals("SGH-S970G") - || model.equals("SHV-E300K") - || model.equals("SHV-E300L") - || model.equals("SHV-E300S") - || model.equals("SHV-E330K") - || model.equals("SHV-E330L") - || model.equals("SM-S975L") - || model.equals("SPH-L720") - || model.equals("SPH-L720T")))) { - return "Galaxy S4"; - } - if ((codename != null && (codename.equals("serrano3g") - || codename.equals("serranods") - || codename.equals("serranolte") - || codename.equals("serranoltebmc") - || codename.equals("serranoltektt") - || codename.equals("serranoltekx") - || codename.equals("serranoltelra") - || codename.equals("serranoltespr") - || codename.equals("serranolteusc") - || codename.equals("serranoltevzw") - || codename.equals("serranove3g") - || codename.equals("serranovelte") - || codename.equals("serranovolteatt"))) - || (model != null && (model.equals("GT-I9190") - || model.equals("GT-I9192") - || model.equals("GT-I9192I") - || model.equals("GT-I9195") - || model.equals("GT-I9195I") - || model.equals("GT-I9195L") - || model.equals("GT-I9195T") - || model.equals("GT-I9195X") - || model.equals("GT-I9197") - || model.equals("SAMSUNG-SGH-I257") - || model.equals("SCH-I435") - || model.equals("SCH-I435L") - || model.equals("SCH-R890") - || model.equals("SGH-I257M") - || model.equals("SHV-E370D") - || model.equals("SHV-E370K") - || model.equals("SPH-L520")))) { - return "Galaxy S4 Mini"; - } - if ((codename != null && (codename.equals("SC-04F") - || codename.equals("SCL23") - || codename.equals("k3g") - || codename.equals("klte") - || codename.equals("klteMetroPCS") - || codename.equals("klteacg") - || codename.equals("klteaio") - || codename.equals("klteatt") - || codename.equals("kltecan") - || codename.equals("klteduoszn") - || codename.equals("kltektt") - || codename.equals("kltelgt") - || codename.equals("kltelra") - || codename.equals("klteskt") - || codename.equals("kltespr") - || codename.equals("kltetfnvzw") - || codename.equals("kltetmo") - || codename.equals("klteusc") - || codename.equals("kltevzw") - || codename.equals("kwifi") - || codename.equals("lentisltektt") - || codename.equals("lentisltelgt") - || codename.equals("lentislteskt"))) - || (model != null && (model.equals("SAMSUNG-SM-G900A") - || model.equals("SAMSUNG-SM-G900AZ") - || model.equals("SC-04F") - || model.equals("SCL23") - || model.equals("SM-G9006W") - || model.equals("SM-G9008W") - || model.equals("SM-G9009W") - || model.equals("SM-G900F") - || model.equals("SM-G900FQ") - || model.equals("SM-G900H") - || model.equals("SM-G900I") - || model.equals("SM-G900K") - || model.equals("SM-G900L") - || model.equals("SM-G900M") - || model.equals("SM-G900MD") - || model.equals("SM-G900P") - || model.equals("SM-G900R4") - || model.equals("SM-G900R6") - || model.equals("SM-G900R7") - || model.equals("SM-G900S") - || model.equals("SM-G900T") - || model.equals("SM-G900T1") - || model.equals("SM-G900T3") - || model.equals("SM-G900T4") - || model.equals("SM-G900V") - || model.equals("SM-G900W8") - || model.equals("SM-G900X") - || model.equals("SM-G906K") - || model.equals("SM-G906L") - || model.equals("SM-G906S") - || model.equals("SM-S903VL")))) { - return "Galaxy S5"; - } - if ((codename != null && (codename.equals("s5neolte") - || codename.equals("s5neoltecan"))) - || (model != null && (model.equals("SM-G903F") - || model.equals("SM-G903M") - || model.equals("SM-G903W")))) { - return "Galaxy S5 Neo"; - } - if ((codename != null && (codename.equals("SC-05G") - || codename.equals("zeroflte") - || codename.equals("zeroflteacg") - || codename.equals("zeroflteaio") - || codename.equals("zeroflteatt") - || codename.equals("zerofltebmc") - || codename.equals("zerofltechn") - || codename.equals("zerofltectc") - || codename.equals("zerofltektt") - || codename.equals("zerofltelgt") - || codename.equals("zerofltelra") - || codename.equals("zerofltemtr") - || codename.equals("zeroflteskt") - || codename.equals("zerofltespr") - || codename.equals("zerofltetfnvzw") - || codename.equals("zerofltetmo") - || codename.equals("zeroflteusc") - || codename.equals("zerofltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-G920A") - || model.equals("SAMSUNG-SM-G920AZ") - || model.equals("SC-05G") - || model.equals("SM-G9200") - || model.equals("SM-G9208") - || model.equals("SM-G9209") - || model.equals("SM-G920F") - || model.equals("SM-G920I") - || model.equals("SM-G920K") - || model.equals("SM-G920L") - || model.equals("SM-G920P") - || model.equals("SM-G920R4") - || model.equals("SM-G920R6") - || model.equals("SM-G920R7") - || model.equals("SM-G920S") - || model.equals("SM-G920T") - || model.equals("SM-G920T1") - || model.equals("SM-G920V") - || model.equals("SM-G920W8") - || model.equals("SM-G920X") - || model.equals("SM-S906L") - || model.equals("SM-S907VL")))) { - return "Galaxy S6"; - } - if ((codename != null && (codename.equals("404SC") - || codename.equals("SC-04G") - || codename.equals("SCV31") - || codename.equals("zerolte") - || codename.equals("zerolteacg") - || codename.equals("zerolteatt") - || codename.equals("zeroltebmc") - || codename.equals("zeroltechn") - || codename.equals("zeroltektt") - || codename.equals("zeroltelgt") - || codename.equals("zeroltelra") - || codename.equals("zerolteskt") - || codename.equals("zeroltespr") - || codename.equals("zeroltetmo") - || codename.equals("zerolteusc") - || codename.equals("zeroltevzw"))) - || (model != null && (model.equals("404SC") - || model.equals("SAMSUNG-SM-G925A") - || model.equals("SC-04G") - || model.equals("SCV31") - || model.equals("SM-G9250") - || model.equals("SM-G925F") - || model.equals("SM-G925I") - || model.equals("SM-G925K") - || model.equals("SM-G925L") - || model.equals("SM-G925P") - || model.equals("SM-G925R4") - || model.equals("SM-G925R6") - || model.equals("SM-G925R7") - || model.equals("SM-G925S") - || model.equals("SM-G925T") - || model.equals("SM-G925V") - || model.equals("SM-G925W8") - || model.equals("SM-G925X")))) { - return "Galaxy S6 Edge"; - } - if ((codename != null && (codename.equals("zenlte") - || codename.equals("zenlteatt") - || codename.equals("zenltebmc") - || codename.equals("zenltechn") - || codename.equals("zenltektt") - || codename.equals("zenltekx") - || codename.equals("zenltelgt") - || codename.equals("zenlteskt") - || codename.equals("zenltespr") - || codename.equals("zenltetmo") - || codename.equals("zenlteusc") - || codename.equals("zenltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-G928A") - || model.equals("SM-G9280") - || model.equals("SM-G9287") - || model.equals("SM-G9287C") - || model.equals("SM-G928C") - || model.equals("SM-G928F") - || model.equals("SM-G928G") - || model.equals("SM-G928I") - || model.equals("SM-G928K") - || model.equals("SM-G928L") - || model.equals("SM-G928N0") - || model.equals("SM-G928P") - || model.equals("SM-G928R4") - || model.equals("SM-G928S") - || model.equals("SM-G928T") - || model.equals("SM-G928V") - || model.equals("SM-G928W8") - || model.equals("SM-G928X")))) { - return "Galaxy S6 Edge+"; - } - if ((codename != null && (codename.equals("herolte") - || codename.equals("heroltebmc") - || codename.equals("heroltektt") - || codename.equals("heroltelgt") - || codename.equals("herolteskt") - || codename.equals("heroqlteacg") - || codename.equals("heroqlteaio") - || codename.equals("heroqlteatt") - || codename.equals("heroqltecctvzw") - || codename.equals("heroqltechn") - || codename.equals("heroqltelra") - || codename.equals("heroqltemtr") - || codename.equals("heroqltespr") - || codename.equals("heroqltetfnvzw") - || codename.equals("heroqltetmo") - || codename.equals("heroqlteue") - || codename.equals("heroqlteusc") - || codename.equals("heroqltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-G930A") - || model.equals("SAMSUNG-SM-G930AZ") - || model.equals("SM-G9300") - || model.equals("SM-G9308") - || model.equals("SM-G930F") - || model.equals("SM-G930K") - || model.equals("SM-G930L") - || model.equals("SM-G930P") - || model.equals("SM-G930R4") - || model.equals("SM-G930R6") - || model.equals("SM-G930R7") - || model.equals("SM-G930S") - || model.equals("SM-G930T") - || model.equals("SM-G930T1") - || model.equals("SM-G930U") - || model.equals("SM-G930V") - || model.equals("SM-G930VC") - || model.equals("SM-G930VL") - || model.equals("SM-G930W8") - || model.equals("SM-G930X")))) { - return "Galaxy S7"; - } - if ((codename != null && (codename.equals("SC-02H") - || codename.equals("SCV33") - || codename.equals("hero2lte") - || codename.equals("hero2ltebmc") - || codename.equals("hero2ltektt") - || codename.equals("hero2ltelgt") - || codename.equals("hero2lteskt") - || codename.equals("hero2qlteatt") - || codename.equals("hero2qltecctvzw") - || codename.equals("hero2qltechn") - || codename.equals("hero2qltespr") - || codename.equals("hero2qltetmo") - || codename.equals("hero2qlteue") - || codename.equals("hero2qlteusc") - || codename.equals("hero2qltevzw"))) - || (model != null && (model.equals("SAMSUNG-SM-G935A") - || model.equals("SC-02H") - || model.equals("SCV33") - || model.equals("SM-G9350") - || model.equals("SM-G935F") - || model.equals("SM-G935K") - || model.equals("SM-G935L") - || model.equals("SM-G935P") - || model.equals("SM-G935R4") - || model.equals("SM-G935S") - || model.equals("SM-G935T") - || model.equals("SM-G935U") - || model.equals("SM-G935V") - || model.equals("SM-G935VC") - || model.equals("SM-G935W8") - || model.equals("SM-G935X")))) { - return "Galaxy S7 Edge"; - } - if ((codename != null && (codename.equals("SC-02J") - || codename.equals("SCV36") - || codename.equals("dreamlte") - || codename.equals("dreamlteks") - || codename.equals("dreamqltecan") - || codename.equals("dreamqltechn") - || codename.equals("dreamqltecmcc") - || codename.equals("dreamqltesq") - || codename.equals("dreamqlteue"))) - || (model != null && (model.equals("SC-02J") - || model.equals("SCV36") - || model.equals("SM-G9500") - || model.equals("SM-G9508") - || model.equals("SM-G950F") - || model.equals("SM-G950N") - || model.equals("SM-G950U") - || model.equals("SM-G950U1") - || model.equals("SM-G950W")))) { - return "Galaxy S8"; - } - if ((codename != null && (codename.equals("SC-03J") - || codename.equals("SCV35") - || codename.equals("dream2lte") - || codename.equals("dream2lteks") - || codename.equals("dream2qltecan") - || codename.equals("dream2qltechn") - || codename.equals("dream2qltesq") - || codename.equals("dream2qlteue"))) - || (model != null && (model.equals("SC-03J") - || model.equals("SCV35") - || model.equals("SM-G9550") - || model.equals("SM-G955F") - || model.equals("SM-G955N") - || model.equals("SM-G955U") - || model.equals("SM-G955U1") - || model.equals("SM-G955W")))) { - return "Galaxy S8+"; - } - if ((codename != null && (codename.equals("starlte") - || codename.equals("starlteks") - || codename.equals("starqltechn") - || codename.equals("starqltecmcc") - || codename.equals("starqltecs") - || codename.equals("starqltesq") - || codename.equals("starqlteue"))) - || (model != null && (model.equals("SM-G9600") - || model.equals("SM-G9608") - || model.equals("SM-G960F") - || model.equals("SM-G960N") - || model.equals("SM-G960U") - || model.equals("SM-G960U1") - || model.equals("SM-G960W")))) { - return "Galaxy S9"; - } - if ((codename != null && (codename.equals("star2lte") - || codename.equals("star2lteks") - || codename.equals("star2qltechn") - || codename.equals("star2qltecs") - || codename.equals("star2qltesq") - || codename.equals("star2qlteue"))) - || (model != null && (model.equals("SM-G9650") - || model.equals("SM-G965F") - || model.equals("SM-G965N") - || model.equals("SM-G965U") - || model.equals("SM-G965U1") - || model.equals("SM-G965W")))) { - return "Galaxy S9+"; - } - if ((codename != null && (codename.equals("GT-P7500") - || codename.equals("GT-P7500D") - || codename.equals("GT-P7503") - || codename.equals("GT-P7510") - || codename.equals("SC-01D") - || codename.equals("SCH-I905") - || codename.equals("SGH-T859") - || codename.equals("SHW-M300W") - || codename.equals("SHW-M380K") - || codename.equals("SHW-M380S") - || codename.equals("SHW-M380W"))) - || (model != null && (model.equals("GT-P7500") - || model.equals("GT-P7500D") - || model.equals("GT-P7503") - || model.equals("GT-P7510") - || model.equals("SC-01D") - || model.equals("SCH-I905") - || model.equals("SGH-T859") - || model.equals("SHW-M300W") - || model.equals("SHW-M380K") - || model.equals("SHW-M380S") - || model.equals("SHW-M380W")))) { - return "Galaxy Tab 10.1"; - } - if ((codename != null && (codename.equals("GT-P6200") - || codename.equals("GT-P6200L") - || codename.equals("GT-P6201") - || codename.equals("GT-P6210") - || codename.equals("GT-P6211") - || codename.equals("SC-02D") - || codename.equals("SGH-T869") - || codename.equals("SHW-M430W"))) - || (model != null && (model.equals("GT-P6200") - || model.equals("GT-P6200L") - || model.equals("GT-P6201") - || model.equals("GT-P6210") - || model.equals("GT-P6211") - || model.equals("SC-02D") - || model.equals("SGH-T869") - || model.equals("SHW-M430W")))) { - return "Galaxy Tab 7.0 Plus"; - } - if ((codename != null && (codename.equals("gteslteatt") - || codename.equals("gtesltebmc") - || codename.equals("gtesltelgt") - || codename.equals("gteslteskt") - || codename.equals("gtesltetmo") - || codename.equals("gtesltetw") - || codename.equals("gtesltevzw") - || codename.equals("gtesqltespr") - || codename.equals("gtesqlteusc"))) - || (model != null && (model.equals("SAMSUNG-SM-T377A") - || model.equals("SM-T375L") - || model.equals("SM-T375S") - || model.equals("SM-T3777") - || model.equals("SM-T377P") - || model.equals("SM-T377R4") - || model.equals("SM-T377T") - || model.equals("SM-T377V") - || model.equals("SM-T377W")))) { - return "Galaxy Tab E 8.0"; - } - if ((codename != null && (codename.equals("gtel3g") - || codename.equals("gtelltevzw") - || codename.equals("gtelwifi") - || codename.equals("gtelwifichn") - || codename.equals("gtelwifiue"))) - || (model != null && (model.equals("SM-T560") - || model.equals("SM-T560NU") - || model.equals("SM-T561") - || model.equals("SM-T561M") - || model.equals("SM-T561Y") - || model.equals("SM-T562") - || model.equals("SM-T567V")))) { - return "Galaxy Tab E 9.6"; - } - if ((codename != null && (codename.equals("403SC") - || codename.equals("degas2wifi") - || codename.equals("degas2wifibmwchn") - || codename.equals("degas3g") - || codename.equals("degaslte") - || codename.equals("degasltespr") - || codename.equals("degasltevzw") - || codename.equals("degasvelte") - || codename.equals("degasveltechn") - || codename.equals("degaswifi") - || codename.equals("degaswifibmwzc") - || codename.equals("degaswifidtv") - || codename.equals("degaswifiopenbnn") - || codename.equals("degaswifiue"))) - || (model != null && (model.equals("403SC") - || model.equals("SM-T230") - || model.equals("SM-T230NT") - || model.equals("SM-T230NU") - || model.equals("SM-T230NW") - || model.equals("SM-T230NY") - || model.equals("SM-T230X") - || model.equals("SM-T231") - || model.equals("SM-T232") - || model.equals("SM-T235") - || model.equals("SM-T235Y") - || model.equals("SM-T237P") - || model.equals("SM-T237V") - || model.equals("SM-T239") - || model.equals("SM-T2397") - || model.equals("SM-T239C") - || model.equals("SM-T239M")))) { - return "Galaxy Tab4 7.0"; - } - if ((codename != null && (codename.equals("gvlte") - || codename.equals("gvlteatt") - || codename.equals("gvltevzw") - || codename.equals("gvltexsp") - || codename.equals("gvwifijpn") - || codename.equals("gvwifiue"))) - || (model != null && (model.equals("SAMSUNG-SM-T677A") - || model.equals("SM-T670") - || model.equals("SM-T677") - || model.equals("SM-T677V")))) { - return "Galaxy View"; - } - if ((codename != null && codename.equals("manta"))) { - return "Nexus 10"; - } - // ---------------------------------------------------------------------------- - // Sony - if ((codename != null && (codename.equals("D2104") - || codename.equals("D2105"))) - || (model != null && (model.equals("D2104") - || model.equals("D2105")))) { - return "Xperia E1 dual"; - } - if ((codename != null && (codename.equals("D2202") - || codename.equals("D2203") - || codename.equals("D2206") - || codename.equals("D2243"))) - || (model != null && (model.equals("D2202") - || model.equals("D2203") - || model.equals("D2206") - || model.equals("D2243")))) { - return "Xperia E3"; - } - if ((codename != null && (codename.equals("E5603") - || codename.equals("E5606") - || codename.equals("E5653"))) - || (model != null && (model.equals("E5603") - || model.equals("E5606") - || model.equals("E5653")))) { - return "Xperia M5"; - } - if ((codename != null && (codename.equals("E5633") - || codename.equals("E5643") - || codename.equals("E5663"))) - || (model != null && (model.equals("E5633") - || model.equals("E5643") - || model.equals("E5663")))) { - return "Xperia M5 Dual"; - } - if ((codename != null && codename.equals("LT26i")) - || (model != null && model.equals("LT26i"))) { - return "Xperia S"; - } - if ((codename != null && (codename.equals("D5303") - || codename.equals("D5306") - || codename.equals("D5316") - || codename.equals("D5316N") - || codename.equals("D5322"))) - || (model != null && (model.equals("D5303") - || model.equals("D5306") - || model.equals("D5316") - || model.equals("D5316N") - || model.equals("D5322")))) { - return "Xperia T2 Ultra"; - } - if ((codename != null && (codename.equals("txs03"))) - || (model != null && (model.equals("SGPT12") - || model.equals("SGPT13")))) { - return "Xperia Tablet S"; - } - if ((codename != null && (codename.equals("SGP311") - || codename.equals("SGP312") - || codename.equals("SGP321") - || codename.equals("SGP351"))) - || (model != null && (model.equals("SGP311") - || model.equals("SGP312") - || model.equals("SGP321") - || model.equals("SGP351")))) { - return "Xperia Tablet Z"; - } - if ((codename != null && (codename.equals("D6502") - || codename.equals("D6503") - || codename.equals("D6543") - || codename.equals("SO-03F"))) - || (model != null && (model.equals("D6502") - || model.equals("D6503") - || model.equals("D6543") - || model.equals("SO-03F")))) { - return "Xperia Z2"; - } - if ((codename != null && (codename.equals("401SO") - || codename.equals("D6603") - || codename.equals("D6616") - || codename.equals("D6643") - || codename.equals("D6646") - || codename.equals("D6653") - || codename.equals("SO-01G") - || codename.equals("SOL26") - || codename.equals("leo"))) - || (model != null && (model.equals("401SO") - || model.equals("D6603") - || model.equals("D6616") - || model.equals("D6643") - || model.equals("D6646") - || model.equals("D6653") - || model.equals("SO-01G") - || model.equals("SOL26")))) { - return "Xperia Z3"; - } - if ((codename != null && (codename.equals("402SO") - || codename.equals("SO-03G") - || codename.equals("SOV31"))) - || (model != null && (model.equals("402SO") - || model.equals("SO-03G") - || model.equals("SOV31")))) { - return "Xperia Z4"; - } - if ((codename != null && (codename.equals("E5803") - || codename.equals("E5823") - || codename.equals("SO-02H"))) - || (model != null && (model.equals("E5803") - || model.equals("E5823") - || model.equals("SO-02H")))) { - return "Xperia Z5 Compact"; - } - // ---------------------------------------------------------------------------- - // Sony Ericsson - if ((codename != null && (codename.equals("LT26i") - || codename.equals("SO-02D"))) - || (model != null && (model.equals("LT26i") - || model.equals("SO-02D")))) { - return "Xperia S"; - } - if ((codename != null && (codename.equals("SGP311") - || codename.equals("SGP321") - || codename.equals("SGP341") - || codename.equals("SO-03E"))) - || (model != null && (model.equals("SGP311") - || model.equals("SGP321") - || model.equals("SGP341") - || model.equals("SO-03E")))) { - return "Xperia Tablet Z"; - } - return fallback; - } - - /** - * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may - * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then - * stored to {@link SharedPreferences}. - * - * @param context - * the application context. - * @return {@link DeviceInfo} for the current device. - */ - @WorkerThread - public static DeviceInfo getDeviceInfo(Context context) { - return getDeviceInfo(context.getApplicationContext(), Build.DEVICE, Build.MODEL); - } - - /** - * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may - * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then - * stored to {@link SharedPreferences}. - * - * @param context - * the application context. - * @param codename - * the codename of the device - * @return {@link DeviceInfo} for the current device. - */ - @WorkerThread - public static DeviceInfo getDeviceInfo(Context context, String codename) { - return getDeviceInfo(context, codename, null); - } - - /** - * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may - * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then - * stored to {@link SharedPreferences}. - * - * @param context - * the application context. - * @param codename - * the codename of the device - * @param model - * the model of the device - * @return {@link DeviceInfo} for the current device. - */ - @WorkerThread - public static DeviceInfo getDeviceInfo(Context context, String codename, String model) { - SharedPreferences prefs = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE); - String key = String.format("%s:%s", codename, model); - String savedJson = prefs.getString(key, null); - if (savedJson != null) { - try { - return new DeviceInfo(new JSONObject(savedJson)); - } catch (JSONException e) { - e.printStackTrace(); - } - } - - // check if we have an internet connection - int ret = context.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE); - boolean isConnectedToNetwork = false; - if (ret == PackageManager.PERMISSION_GRANTED) { - ConnectivityManager connMgr = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); - if (networkInfo != null && networkInfo.isConnected()) { - isConnectedToNetwork = true; - } - } else { - // assume we are connected. - isConnectedToNetwork = true; - } - - if (isConnectedToNetwork) { - try { - // Get the device name from the generated JSON files created from Google's device list. - String url = String.format(DEVICE_JSON_URL, codename.toLowerCase(Locale.ENGLISH)); - String jsonString = downloadJson(url); - JSONArray jsonArray = new JSONArray(jsonString); - for (int i = 0, len = jsonArray.length(); i < len; i++) { - JSONObject json = jsonArray.getJSONObject(i); - DeviceInfo info = new DeviceInfo(json); - if ((codename.equalsIgnoreCase(info.codename) && model == null) - || codename.equalsIgnoreCase(info.codename) && model.equalsIgnoreCase(info.model)) { - // Save to SharedPreferences so we don't need to make another request. - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(key, json.toString()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { - editor.apply(); - } else { - editor.commit(); - } - return info; - } - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (codename.equals(Build.DEVICE) && model.equals(Build.MODEL)) { - return new DeviceInfo(Build.MANUFACTURER, getDeviceName(), codename, model); // current device - } - - return new DeviceInfo(null, null, codename, model); // unknown device - } - - /** - *

Capitalizes getAllProcesses the whitespace separated words in a String. Only the first - * letter of each word is changed.

- * - * Whitespace is defined by {@link Character#isWhitespace(char)}. - * - * @param str - * the String to capitalize - * @return capitalized The capitalized String - */ - private static String capitalize(String str) { - if (TextUtils.isEmpty(str)) { - return str; - } - char[] arr = str.toCharArray(); - boolean capitalizeNext = true; - String phrase = ""; - for (char c : arr) { - if (capitalizeNext && Character.isLetter(c)) { - phrase += Character.toUpperCase(c); - capitalizeNext = false; - continue; - } else if (Character.isWhitespace(c)) { - capitalizeNext = true; - } - phrase += c; - } - return phrase; - } - - /** Download URL to String */ - @WorkerThread - private static String downloadJson(String myurl) throws IOException { - StringBuilder sb = new StringBuilder(); - BufferedReader reader = null; - try { - URL url = new URL(myurl); - HttpURLConnection conn = (HttpURLConnection) url.openConnection(); - conn.setReadTimeout(10000); - conn.setConnectTimeout(15000); - conn.setRequestMethod("GET"); - conn.setDoInput(true); - conn.connect(); - if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { - reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); - String line; - while ((line = reader.readLine()) != null) { - sb.append(line).append('\n'); - } - } - return sb.toString(); - } finally { - if (reader != null) { - reader.close(); - } - } - } - - public static final class Request { - - final Context context; - final Handler handler; - String codename; - String model; - - private Request(Context ctx) { - context = ctx; - handler = new Handler(ctx.getMainLooper()); - } - - /** - * Set the device codename to query. You should also set the model. - * - * @param codename - * the value of the system property "ro.product.device" - * @return This Request object to allow for chaining of calls to set methods. - * @see Build#DEVICE - */ - public Request setCodename(String codename) { - this.codename = codename; - return this; - } - - /** - * Set the device model to query. You should also set the codename. - * - * @param model - * the value of the system property "ro.product.model" - * @return This Request object to allow for chaining of calls to set methods. - * @see Build#MODEL - */ - public Request setModel(String model) { - this.model = model; - return this; - } - - /** - * Download information about the device. This saves the results in shared-preferences so - * future requests will not need a network connection. - * - * @param callback - * the callback to retrieve the {@link DeviceInfo} - */ - public void request(Callback callback) { - if (codename == null && model == null) { - codename = Build.DEVICE; - model = Build.MODEL; - } - GetDeviceRunnable runnable = new GetDeviceRunnable(callback); - if (Looper.myLooper() == Looper.getMainLooper()) { - new Thread(runnable).start(); - } else { - runnable.run(); // already running in background thread. - } - } - - private final class GetDeviceRunnable implements Runnable { - - final Callback callback; - DeviceInfo deviceInfo; - Exception error; - - public GetDeviceRunnable(Callback callback) { - this.callback = callback; - } - - @Override public void run() { - try { - deviceInfo = getDeviceInfo(context, codename, model); - } catch (Exception e) { - error = e; - } - handler.post(new Runnable() { - - @Override public void run() { - callback.onFinished(deviceInfo, error); - } - }); - } - } - - } - - /** - * Callback which is invoked when the {@link DeviceInfo} is finished loading. - */ - public interface Callback { - - /** - * Callback to get the device info. This is run on the UI thread. - * - * @param info - * the requested {@link DeviceInfo} - * @param error - * {@code null} if nothing went wrong. - */ - void onFinished(DeviceInfo info, Exception error); - } - - /** - * Device information based on - * Google's maintained list. - */ - public static final class DeviceInfo { - - /** Retail branding */ - public final String manufacturer; - - /** Marketing name */ - public final String marketName; - - /** the value of the system property "ro.product.device" */ - public final String codename; - - /** the value of the system property "ro.product.model" */ - public final String model; - - public DeviceInfo(String manufacturer, String marketName, String codename, String model) { - this.manufacturer = manufacturer; - this.marketName = marketName; - this.codename = codename; - this.model = model; - } - - private DeviceInfo(JSONObject jsonObject) throws JSONException { - manufacturer = jsonObject.getString("manufacturer"); - marketName = jsonObject.getString("market_name"); - codename = jsonObject.getString("codename"); - model = jsonObject.getString("model"); - } - - /** - * @return the consumer friendly name of the device. - */ - public String getName() { - if (!TextUtils.isEmpty(marketName)) { - return marketName; - } - return capitalize(model); - } - } - -} - +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 20.04.2018. + */ +/* + * Copyright (C) 2017 Jared Rummler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + import android.Manifest; + import android.content.Context; + import android.content.SharedPreferences; + import android.content.pm.PackageManager; + import android.net.ConnectivityManager; + import android.net.NetworkInfo; + import android.os.Build; + import android.os.Handler; + import android.os.Looper; + import android.support.annotation.WorkerThread; + import android.text.TextUtils; + import java.io.BufferedReader; + import java.io.IOException; + import java.io.InputStreamReader; + import java.net.HttpURLConnection; + import java.net.URL; + import java.util.Locale; + import org.json.JSONArray; + import org.json.JSONException; + import org.json.JSONObject; + +// @formatter:off +/** + *

Get the consumer friendly name of an Android device.

+ * + *

On many popular devices the market name of the device is not available. For example, on the + * Samsung Galaxy S6 the value of {@link Build#MODEL} could be "SM-G920F", "SM-G920I", "SM-G920W8", + * etc.

+ * + *

See the usages below to get the consumer friends name of a device:

+ * + *

Get the name of the current device:

+ * + *
+ * String deviceName = DeviceName.getDeviceName();
+ * 
+ * + *

The above code will get the correct device name for the top 600 Android devices. If the + * device is unrecognized, then Build.MODEL is returned.

+ * + *

Get the name of a device using the device's codename:

+ * + *
+ * // Retruns "Moto X Style"
+ * DeviceName.getDeviceName("clark", "Unknown device");
+ * 
+ * + *

Get information about the device:

+ * + *
+ * DeviceName.with(context).request(new DeviceName.Callback() {
+ *
+ *   @Override public void onFinished(DeviceName.DeviceInfo info, Exception error) {
+ *     String manufacturer = info.manufacturer;  // "Samsung"
+ *     String name = info.marketName;            // "Galaxy S6 Edge"
+ *     String model = info.model;                // "SM-G925I"
+ *     String codename = info.codename;          // "zerolte"
+ *     String deviceName = info.getName();       // "Galaxy S6 Edge"
+ *     // FYI: We are on the UI thread.
+ *   }
+ * });
+ * 
+ * + *

The above code loads JSON from a generated list of device names based on Google's maintained + * list. It will be up-to-date with Google's supported device list so that you will get the correct + * name for new or unknown devices. This supports over 10,000 devices.

+ * + *

This will only make a network call once. The value is saved to SharedPreferences for future + * calls.

+ */ + +public class DeviceName { + + // @formatter:on + + // JSON which is derived from Google's PDF document which contains all devices on Google Play. + // To get the URL to the JSON file which contains information about the device name: + // String url = String.format(DEVICE_JSON_URL, Build.DEVICE); + private static final String DEVICE_JSON_URL = + "https://raw.githubusercontent.com/jaredrummler/AndroidDeviceNames/master/json/devices/%s.json"; + + // Preference filename for storing device info so we don't need to download it again. + private static final String SHARED_PREF_NAME = "device_names"; + + /** + * Create a new request to get information about a device. + * + * @param context + * the application context + * @return a new Request instance. + */ + public static Request with(Context context) { + return new Request(context.getApplicationContext()); + } + + /** + * Get the consumer friendly name of the device. + * + * @return the market name of the current device. + * @see #getDeviceName(String, String) + */ + public static String getDeviceName() { + return getDeviceName(Build.DEVICE, Build.MODEL, capitalize(Build.MODEL)); + } + + /** + * Get the consumer friendly name of a device. + * + * @param codename + * the value of the system property "ro.product.device" ({@link Build#DEVICE}) + * or + * the value of the system property "ro.product.model" ({@link Build#MODEL}) + * @param fallback + * the fallback name if the device is unknown. Usually the value of the system property + * "ro.product.model" ({@link Build#MODEL}) + * @return the market name of a device or {@code fallback} if the device is unknown. + */ + public static String getDeviceName(String codename, String fallback) { + return getDeviceName(codename, codename, fallback); + } + + /** + * Get the consumer friendly name of a device. + * + * @param codename + * the value of the system property "ro.product.device" ({@link Build#DEVICE}). + * @param model + * the value of the system property "ro.product.model" ({@link Build#MODEL}). + * @param fallback + * the fallback name if the device is unknown. Usually the value of the system property + * "ro.product.model" ({@link Build#MODEL}) + * @return the market name of a device or {@code fallback} if the device is unknown. + */ + public static String getDeviceName(String codename, String model, String fallback) { + // ---------------------------------------------------------------------------- + // Acer + if ((codename != null && codename.equals("acer_S57")) + || (model != null && model.equals("S57"))) { + return "Liquid Jade Z"; + } + if ((codename != null && codename.equals("acer_t08")) + || (model != null && model.equals("T08"))) { + return "Liquid Zest Plus"; + } + // ---------------------------------------------------------------------------- + // Asus + if ((codename != null && (codename.equals("grouper") + || codename.equals("tilapia")))) { + return "Nexus 7 (2012)"; + } + if ((codename != null && (codename.equals("deb") + || codename.equals("flo")))) { + return "Nexus 7 (2013)"; + } + // ---------------------------------------------------------------------------- + // Google + if ((codename != null && codename.equals("sailfish"))) { + return "Pixel"; + } + if ((codename != null && codename.equals("walleye"))) { + return "Pixel 2"; + } + if ((codename != null && codename.equals("taimen"))) { + return "Pixel 2 XL"; + } + if ((codename != null && codename.equals("dragon"))) { + return "Pixel C"; + } + if ((codename != null && codename.equals("marlin"))) { + return "Pixel XL"; + } + // ---------------------------------------------------------------------------- + // HTC + if ((codename != null && codename.equals("flounder"))) { + return "Nexus 9"; + } + // ---------------------------------------------------------------------------- + // Huawei + if ((codename != null && (codename.equals("HWBND-H"))) + || (model != null && (model.equals("BND-L21") + || model.equals("BND-L24")))) { + return "Honor 7X"; + } + if (model != null && model.contains("WAS-LX")) { + return "P10 lite"; + } + if ((codename != null && codename.equals("HWBKL")) + || (model != null && model.equals("BKL-L09"))) { + return "Honor View 10"; + } + if ((codename != null && (codename.equals("HWALP"))) + || (model != null && (model.equals("ALP-AL00") + || model.equals("ALP-L09") + || model.equals("ALP-L29") + || model.equals("ALP-TL00")))) { + return "Mate 10"; + } + if ((codename != null && (codename.equals("HWMHA"))) + || (model != null && (model.equals("MHA-AL00") + || model.equals("MHA-L09") + || model.equals("MHA-L29") + || model.equals("MHA-TL00")))) { + return "Mate 9"; + } + if ((codename != null && codename.equals("angler"))) { + return "Nexus 6P"; + } + // ---------------------------------------------------------------------------- + // LGE + if ((codename != null && (codename.equals("g2"))) + || (model != null && (model.equals("LG-D800") + || model.equals("LG-D801") + || model.equals("LG-D802") + || model.equals("LG-D802T") + || model.equals("LG-D802TR") + || model.equals("LG-D803") + || model.equals("LG-D805") + || model.equals("LG-D806") + || model.equals("LG-F320K") + || model.equals("LG-F320L") + || model.equals("LG-F320S") + || model.equals("LG-LS980") + || model.equals("VS980 4G")))) { + return "LG G2"; + } + if ((codename != null && (codename.equals("g3"))) + || (model != null && (model.equals("AS985") + || model.equals("LG-AS990") + || model.equals("LG-D850") + || model.equals("LG-D851") + || model.equals("LG-D852") + || model.equals("LG-D852G") + || model.equals("LG-D855") + || model.equals("LG-D856") + || model.equals("LG-D857") + || model.equals("LG-D858") + || model.equals("LG-D858HK") + || model.equals("LG-D859") + || model.equals("LG-F400K") + || model.equals("LG-F400L") + || model.equals("LG-F400S") + || model.equals("LGL24") + || model.equals("LGLS990") + || model.equals("LGUS990") + || model.equals("LGV31") + || model.equals("VS985 4G")))) { + return "LG G3"; + } + if ((codename != null && (codename.equals("p1"))) + || (model != null && (model.equals("AS986") + || model.equals("LG-AS811") + || model.equals("LG-AS991") + || model.equals("LG-F500K") + || model.equals("LG-F500L") + || model.equals("LG-F500S") + || model.equals("LG-H810") + || model.equals("LG-H811") + || model.equals("LG-H812") + || model.equals("LG-H815") + || model.equals("LG-H818") + || model.equals("LG-H819") + || model.equals("LGLS991") + || model.equals("LGUS991") + || model.equals("LGV32") + || model.equals("VS986")))) { + return "LG G4"; + } + if ((codename != null && (codename.equals("h1"))) + || (model != null && (model.equals("LG-F700K") + || model.equals("LG-F700L") + || model.equals("LG-F700S") + || model.equals("LG-H820") + || model.equals("LG-H820PR") + || model.equals("LG-H830") + || model.equals("LG-H831") + || model.equals("LG-H850") + || model.equals("LG-H858") + || model.equals("LG-H860") + || model.equals("LG-H868") + || model.equals("LGAS992") + || model.equals("LGLS992") + || model.equals("LGUS992") + || model.equals("RS988") + || model.equals("VS987")))) { + return "LG G5"; + } + if ((codename != null && (codename.equals("lucye"))) + || (model != null && (model.equals("LG-AS993") + || model.equals("LG-H870") + || model.equals("LG-H870AR") + || model.equals("LG-H870DS") + || model.equals("LG-H870I") + || model.equals("LG-H870S") + || model.equals("LG-H871") + || model.equals("LG-H872") + || model.equals("LG-H872PR") + || model.equals("LG-H873") + || model.equals("LG-LS993") + || model.equals("LGM-G600K") + || model.equals("LGM-G600L") + || model.equals("LGM-G600S") + || model.equals("LGUS997") + || model.equals("VS988")))) { + return "LG G6"; + } + if ((codename != null && codename.equals("mako"))) { + return "Nexus 4"; + } + if ((codename != null && codename.equals("hammerhead"))) { + return "Nexus 5"; + } + if ((codename != null && codename.equals("bullhead"))) { + return "Nexus 5X"; + } + // ---------------------------------------------------------------------------- + // Motorola + if ((codename != null && codename.equals("shamu"))) { + return "Nexus 6"; + } + // ---------------------------------------------------------------------------- + // OnePlus + if ((codename != null && codename.equals("OnePlus3")) + || (model != null && model.equals("ONEPLUS A3000"))) { + return "OnePlus3"; + } + if ((codename != null && codename.equals("OnePlus3T")) + || (model != null && model.equals("ONEPLUS A3000"))) { + return "OnePlus3T"; + } + if ((codename != null && codename.equals("OnePlus5")) + || (model != null && model.equals("ONEPLUS A5000"))) { + return "OnePlus5"; + } + if ((codename != null && codename.equals("OnePlus5T")) + || (model != null && model.equals("ONEPLUS A5010"))) { + return "OnePlus5T"; + } + // ---------------------------------------------------------------------------- + // Samsung + if ((codename != null && (codename.equals("a53g") + || codename.equals("a5lte") + || codename.equals("a5ltechn") + || codename.equals("a5ltectc") + || codename.equals("a5ltezh") + || codename.equals("a5ltezt") + || codename.equals("a5ulte") + || codename.equals("a5ultebmc") + || codename.equals("a5ultektt") + || codename.equals("a5ultelgt") + || codename.equals("a5ulteskt"))) + || (model != null && (model.equals("SM-A5000") + || model.equals("SM-A5009") + || model.equals("SM-A500F") + || model.equals("SM-A500F1") + || model.equals("SM-A500FU") + || model.equals("SM-A500G") + || model.equals("SM-A500H") + || model.equals("SM-A500K") + || model.equals("SM-A500L") + || model.equals("SM-A500M") + || model.equals("SM-A500S") + || model.equals("SM-A500W") + || model.equals("SM-A500X") + || model.equals("SM-A500XZ") + || model.equals("SM-A500Y") + || model.equals("SM-A500YZ")))) { + return "Galaxy A5"; + } + if ((codename != null && (codename.equals("vivaltods5m"))) + || (model != null && (model.equals("SM-G313HU") + || model.equals("SM-G313HY") + || model.equals("SM-G313M") + || model.equals("SM-G313MY")))) { + return "Galaxy Ace 4"; + } + if ((codename != null && (codename.equals("GT-S6352") + || codename.equals("GT-S6802") + || codename.equals("GT-S6802B") + || codename.equals("SCH-I579") + || codename.equals("SCH-I589") + || codename.equals("SCH-i579") + || codename.equals("SCH-i589"))) + || (model != null && (model.equals("GT-S6352") + || model.equals("GT-S6802") + || model.equals("GT-S6802B") + || model.equals("SCH-I589") + || model.equals("SCH-i579") + || model.equals("SCH-i589")))) { + return "Galaxy Ace Duos"; + } + if ((codename != null && (codename.equals("GT-S7500") + || codename.equals("GT-S7500L") + || codename.equals("GT-S7500T") + || codename.equals("GT-S7500W") + || codename.equals("GT-S7508"))) + || (model != null && (model.equals("GT-S7500") + || model.equals("GT-S7500L") + || model.equals("GT-S7500T") + || model.equals("GT-S7500W") + || model.equals("GT-S7508")))) { + return "Galaxy Ace Plus"; + } + if ((codename != null && (codename.equals("heat3gtfnvzw") + || codename.equals("heatnfc3g") + || codename.equals("heatqlte"))) + || (model != null && (model.equals("SM-G310HN") + || model.equals("SM-G357FZ") + || model.equals("SM-S765C") + || model.equals("SM-S766C")))) { + return "Galaxy Ace Style"; + } + if ((codename != null && (codename.equals("vivalto3g") + || codename.equals("vivalto3mve3g") + || codename.equals("vivalto5mve3g") + || codename.equals("vivaltolte") + || codename.equals("vivaltonfc3g"))) + || (model != null && (model.equals("SM-G313F") + || model.equals("SM-G313HN") + || model.equals("SM-G313ML") + || model.equals("SM-G313MU") + || model.equals("SM-G316H") + || model.equals("SM-G316HU") + || model.equals("SM-G316M") + || model.equals("SM-G316MY")))) { + return "Galaxy Ace4"; + } + if ((codename != null && (codename.equals("core33g") + || codename.equals("coreprimelte") + || codename.equals("coreprimelteaio") + || codename.equals("coreprimeltelra") + || codename.equals("coreprimeltespr") + || codename.equals("coreprimeltetfnvzw") + || codename.equals("coreprimeltevzw") + || codename.equals("coreprimeve3g") + || codename.equals("coreprimevelte") + || codename.equals("cprimeltemtr") + || codename.equals("cprimeltetmo") + || codename.equals("rossalte") + || codename.equals("rossaltectc") + || codename.equals("rossaltexsa"))) + || (model != null && (model.equals("SAMSUNG-SM-G360AZ") + || model.equals("SM-G3606") + || model.equals("SM-G3608") + || model.equals("SM-G3609") + || model.equals("SM-G360F") + || model.equals("SM-G360FY") + || model.equals("SM-G360GY") + || model.equals("SM-G360H") + || model.equals("SM-G360HU") + || model.equals("SM-G360M") + || model.equals("SM-G360P") + || model.equals("SM-G360R6") + || model.equals("SM-G360T") + || model.equals("SM-G360T1") + || model.equals("SM-G360V") + || model.equals("SM-G361F") + || model.equals("SM-G361H") + || model.equals("SM-G361HU") + || model.equals("SM-G361M") + || model.equals("SM-S820L")))) { + return "Galaxy Core Prime"; + } + if ((codename != null && (codename.equals("kanas") + || codename.equals("kanas3g") + || codename.equals("kanas3gcmcc") + || codename.equals("kanas3gctc") + || codename.equals("kanas3gnfc"))) + || (model != null && (model.equals("SM-G3556D") + || model.equals("SM-G3558") + || model.equals("SM-G3559") + || model.equals("SM-G355H") + || model.equals("SM-G355HN") + || model.equals("SM-G355HQ") + || model.equals("SM-G355M")))) { + return "Galaxy Core2"; + } + if ((codename != null && (codename.equals("e53g") + || codename.equals("e5lte") + || codename.equals("e5ltetfnvzw") + || codename.equals("e5ltetw"))) + || (model != null && (model.equals("SM-E500F") + || model.equals("SM-E500H") + || model.equals("SM-E500M") + || model.equals("SM-E500YZ") + || model.equals("SM-S978L")))) { + return "Galaxy E5"; + } + if ((codename != null && (codename.equals("e73g") + || codename.equals("e7lte") + || codename.equals("e7ltechn") + || codename.equals("e7ltectc") + || codename.equals("e7ltehktw"))) + || (model != null && (model.equals("SM-E7000") + || model.equals("SM-E7009") + || model.equals("SM-E700F") + || model.equals("SM-E700H") + || model.equals("SM-E700M")))) { + return "Galaxy E7"; + } + if ((codename != null && (codename.equals("SCH-I629") + || codename.equals("nevis") + || codename.equals("nevis3g") + || codename.equals("nevis3gcmcc") + || codename.equals("nevisds") + || codename.equals("nevisnvess") + || codename.equals("nevisp") + || codename.equals("nevisvess") + || codename.equals("nevisw"))) + || (model != null && (model.equals("GT-S6790") + || model.equals("GT-S6790E") + || model.equals("GT-S6790L") + || model.equals("GT-S6790N") + || model.equals("GT-S6810") + || model.equals("GT-S6810B") + || model.equals("GT-S6810E") + || model.equals("GT-S6810L") + || model.equals("GT-S6810M") + || model.equals("GT-S6810P") + || model.equals("GT-S6812") + || model.equals("GT-S6812B") + || model.equals("GT-S6812C") + || model.equals("GT-S6812i") + || model.equals("GT-S6818") + || model.equals("GT-S6818V") + || model.equals("SCH-I629")))) { + return "Galaxy Fame"; + } + if ((codename != null && codename.equals("grandprimelteatt")) + || (model != null && model.equals("SAMSUNG-SM-G530A"))) { + return "Galaxy Go Prime"; + } + if ((codename != null && (codename.equals("baffinlite") + || codename.equals("baffinlitedtv") + || codename.equals("baffinq3g"))) + || (model != null && (model.equals("GT-I9060") + || model.equals("GT-I9060L") + || model.equals("GT-I9063T") + || model.equals("GT-I9082C") + || model.equals("GT-I9168") + || model.equals("GT-I9168I")))) { + return "Galaxy Grand Neo"; + } + if ((codename != null && (codename.equals("fortuna3g") + || codename.equals("fortuna3gdtv") + || codename.equals("fortunalte") + || codename.equals("fortunaltectc") + || codename.equals("fortunaltezh") + || codename.equals("fortunaltezt") + || codename.equals("fortunave3g") + || codename.equals("gprimelteacg") + || codename.equals("gprimeltecan") + || codename.equals("gprimeltemtr") + || codename.equals("gprimeltespr") + || codename.equals("gprimeltetfnvzw") + || codename.equals("gprimeltetmo") + || codename.equals("gprimelteusc") + || codename.equals("grandprimelte") + || codename.equals("grandprimelteaio") + || codename.equals("grandprimeve3g") + || codename.equals("grandprimeve3gdtv") + || codename.equals("grandprimevelte") + || codename.equals("grandprimevelteltn") + || codename.equals("grandprimeveltezt"))) + || (model != null && (model.equals("SAMSUNG-SM-G530AZ") + || model.equals("SM-G5306W") + || model.equals("SM-G5308W") + || model.equals("SM-G5309W") + || model.equals("SM-G530BT") + || model.equals("SM-G530F") + || model.equals("SM-G530FZ") + || model.equals("SM-G530H") + || model.equals("SM-G530M") + || model.equals("SM-G530MU") + || model.equals("SM-G530P") + || model.equals("SM-G530R4") + || model.equals("SM-G530R7") + || model.equals("SM-G530T") + || model.equals("SM-G530T1") + || model.equals("SM-G530W") + || model.equals("SM-G530Y") + || model.equals("SM-G531BT") + || model.equals("SM-G531F") + || model.equals("SM-G531H") + || model.equals("SM-G531M") + || model.equals("SM-G531Y") + || model.equals("SM-S920L") + || model.equals("gprimelteacg")))) { + return "Galaxy Grand Prime"; + } + if ((codename != null && (codename.equals("ms013g") + || codename.equals("ms013gdtv") + || codename.equals("ms013gss") + || codename.equals("ms01lte") + || codename.equals("ms01ltektt") + || codename.equals("ms01ltelgt") + || codename.equals("ms01lteskt"))) + || (model != null && (model.equals("SM-G710") + || model.equals("SM-G7102") + || model.equals("SM-G7102T") + || model.equals("SM-G7105") + || model.equals("SM-G7105H") + || model.equals("SM-G7105L") + || model.equals("SM-G7106") + || model.equals("SM-G7108") + || model.equals("SM-G7109") + || model.equals("SM-G710K") + || model.equals("SM-G710L") + || model.equals("SM-G710S")))) { + return "Galaxy Grand2"; + } + if ((codename != null && (codename.equals("j13g") + || codename.equals("j13gtfnvzw") + || codename.equals("j1lte") + || codename.equals("j1nlte") + || codename.equals("j1qltevzw") + || codename.equals("j1xlte") + || codename.equals("j1xlteaio") + || codename.equals("j1xlteatt") + || codename.equals("j1xltecan") + || codename.equals("j1xqltespr") + || codename.equals("j1xqltetfnvzw"))) + || (model != null && (model.equals("SAMSUNG-SM-J120A") + || model.equals("SAMSUNG-SM-J120AZ") + || model.equals("SM-J100F") + || model.equals("SM-J100FN") + || model.equals("SM-J100G") + || model.equals("SM-J100H") + || model.equals("SM-J100M") + || model.equals("SM-J100ML") + || model.equals("SM-J100MU") + || model.equals("SM-J100VPP") + || model.equals("SM-J100Y") + || model.equals("SM-J120F") + || model.equals("SM-J120FN") + || model.equals("SM-J120M") + || model.equals("SM-J120P") + || model.equals("SM-J120W") + || model.equals("SM-S120VL") + || model.equals("SM-S777C")))) { + return "Galaxy J1"; + } + if ((codename != null && (codename.equals("j1acelte") + || codename.equals("j1acelteltn") + || codename.equals("j1acevelte") + || codename.equals("j1pop3g"))) + || (model != null && (model.equals("SM-J110F") + || model.equals("SM-J110G") + || model.equals("SM-J110H") + || model.equals("SM-J110L") + || model.equals("SM-J110M") + || model.equals("SM-J111F") + || model.equals("SM-J111M")))) { + return "Galaxy J1 Ace"; + } + if ((codename != null && (codename.equals("j53g") + || codename.equals("j5lte") + || codename.equals("j5ltechn") + || codename.equals("j5ltekx") + || codename.equals("j5nlte") + || codename.equals("j5ylte"))) + || (model != null && (model.equals("SM-J5007") + || model.equals("SM-J5008") + || model.equals("SM-J500F") + || model.equals("SM-J500FN") + || model.equals("SM-J500G") + || model.equals("SM-J500H") + || model.equals("SM-J500M") + || model.equals("SM-J500N0") + || model.equals("SM-J500Y")))) { + return "Galaxy J5"; + } + if ((codename != null && (codename.equals("j75ltektt") + || codename.equals("j7e3g") + || codename.equals("j7elte") + || codename.equals("j7ltechn"))) + || (model != null && (model.equals("SM-J7008") + || model.equals("SM-J700F") + || model.equals("SM-J700H") + || model.equals("SM-J700K") + || model.equals("SM-J700M")))) { + return "Galaxy J7"; + } + if ((codename != null && (codename.equals("maguro") + || codename.equals("toro") + || codename.equals("toroplus"))) + || (model != null && (model.equals("Galaxy X")))) { + return "Galaxy Nexus"; + } + if ((codename != null && (codename.equals("lt033g") + || codename.equals("lt03ltektt") + || codename.equals("lt03ltelgt") + || codename.equals("lt03lteskt") + || codename.equals("p4notelte") + || codename.equals("p4noteltektt") + || codename.equals("p4noteltelgt") + || codename.equals("p4notelteskt") + || codename.equals("p4noteltespr") + || codename.equals("p4notelteusc") + || codename.equals("p4noteltevzw") + || codename.equals("p4noterf") + || codename.equals("p4noterfktt") + || codename.equals("p4notewifi") + || codename.equals("p4notewifi43241any") + || codename.equals("p4notewifiany") + || codename.equals("p4notewifiktt") + || codename.equals("p4notewifiww"))) + || (model != null && (model.equals("GT-N8000") + || model.equals("GT-N8005") + || model.equals("GT-N8010") + || model.equals("GT-N8013") + || model.equals("GT-N8020") + || model.equals("SCH-I925") + || model.equals("SCH-I925U") + || model.equals("SHV-E230K") + || model.equals("SHV-E230L") + || model.equals("SHV-E230S") + || model.equals("SHW-M480K") + || model.equals("SHW-M480W") + || model.equals("SHW-M485W") + || model.equals("SHW-M486W") + || model.equals("SM-P601") + || model.equals("SM-P602") + || model.equals("SM-P605K") + || model.equals("SM-P605L") + || model.equals("SM-P605S") + || model.equals("SPH-P600")))) { + return "Galaxy Note 10.1"; + } + if ((codename != null && (codename.equals("SC-01G") + || codename.equals("SCL24") + || codename.equals("tbeltektt") + || codename.equals("tbeltelgt") + || codename.equals("tbelteskt") + || codename.equals("tblte") + || codename.equals("tblteatt") + || codename.equals("tbltecan") + || codename.equals("tbltechn") + || codename.equals("tbltespr") + || codename.equals("tbltetmo") + || codename.equals("tblteusc") + || codename.equals("tbltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-N915A") + || model.equals("SC-01G") + || model.equals("SCL24") + || model.equals("SM-N9150") + || model.equals("SM-N915F") + || model.equals("SM-N915FY") + || model.equals("SM-N915G") + || model.equals("SM-N915K") + || model.equals("SM-N915L") + || model.equals("SM-N915P") + || model.equals("SM-N915R4") + || model.equals("SM-N915S") + || model.equals("SM-N915T") + || model.equals("SM-N915T3") + || model.equals("SM-N915V") + || model.equals("SM-N915W8") + || model.equals("SM-N915X")))) { + return "Galaxy Note Edge"; + } + if ((codename != null && (codename.equals("v1a3g") + || codename.equals("v1awifi") + || codename.equals("v1awifikx") + || codename.equals("viennalte") + || codename.equals("viennalteatt") + || codename.equals("viennaltekx") + || codename.equals("viennaltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-P907A") + || model.equals("SM-P900") + || model.equals("SM-P901") + || model.equals("SM-P905") + || model.equals("SM-P905F0") + || model.equals("SM-P905M") + || model.equals("SM-P905V")))) { + return "Galaxy Note Pro 12.2"; + } + if ((codename != null && (codename.equals("tre3caltektt") + || codename.equals("tre3caltelgt") + || codename.equals("tre3calteskt") + || codename.equals("tre3g") + || codename.equals("trelte") + || codename.equals("treltektt") + || codename.equals("treltelgt") + || codename.equals("trelteskt") + || codename.equals("trhplte") + || codename.equals("trlte") + || codename.equals("trlteatt") + || codename.equals("trltecan") + || codename.equals("trltechn") + || codename.equals("trltechnzh") + || codename.equals("trltespr") + || codename.equals("trltetmo") + || codename.equals("trlteusc") + || codename.equals("trltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-N910A") + || model.equals("SM-N9100") + || model.equals("SM-N9106W") + || model.equals("SM-N9108V") + || model.equals("SM-N9109W") + || model.equals("SM-N910C") + || model.equals("SM-N910F") + || model.equals("SM-N910G") + || model.equals("SM-N910H") + || model.equals("SM-N910K") + || model.equals("SM-N910L") + || model.equals("SM-N910P") + || model.equals("SM-N910R4") + || model.equals("SM-N910S") + || model.equals("SM-N910T") + || model.equals("SM-N910T2") + || model.equals("SM-N910T3") + || model.equals("SM-N910U") + || model.equals("SM-N910V") + || model.equals("SM-N910W8") + || model.equals("SM-N910X") + || model.equals("SM-N916K") + || model.equals("SM-N916L") + || model.equals("SM-N916S")))) { + return "Galaxy Note4"; + } + if ((codename != null && (codename.equals("noblelte") + || codename.equals("noblelteacg") + || codename.equals("noblelteatt") + || codename.equals("nobleltebmc") + || codename.equals("nobleltechn") + || codename.equals("nobleltecmcc") + || codename.equals("nobleltehk") + || codename.equals("nobleltektt") + || codename.equals("nobleltelgt") + || codename.equals("nobleltelra") + || codename.equals("noblelteskt") + || codename.equals("nobleltespr") + || codename.equals("nobleltetmo") + || codename.equals("noblelteusc") + || codename.equals("nobleltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-N920A") + || model.equals("SM-N9200") + || model.equals("SM-N9208") + || model.equals("SM-N920C") + || model.equals("SM-N920F") + || model.equals("SM-N920G") + || model.equals("SM-N920I") + || model.equals("SM-N920K") + || model.equals("SM-N920L") + || model.equals("SM-N920P") + || model.equals("SM-N920R4") + || model.equals("SM-N920R6") + || model.equals("SM-N920R7") + || model.equals("SM-N920S") + || model.equals("SM-N920T") + || model.equals("SM-N920V") + || model.equals("SM-N920W8") + || model.equals("SM-N920X")))) { + return "Galaxy Note5"; + } + if ((codename != null && (codename.equals("SC-01J") + || codename.equals("SCV34") + || codename.equals("gracelte") + || codename.equals("graceltektt") + || codename.equals("graceltelgt") + || codename.equals("gracelteskt") + || codename.equals("graceqlteacg") + || codename.equals("graceqlteatt") + || codename.equals("graceqltebmc") + || codename.equals("graceqltechn") + || codename.equals("graceqltedcm") + || codename.equals("graceqltelra") + || codename.equals("graceqltespr") + || codename.equals("graceqltetfnvzw") + || codename.equals("graceqltetmo") + || codename.equals("graceqlteue") + || codename.equals("graceqlteusc") + || codename.equals("graceqltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-N930A") + || model.equals("SC-01J") + || model.equals("SCV34") + || model.equals("SGH-N037") + || model.equals("SM-N9300") + || model.equals("SM-N930F") + || model.equals("SM-N930K") + || model.equals("SM-N930L") + || model.equals("SM-N930P") + || model.equals("SM-N930R4") + || model.equals("SM-N930R6") + || model.equals("SM-N930R7") + || model.equals("SM-N930S") + || model.equals("SM-N930T") + || model.equals("SM-N930U") + || model.equals("SM-N930V") + || model.equals("SM-N930VL") + || model.equals("SM-N930W8") + || model.equals("SM-N930X")))) { + return "Galaxy Note7"; + } + if ((codename != null && (codename.equals("SC-01K") + || codename.equals("SCV37") + || codename.equals("greatlte") + || codename.equals("greatlteks") + || codename.equals("greatqlte") + || codename.equals("greatqltechn") + || codename.equals("greatqltecmcc") + || codename.equals("greatqltecs") + || codename.equals("greatqlteue"))) + || (model != null && (model.equals("SC-01K") + || model.equals("SCV37") + || model.equals("SM-N9500") + || model.equals("SM-N9508") + || model.equals("SM-N950F") + || model.equals("SM-N950N") + || model.equals("SM-N950U") + || model.equals("SM-N950U1") + || model.equals("SM-N950W") + || model.equals("SM-N950XN")))) { + return "Galaxy Note8"; + } + if ((codename != null && (codename.equals("o5lte") + || codename.equals("o5ltechn") + || codename.equals("o5prolte") + || codename.equals("on5ltemtr") + || codename.equals("on5ltetfntmo") + || codename.equals("on5ltetmo"))) + || (model != null && (model.equals("SM-G5500") + || model.equals("SM-G550FY") + || model.equals("SM-G550T") + || model.equals("SM-G550T1") + || model.equals("SM-G550T2") + || model.equals("SM-S550TL")))) { + return "Galaxy On5"; + } + if ((codename != null && (codename.equals("o7lte") + || codename.equals("o7ltechn") + || codename.equals("on7elte"))) + || (model != null && (model.equals("SM-G6000") + || model.equals("SM-G600F") + || model.equals("SM-G600FY")))) { + return "Galaxy On7"; + } + if ((codename != null && (codename.equals("GT-I9000") + || codename.equals("GT-I9000B") + || codename.equals("GT-I9000M") + || codename.equals("GT-I9000T") + || codename.equals("GT-I9003") + || codename.equals("GT-I9003L") + || codename.equals("GT-I9008L") + || codename.equals("GT-I9010") + || codename.equals("GT-I9018") + || codename.equals("GT-I9050") + || codename.equals("SC-02B") + || codename.equals("SCH-I500") + || codename.equals("SCH-S950C") + || codename.equals("SCH-i909") + || codename.equals("SGH-I897") + || codename.equals("SGH-T959V") + || codename.equals("SGH-T959W") + || codename.equals("SHW-M110S") + || codename.equals("SHW-M190S") + || codename.equals("SPH-D700") + || codename.equals("loganlte"))) + || (model != null && (model.equals("GT-I9000") + || model.equals("GT-I9000B") + || model.equals("GT-I9000M") + || model.equals("GT-I9000T") + || model.equals("GT-I9003") + || model.equals("GT-I9003L") + || model.equals("GT-I9008L") + || model.equals("GT-I9010") + || model.equals("GT-I9018") + || model.equals("GT-I9050") + || model.equals("GT-S7275") + || model.equals("SAMSUNG-SGH-I897") + || model.equals("SC-02B") + || model.equals("SCH-I500") + || model.equals("SCH-S950C") + || model.equals("SCH-i909") + || model.equals("SGH-T959V") + || model.equals("SGH-T959W") + || model.equals("SHW-M110S") + || model.equals("SHW-M190S") + || model.equals("SPH-D700")))) { + return "Galaxy S"; + } + if ((codename != null && (codename.equals("kylechn") + || codename.equals("kyleopen") + || codename.equals("kyletdcmcc"))) + || (model != null && (model.equals("GT-S7562") + || model.equals("GT-S7568")))) { + return "Galaxy S Duos"; + } + if ((codename != null && (codename.equals("kyleprods"))) + || (model != null && (model.equals("GT-S7582") + || model.equals("GT-S7582L")))) { + return "Galaxy S Duos2"; + } + if ((codename != null && codename.equals("vivalto3gvn")) + || (model != null && model.equals("SM-G313HZ"))) { + return "Galaxy S Duos3"; + } + if ((codename != null && (codename.equals("SC-03E") + || codename.equals("c1att") + || codename.equals("c1ktt") + || codename.equals("c1lgt") + || codename.equals("c1skt") + || codename.equals("d2att") + || codename.equals("d2can") + || codename.equals("d2cri") + || codename.equals("d2dcm") + || codename.equals("d2lteMetroPCS") + || codename.equals("d2lterefreshspr") + || codename.equals("d2ltetmo") + || codename.equals("d2mtr") + || codename.equals("d2spi") + || codename.equals("d2spr") + || codename.equals("d2tfnspr") + || codename.equals("d2tfnvzw") + || codename.equals("d2tmo") + || codename.equals("d2usc") + || codename.equals("d2vmu") + || codename.equals("d2vzw") + || codename.equals("d2xar") + || codename.equals("m0") + || codename.equals("m0apt") + || codename.equals("m0chn") + || codename.equals("m0cmcc") + || codename.equals("m0ctc") + || codename.equals("m0ctcduos") + || codename.equals("m0skt") + || codename.equals("m3") + || codename.equals("m3dcm"))) + || (model != null && (model.equals("GT-I9300") + || model.equals("GT-I9300T") + || model.equals("GT-I9305") + || model.equals("GT-I9305N") + || model.equals("GT-I9305T") + || model.equals("GT-I9308") + || model.equals("Gravity") + || model.equals("GravityQuad") + || model.equals("SAMSUNG-SGH-I747") + || model.equals("SC-03E") + || model.equals("SC-06D") + || model.equals("SCH-I535") + || model.equals("SCH-I535PP") + || model.equals("SCH-I939") + || model.equals("SCH-I939D") + || model.equals("SCH-L710") + || model.equals("SCH-R530C") + || model.equals("SCH-R530M") + || model.equals("SCH-R530U") + || model.equals("SCH-R530X") + || model.equals("SCH-S960L") + || model.equals("SCH-S968C") + || model.equals("SGH-I747M") + || model.equals("SGH-I748") + || model.equals("SGH-T999") + || model.equals("SGH-T999L") + || model.equals("SGH-T999N") + || model.equals("SGH-T999V") + || model.equals("SHV-E210K") + || model.equals("SHV-E210L") + || model.equals("SHV-E210S") + || model.equals("SHW-M440S") + || model.equals("SPH-L710") + || model.equals("SPH-L710T")))) { + return "Galaxy S3"; + } + if ((codename != null && (codename.equals("golden") + || codename.equals("goldenlteatt") + || codename.equals("goldenltebmc") + || codename.equals("goldenltevzw") + || codename.equals("goldenve3g"))) + || (model != null && (model.equals("GT-I8190") + || model.equals("GT-I8190L") + || model.equals("GT-I8190N") + || model.equals("GT-I8190T") + || model.equals("GT-I8200L") + || model.equals("SAMSUNG-SM-G730A") + || model.equals("SM-G730V") + || model.equals("SM-G730W8")))) { + return "Galaxy S3 Mini"; + } + if ((codename != null && (codename.equals("goldenve3g") + || codename.equals("goldenvess3g"))) + || (model != null && (model.equals("GT-I8200") + || model.equals("GT-I8200N") + || model.equals("GT-I8200Q")))) { + return "Galaxy S3 Mini Value Edition"; + } + if ((codename != null && (codename.equals("s3ve3g") + || codename.equals("s3ve3gdd") + || codename.equals("s3ve3gds") + || codename.equals("s3ve3gdsdd"))) + || (model != null && (model.equals("GT-I9300I") + || model.equals("GT-I9301I") + || model.equals("GT-I9301Q")))) { + return "Galaxy S3 Neo"; + } + if ((codename != null && (codename.equals("SC-04E") + || codename.equals("ja3g") + || codename.equals("ja3gduosctc") + || codename.equals("jaltektt") + || codename.equals("jaltelgt") + || codename.equals("jalteskt") + || codename.equals("jflte") + || codename.equals("jflteMetroPCS") + || codename.equals("jflteaio") + || codename.equals("jflteatt") + || codename.equals("jfltecan") + || codename.equals("jfltecri") + || codename.equals("jfltecsp") + || codename.equals("jfltelra") + || codename.equals("jflterefreshspr") + || codename.equals("jfltespr") + || codename.equals("jfltetfnatt") + || codename.equals("jfltetfntmo") + || codename.equals("jfltetmo") + || codename.equals("jflteusc") + || codename.equals("jfltevzw") + || codename.equals("jfltevzwpp") + || codename.equals("jftdd") + || codename.equals("jfvelte") + || codename.equals("jfwifi") + || codename.equals("jsglte") + || codename.equals("ks01lte") + || codename.equals("ks01ltektt") + || codename.equals("ks01ltelgt"))) + || (model != null && (model.equals("GT-I9500") + || model.equals("GT-I9505") + || model.equals("GT-I9505X") + || model.equals("GT-I9506") + || model.equals("GT-I9507") + || model.equals("GT-I9507V") + || model.equals("GT-I9508") + || model.equals("GT-I9508C") + || model.equals("GT-I9508V") + || model.equals("GT-I9515") + || model.equals("GT-I9515L") + || model.equals("SAMSUNG-SGH-I337") + || model.equals("SAMSUNG-SGH-I337Z") + || model.equals("SC-04E") + || model.equals("SCH-I545") + || model.equals("SCH-I545L") + || model.equals("SCH-I545PP") + || model.equals("SCH-I959") + || model.equals("SCH-R970") + || model.equals("SCH-R970C") + || model.equals("SCH-R970X") + || model.equals("SGH-I337M") + || model.equals("SGH-M919") + || model.equals("SGH-M919N") + || model.equals("SGH-M919V") + || model.equals("SGH-S970G") + || model.equals("SHV-E300K") + || model.equals("SHV-E300L") + || model.equals("SHV-E300S") + || model.equals("SHV-E330K") + || model.equals("SHV-E330L") + || model.equals("SM-S975L") + || model.equals("SPH-L720") + || model.equals("SPH-L720T")))) { + return "Galaxy S4"; + } + if ((codename != null && (codename.equals("serrano3g") + || codename.equals("serranods") + || codename.equals("serranolte") + || codename.equals("serranoltebmc") + || codename.equals("serranoltektt") + || codename.equals("serranoltekx") + || codename.equals("serranoltelra") + || codename.equals("serranoltespr") + || codename.equals("serranolteusc") + || codename.equals("serranoltevzw") + || codename.equals("serranove3g") + || codename.equals("serranovelte") + || codename.equals("serranovolteatt"))) + || (model != null && (model.equals("GT-I9190") + || model.equals("GT-I9192") + || model.equals("GT-I9192I") + || model.equals("GT-I9195") + || model.equals("GT-I9195I") + || model.equals("GT-I9195L") + || model.equals("GT-I9195T") + || model.equals("GT-I9195X") + || model.equals("GT-I9197") + || model.equals("SAMSUNG-SGH-I257") + || model.equals("SCH-I435") + || model.equals("SCH-I435L") + || model.equals("SCH-R890") + || model.equals("SGH-I257M") + || model.equals("SHV-E370D") + || model.equals("SHV-E370K") + || model.equals("SPH-L520")))) { + return "Galaxy S4 Mini"; + } + if ((codename != null && (codename.equals("SC-04F") + || codename.equals("SCL23") + || codename.equals("k3g") + || codename.equals("klte") + || codename.equals("klteMetroPCS") + || codename.equals("klteacg") + || codename.equals("klteaio") + || codename.equals("klteatt") + || codename.equals("kltecan") + || codename.equals("klteduoszn") + || codename.equals("kltektt") + || codename.equals("kltelgt") + || codename.equals("kltelra") + || codename.equals("klteskt") + || codename.equals("kltespr") + || codename.equals("kltetfnvzw") + || codename.equals("kltetmo") + || codename.equals("klteusc") + || codename.equals("kltevzw") + || codename.equals("kwifi") + || codename.equals("lentisltektt") + || codename.equals("lentisltelgt") + || codename.equals("lentislteskt"))) + || (model != null && (model.equals("SAMSUNG-SM-G900A") + || model.equals("SAMSUNG-SM-G900AZ") + || model.equals("SC-04F") + || model.equals("SCL23") + || model.equals("SM-G9006W") + || model.equals("SM-G9008W") + || model.equals("SM-G9009W") + || model.equals("SM-G900F") + || model.equals("SM-G900FQ") + || model.equals("SM-G900H") + || model.equals("SM-G900I") + || model.equals("SM-G900K") + || model.equals("SM-G900L") + || model.equals("SM-G900M") + || model.equals("SM-G900MD") + || model.equals("SM-G900P") + || model.equals("SM-G900R4") + || model.equals("SM-G900R6") + || model.equals("SM-G900R7") + || model.equals("SM-G900S") + || model.equals("SM-G900T") + || model.equals("SM-G900T1") + || model.equals("SM-G900T3") + || model.equals("SM-G900T4") + || model.equals("SM-G900V") + || model.equals("SM-G900W8") + || model.equals("SM-G900X") + || model.equals("SM-G906K") + || model.equals("SM-G906L") + || model.equals("SM-G906S") + || model.equals("SM-S903VL")))) { + return "Galaxy S5"; + } + if ((codename != null && (codename.equals("s5neolte") + || codename.equals("s5neoltecan"))) + || (model != null && (model.equals("SM-G903F") + || model.equals("SM-G903M") + || model.equals("SM-G903W")))) { + return "Galaxy S5 Neo"; + } + if ((codename != null && (codename.equals("SC-05G") + || codename.equals("zeroflte") + || codename.equals("zeroflteacg") + || codename.equals("zeroflteaio") + || codename.equals("zeroflteatt") + || codename.equals("zerofltebmc") + || codename.equals("zerofltechn") + || codename.equals("zerofltectc") + || codename.equals("zerofltektt") + || codename.equals("zerofltelgt") + || codename.equals("zerofltelra") + || codename.equals("zerofltemtr") + || codename.equals("zeroflteskt") + || codename.equals("zerofltespr") + || codename.equals("zerofltetfnvzw") + || codename.equals("zerofltetmo") + || codename.equals("zeroflteusc") + || codename.equals("zerofltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-G920A") + || model.equals("SAMSUNG-SM-G920AZ") + || model.equals("SC-05G") + || model.equals("SM-G9200") + || model.equals("SM-G9208") + || model.equals("SM-G9209") + || model.equals("SM-G920F") + || model.equals("SM-G920I") + || model.equals("SM-G920K") + || model.equals("SM-G920L") + || model.equals("SM-G920P") + || model.equals("SM-G920R4") + || model.equals("SM-G920R6") + || model.equals("SM-G920R7") + || model.equals("SM-G920S") + || model.equals("SM-G920T") + || model.equals("SM-G920T1") + || model.equals("SM-G920V") + || model.equals("SM-G920W8") + || model.equals("SM-G920X") + || model.equals("SM-S906L") + || model.equals("SM-S907VL")))) { + return "Galaxy S6"; + } + if ((codename != null && (codename.equals("404SC") + || codename.equals("SC-04G") + || codename.equals("SCV31") + || codename.equals("zerolte") + || codename.equals("zerolteacg") + || codename.equals("zerolteatt") + || codename.equals("zeroltebmc") + || codename.equals("zeroltechn") + || codename.equals("zeroltektt") + || codename.equals("zeroltelgt") + || codename.equals("zeroltelra") + || codename.equals("zerolteskt") + || codename.equals("zeroltespr") + || codename.equals("zeroltetmo") + || codename.equals("zerolteusc") + || codename.equals("zeroltevzw"))) + || (model != null && (model.equals("404SC") + || model.equals("SAMSUNG-SM-G925A") + || model.equals("SC-04G") + || model.equals("SCV31") + || model.equals("SM-G9250") + || model.equals("SM-G925F") + || model.equals("SM-G925I") + || model.equals("SM-G925K") + || model.equals("SM-G925L") + || model.equals("SM-G925P") + || model.equals("SM-G925R4") + || model.equals("SM-G925R6") + || model.equals("SM-G925R7") + || model.equals("SM-G925S") + || model.equals("SM-G925T") + || model.equals("SM-G925V") + || model.equals("SM-G925W8") + || model.equals("SM-G925X")))) { + return "Galaxy S6 Edge"; + } + if ((codename != null && (codename.equals("zenlte") + || codename.equals("zenlteatt") + || codename.equals("zenltebmc") + || codename.equals("zenltechn") + || codename.equals("zenltektt") + || codename.equals("zenltekx") + || codename.equals("zenltelgt") + || codename.equals("zenlteskt") + || codename.equals("zenltespr") + || codename.equals("zenltetmo") + || codename.equals("zenlteusc") + || codename.equals("zenltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-G928A") + || model.equals("SM-G9280") + || model.equals("SM-G9287") + || model.equals("SM-G9287C") + || model.equals("SM-G928C") + || model.equals("SM-G928F") + || model.equals("SM-G928G") + || model.equals("SM-G928I") + || model.equals("SM-G928K") + || model.equals("SM-G928L") + || model.equals("SM-G928N0") + || model.equals("SM-G928P") + || model.equals("SM-G928R4") + || model.equals("SM-G928S") + || model.equals("SM-G928T") + || model.equals("SM-G928V") + || model.equals("SM-G928W8") + || model.equals("SM-G928X")))) { + return "Galaxy S6 Edge+"; + } + if ((codename != null && (codename.equals("herolte") + || codename.equals("heroltebmc") + || codename.equals("heroltektt") + || codename.equals("heroltelgt") + || codename.equals("herolteskt") + || codename.equals("heroqlteacg") + || codename.equals("heroqlteaio") + || codename.equals("heroqlteatt") + || codename.equals("heroqltecctvzw") + || codename.equals("heroqltechn") + || codename.equals("heroqltelra") + || codename.equals("heroqltemtr") + || codename.equals("heroqltespr") + || codename.equals("heroqltetfnvzw") + || codename.equals("heroqltetmo") + || codename.equals("heroqlteue") + || codename.equals("heroqlteusc") + || codename.equals("heroqltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-G930A") + || model.equals("SAMSUNG-SM-G930AZ") + || model.equals("SM-G9300") + || model.equals("SM-G9308") + || model.equals("SM-G930F") + || model.equals("SM-G930K") + || model.equals("SM-G930L") + || model.equals("SM-G930P") + || model.equals("SM-G930R4") + || model.equals("SM-G930R6") + || model.equals("SM-G930R7") + || model.equals("SM-G930S") + || model.equals("SM-G930T") + || model.equals("SM-G930T1") + || model.equals("SM-G930U") + || model.equals("SM-G930V") + || model.equals("SM-G930VC") + || model.equals("SM-G930VL") + || model.equals("SM-G930W8") + || model.equals("SM-G930X")))) { + return "Galaxy S7"; + } + if ((codename != null && (codename.equals("SC-02H") + || codename.equals("SCV33") + || codename.equals("hero2lte") + || codename.equals("hero2ltebmc") + || codename.equals("hero2ltektt") + || codename.equals("hero2ltelgt") + || codename.equals("hero2lteskt") + || codename.equals("hero2qlteatt") + || codename.equals("hero2qltecctvzw") + || codename.equals("hero2qltechn") + || codename.equals("hero2qltespr") + || codename.equals("hero2qltetmo") + || codename.equals("hero2qlteue") + || codename.equals("hero2qlteusc") + || codename.equals("hero2qltevzw"))) + || (model != null && (model.equals("SAMSUNG-SM-G935A") + || model.equals("SC-02H") + || model.equals("SCV33") + || model.equals("SM-G9350") + || model.equals("SM-G935F") + || model.equals("SM-G935K") + || model.equals("SM-G935L") + || model.equals("SM-G935P") + || model.equals("SM-G935R4") + || model.equals("SM-G935S") + || model.equals("SM-G935T") + || model.equals("SM-G935U") + || model.equals("SM-G935V") + || model.equals("SM-G935VC") + || model.equals("SM-G935W8") + || model.equals("SM-G935X")))) { + return "Galaxy S7 Edge"; + } + if ((codename != null && (codename.equals("SC-02J") + || codename.equals("SCV36") + || codename.equals("dreamlte") + || codename.equals("dreamlteks") + || codename.equals("dreamqltecan") + || codename.equals("dreamqltechn") + || codename.equals("dreamqltecmcc") + || codename.equals("dreamqltesq") + || codename.equals("dreamqlteue"))) + || (model != null && (model.equals("SC-02J") + || model.equals("SCV36") + || model.equals("SM-G9500") + || model.equals("SM-G9508") + || model.equals("SM-G950F") + || model.equals("SM-G950N") + || model.equals("SM-G950U") + || model.equals("SM-G950U1") + || model.equals("SM-G950W")))) { + return "Galaxy S8"; + } + if ((codename != null && (codename.equals("SC-03J") + || codename.equals("SCV35") + || codename.equals("dream2lte") + || codename.equals("dream2lteks") + || codename.equals("dream2qltecan") + || codename.equals("dream2qltechn") + || codename.equals("dream2qltesq") + || codename.equals("dream2qlteue"))) + || (model != null && (model.equals("SC-03J") + || model.equals("SCV35") + || model.equals("SM-G9550") + || model.equals("SM-G955F") + || model.equals("SM-G955N") + || model.equals("SM-G955U") + || model.equals("SM-G955U1") + || model.equals("SM-G955W")))) { + return "Galaxy S8+"; + } + if ((codename != null && (codename.equals("starlte") + || codename.equals("starlteks") + || codename.equals("starqltechn") + || codename.equals("starqltecmcc") + || codename.equals("starqltecs") + || codename.equals("starqltesq") + || codename.equals("starqlteue"))) + || (model != null && (model.equals("SM-G9600") + || model.equals("SM-G9608") + || model.equals("SM-G960F") + || model.equals("SM-G960N") + || model.equals("SM-G960U") + || model.equals("SM-G960U1") + || model.equals("SM-G960W")))) { + return "Galaxy S9"; + } + if ((codename != null && (codename.equals("star2lte") + || codename.equals("star2lteks") + || codename.equals("star2qltechn") + || codename.equals("star2qltecs") + || codename.equals("star2qltesq") + || codename.equals("star2qlteue"))) + || (model != null && (model.equals("SM-G9650") + || model.equals("SM-G965F") + || model.equals("SM-G965N") + || model.equals("SM-G965U") + || model.equals("SM-G965U1") + || model.equals("SM-G965W")))) { + return "Galaxy S9+"; + } + if ((codename != null && (codename.equals("GT-P7500") + || codename.equals("GT-P7500D") + || codename.equals("GT-P7503") + || codename.equals("GT-P7510") + || codename.equals("SC-01D") + || codename.equals("SCH-I905") + || codename.equals("SGH-T859") + || codename.equals("SHW-M300W") + || codename.equals("SHW-M380K") + || codename.equals("SHW-M380S") + || codename.equals("SHW-M380W"))) + || (model != null && (model.equals("GT-P7500") + || model.equals("GT-P7500D") + || model.equals("GT-P7503") + || model.equals("GT-P7510") + || model.equals("SC-01D") + || model.equals("SCH-I905") + || model.equals("SGH-T859") + || model.equals("SHW-M300W") + || model.equals("SHW-M380K") + || model.equals("SHW-M380S") + || model.equals("SHW-M380W")))) { + return "Galaxy Tab 10.1"; + } + if ((codename != null && (codename.equals("GT-P6200") + || codename.equals("GT-P6200L") + || codename.equals("GT-P6201") + || codename.equals("GT-P6210") + || codename.equals("GT-P6211") + || codename.equals("SC-02D") + || codename.equals("SGH-T869") + || codename.equals("SHW-M430W"))) + || (model != null && (model.equals("GT-P6200") + || model.equals("GT-P6200L") + || model.equals("GT-P6201") + || model.equals("GT-P6210") + || model.equals("GT-P6211") + || model.equals("SC-02D") + || model.equals("SGH-T869") + || model.equals("SHW-M430W")))) { + return "Galaxy Tab 7.0 Plus"; + } + if ((codename != null && (codename.equals("gteslteatt") + || codename.equals("gtesltebmc") + || codename.equals("gtesltelgt") + || codename.equals("gteslteskt") + || codename.equals("gtesltetmo") + || codename.equals("gtesltetw") + || codename.equals("gtesltevzw") + || codename.equals("gtesqltespr") + || codename.equals("gtesqlteusc"))) + || (model != null && (model.equals("SAMSUNG-SM-T377A") + || model.equals("SM-T375L") + || model.equals("SM-T375S") + || model.equals("SM-T3777") + || model.equals("SM-T377P") + || model.equals("SM-T377R4") + || model.equals("SM-T377T") + || model.equals("SM-T377V") + || model.equals("SM-T377W")))) { + return "Galaxy Tab E 8.0"; + } + if ((codename != null && (codename.equals("gtel3g") + || codename.equals("gtelltevzw") + || codename.equals("gtelwifi") + || codename.equals("gtelwifichn") + || codename.equals("gtelwifiue"))) + || (model != null && (model.equals("SM-T560") + || model.equals("SM-T560NU") + || model.equals("SM-T561") + || model.equals("SM-T561M") + || model.equals("SM-T561Y") + || model.equals("SM-T562") + || model.equals("SM-T567V")))) { + return "Galaxy Tab E 9.6"; + } + if ((codename != null && (codename.equals("403SC") + || codename.equals("degas2wifi") + || codename.equals("degas2wifibmwchn") + || codename.equals("degas3g") + || codename.equals("degaslte") + || codename.equals("degasltespr") + || codename.equals("degasltevzw") + || codename.equals("degasvelte") + || codename.equals("degasveltechn") + || codename.equals("degaswifi") + || codename.equals("degaswifibmwzc") + || codename.equals("degaswifidtv") + || codename.equals("degaswifiopenbnn") + || codename.equals("degaswifiue"))) + || (model != null && (model.equals("403SC") + || model.equals("SM-T230") + || model.equals("SM-T230NT") + || model.equals("SM-T230NU") + || model.equals("SM-T230NW") + || model.equals("SM-T230NY") + || model.equals("SM-T230X") + || model.equals("SM-T231") + || model.equals("SM-T232") + || model.equals("SM-T235") + || model.equals("SM-T235Y") + || model.equals("SM-T237P") + || model.equals("SM-T237V") + || model.equals("SM-T239") + || model.equals("SM-T2397") + || model.equals("SM-T239C") + || model.equals("SM-T239M")))) { + return "Galaxy Tab4 7.0"; + } + if ((codename != null && (codename.equals("gvlte") + || codename.equals("gvlteatt") + || codename.equals("gvltevzw") + || codename.equals("gvltexsp") + || codename.equals("gvwifijpn") + || codename.equals("gvwifiue"))) + || (model != null && (model.equals("SAMSUNG-SM-T677A") + || model.equals("SM-T670") + || model.equals("SM-T677") + || model.equals("SM-T677V")))) { + return "Galaxy View"; + } + if ((codename != null && codename.equals("manta"))) { + return "Nexus 10"; + } + // ---------------------------------------------------------------------------- + // Sony + if ((codename != null && (codename.equals("D2104") + || codename.equals("D2105"))) + || (model != null && (model.equals("D2104") + || model.equals("D2105")))) { + return "Xperia E1 dual"; + } + if ((codename != null && (codename.equals("D2202") + || codename.equals("D2203") + || codename.equals("D2206") + || codename.equals("D2243"))) + || (model != null && (model.equals("D2202") + || model.equals("D2203") + || model.equals("D2206") + || model.equals("D2243")))) { + return "Xperia E3"; + } + if ((codename != null && (codename.equals("E5603") + || codename.equals("E5606") + || codename.equals("E5653"))) + || (model != null && (model.equals("E5603") + || model.equals("E5606") + || model.equals("E5653")))) { + return "Xperia M5"; + } + if ((codename != null && (codename.equals("E5633") + || codename.equals("E5643") + || codename.equals("E5663"))) + || (model != null && (model.equals("E5633") + || model.equals("E5643") + || model.equals("E5663")))) { + return "Xperia M5 Dual"; + } + if ((codename != null && codename.equals("LT26i")) + || (model != null && model.equals("LT26i"))) { + return "Xperia S"; + } + if ((codename != null && (codename.equals("D5303") + || codename.equals("D5306") + || codename.equals("D5316") + || codename.equals("D5316N") + || codename.equals("D5322"))) + || (model != null && (model.equals("D5303") + || model.equals("D5306") + || model.equals("D5316") + || model.equals("D5316N") + || model.equals("D5322")))) { + return "Xperia T2 Ultra"; + } + if ((codename != null && (codename.equals("txs03"))) + || (model != null && (model.equals("SGPT12") + || model.equals("SGPT13")))) { + return "Xperia Tablet S"; + } + if ((codename != null && (codename.equals("SGP311") + || codename.equals("SGP312") + || codename.equals("SGP321") + || codename.equals("SGP351"))) + || (model != null && (model.equals("SGP311") + || model.equals("SGP312") + || model.equals("SGP321") + || model.equals("SGP351")))) { + return "Xperia Tablet Z"; + } + if ((codename != null && (codename.equals("D6502") + || codename.equals("D6503") + || codename.equals("D6543") + || codename.equals("SO-03F"))) + || (model != null && (model.equals("D6502") + || model.equals("D6503") + || model.equals("D6543") + || model.equals("SO-03F")))) { + return "Xperia Z2"; + } + if ((codename != null && (codename.equals("401SO") + || codename.equals("D6603") + || codename.equals("D6616") + || codename.equals("D6643") + || codename.equals("D6646") + || codename.equals("D6653") + || codename.equals("SO-01G") + || codename.equals("SOL26") + || codename.equals("leo"))) + || (model != null && (model.equals("401SO") + || model.equals("D6603") + || model.equals("D6616") + || model.equals("D6643") + || model.equals("D6646") + || model.equals("D6653") + || model.equals("SO-01G") + || model.equals("SOL26")))) { + return "Xperia Z3"; + } + if ((codename != null && (codename.equals("402SO") + || codename.equals("SO-03G") + || codename.equals("SOV31"))) + || (model != null && (model.equals("402SO") + || model.equals("SO-03G") + || model.equals("SOV31")))) { + return "Xperia Z4"; + } + if ((codename != null && (codename.equals("E5803") + || codename.equals("E5823") + || codename.equals("SO-02H"))) + || (model != null && (model.equals("E5803") + || model.equals("E5823") + || model.equals("SO-02H")))) { + return "Xperia Z5 Compact"; + } + // ---------------------------------------------------------------------------- + // Sony Ericsson + if ((codename != null && (codename.equals("LT26i") + || codename.equals("SO-02D"))) + || (model != null && (model.equals("LT26i") + || model.equals("SO-02D")))) { + return "Xperia S"; + } + if ((codename != null && (codename.equals("SGP311") + || codename.equals("SGP321") + || codename.equals("SGP341") + || codename.equals("SO-03E"))) + || (model != null && (model.equals("SGP311") + || model.equals("SGP321") + || model.equals("SGP341") + || model.equals("SO-03E")))) { + return "Xperia Tablet Z"; + } + return fallback; + } + + /** + * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may + * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then + * stored to {@link SharedPreferences}. + * + * @param context + * the application context. + * @return {@link DeviceInfo} for the current device. + */ + @WorkerThread + public static DeviceInfo getDeviceInfo(Context context) { + return getDeviceInfo(context.getApplicationContext(), Build.DEVICE, Build.MODEL); + } + + /** + * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may + * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then + * stored to {@link SharedPreferences}. + * + * @param context + * the application context. + * @param codename + * the codename of the device + * @return {@link DeviceInfo} for the current device. + */ + @WorkerThread + public static DeviceInfo getDeviceInfo(Context context, String codename) { + return getDeviceInfo(context, codename, null); + } + + /** + * Get the {@link DeviceInfo} for the current device. Do not run on the UI thread, as this may + * download JSON to retrieve the {@link DeviceInfo}. JSON is only downloaded once and then + * stored to {@link SharedPreferences}. + * + * @param context + * the application context. + * @param codename + * the codename of the device + * @param model + * the model of the device + * @return {@link DeviceInfo} for the current device. + */ + @WorkerThread + public static DeviceInfo getDeviceInfo(Context context, String codename, String model) { + SharedPreferences prefs = context.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE); + String key = String.format("%s:%s", codename, model); + String savedJson = prefs.getString(key, null); + if (savedJson != null) { + try { + return new DeviceInfo(new JSONObject(savedJson)); + } catch (JSONException e) { + e.printStackTrace(); + } + } + + // check if we have an internet connection + int ret = context.checkCallingOrSelfPermission(Manifest.permission.ACCESS_NETWORK_STATE); + boolean isConnectedToNetwork = false; + if (ret == PackageManager.PERMISSION_GRANTED) { + ConnectivityManager connMgr = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = connMgr.getActiveNetworkInfo(); + if (networkInfo != null && networkInfo.isConnected()) { + isConnectedToNetwork = true; + } + } else { + // assume we are connected. + isConnectedToNetwork = true; + } + + if (isConnectedToNetwork) { + try { + // Get the device name from the generated JSON files created from Google's device list. + String url = String.format(DEVICE_JSON_URL, codename.toLowerCase(Locale.ENGLISH)); + String jsonString = downloadJson(url); + JSONArray jsonArray = new JSONArray(jsonString); + for (int i = 0, len = jsonArray.length(); i < len; i++) { + JSONObject json = jsonArray.getJSONObject(i); + DeviceInfo info = new DeviceInfo(json); + if ((codename.equalsIgnoreCase(info.codename) && model == null) + || codename.equalsIgnoreCase(info.codename) && model.equalsIgnoreCase(info.model)) { + // Save to SharedPreferences so we don't need to make another request. + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(key, json.toString()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + editor.apply(); + } else { + editor.commit(); + } + return info; + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + if (codename.equals(Build.DEVICE) && model.equals(Build.MODEL)) { + return new DeviceInfo(Build.MANUFACTURER, getDeviceName(), codename, model); // current device + } + + return new DeviceInfo(null, null, codename, model); // unknown device + } + + /** + *

Capitalizes getAllProcesses the whitespace separated words in a String. Only the first + * letter of each word is changed.

+ * + * Whitespace is defined by {@link Character#isWhitespace(char)}. + * + * @param str + * the String to capitalize + * @return capitalized The capitalized String + */ + private static String capitalize(String str) { + if (TextUtils.isEmpty(str)) { + return str; + } + char[] arr = str.toCharArray(); + boolean capitalizeNext = true; + String phrase = ""; + for (char c : arr) { + if (capitalizeNext && Character.isLetter(c)) { + phrase += Character.toUpperCase(c); + capitalizeNext = false; + continue; + } else if (Character.isWhitespace(c)) { + capitalizeNext = true; + } + phrase += c; + } + return phrase; + } + + /** Download URL to String */ + @WorkerThread + private static String downloadJson(String myurl) throws IOException { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = null; + try { + URL url = new URL(myurl); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setReadTimeout(10000); + conn.setConnectTimeout(15000); + conn.setRequestMethod("GET"); + conn.setDoInput(true); + conn.connect(); + if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) { + reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line; + while ((line = reader.readLine()) != null) { + sb.append(line).append('\n'); + } + } + return sb.toString(); + } finally { + if (reader != null) { + reader.close(); + } + } + } + + public static final class Request { + + final Context context; + final Handler handler; + String codename; + String model; + + private Request(Context ctx) { + context = ctx; + handler = new Handler(ctx.getMainLooper()); + } + + /** + * Set the device codename to query. You should also set the model. + * + * @param codename + * the value of the system property "ro.product.device" + * @return This Request object to allow for chaining of calls to set methods. + * @see Build#DEVICE + */ + public Request setCodename(String codename) { + this.codename = codename; + return this; + } + + /** + * Set the device model to query. You should also set the codename. + * + * @param model + * the value of the system property "ro.product.model" + * @return This Request object to allow for chaining of calls to set methods. + * @see Build#MODEL + */ + public Request setModel(String model) { + this.model = model; + return this; + } + + /** + * Download information about the device. This saves the results in shared-preferences so + * future requests will not need a network connection. + * + * @param callback + * the callback to retrieve the {@link DeviceInfo} + */ + public void request(Callback callback) { + if (codename == null && model == null) { + codename = Build.DEVICE; + model = Build.MODEL; + } + GetDeviceRunnable runnable = new GetDeviceRunnable(callback); + if (Looper.myLooper() == Looper.getMainLooper()) { + new Thread(runnable).start(); + } else { + runnable.run(); // already running in background thread. + } + } + + private final class GetDeviceRunnable implements Runnable { + + final Callback callback; + DeviceInfo deviceInfo; + Exception error; + + public GetDeviceRunnable(Callback callback) { + this.callback = callback; + } + + @Override public void run() { + try { + deviceInfo = getDeviceInfo(context, codename, model); + } catch (Exception e) { + error = e; + } + handler.post(new Runnable() { + + @Override public void run() { + callback.onFinished(deviceInfo, error); + } + }); + } + } + + } + + /** + * Callback which is invoked when the {@link DeviceInfo} is finished loading. + */ + public interface Callback { + + /** + * Callback to get the device info. This is run on the UI thread. + * + * @param info + * the requested {@link DeviceInfo} + * @param error + * {@code null} if nothing went wrong. + */ + void onFinished(DeviceInfo info, Exception error); + } + + /** + * Device information based on + * Google's maintained list. + */ + public static final class DeviceInfo { + + /** Retail branding */ + public final String manufacturer; + + /** Marketing name */ + public final String marketName; + + /** the value of the system property "ro.product.device" */ + public final String codename; + + /** the value of the system property "ro.product.model" */ + public final String model; + + public DeviceInfo(String manufacturer, String marketName, String codename, String model) { + this.manufacturer = manufacturer; + this.marketName = marketName; + this.codename = codename; + this.model = model; + } + + private DeviceInfo(JSONObject jsonObject) throws JSONException { + manufacturer = jsonObject.getString("manufacturer"); + marketName = jsonObject.getString("market_name"); + codename = jsonObject.getString("codename"); + model = jsonObject.getString("model"); + } + + /** + * @return the consumer friendly name of the device. + */ + public String getName() { + if (!TextUtils.isEmpty(marketName)) { + return marketName; + } + return capitalize(model); + } + } + +} + diff --git a/app/src/main/java/com/tangem/wallet/Digest.java b/app/src/main/java/com/tangem/domain/wallet/Digest.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/Digest.java rename to app/src/main/java/com/tangem/domain/wallet/Digest.java index 51e1e70c58..5e01c1dba6 100644 --- a/app/src/main/java/com/tangem/wallet/Digest.java +++ b/app/src/main/java/com/tangem/domain/wallet/Digest.java @@ -1,114 +1,114 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 18.12.2017. - */ - -public interface Digest{ - - /** - * Insert one more input data byte. - * - * @param in the input byte - */ - void update(byte in); - - /** - * Insert some more bytes. - * - * @param inbuf the data bytes - */ - void update(byte[] inbuf); - - /** - * Insert some more bytes. - * - * @param inbuf the data buffer - * @param off the data offset in {@code inbuf} - * @param len the data length (in bytes) - */ - void update(byte[] inbuf, int off, int len); - - /** - * Finalize the current hash computation and return the hash value - * in a newly-allocated array. The object is resetted. - * - * @return the hash output - */ - byte[] digest(); - - /** - * Input some bytes, then finalize the current hash computation - * and return the hash value in a newly-allocated array. The object - * is resetted. - * - * @param inbuf the input data - * @return the hash output - */ - byte[] digest(byte[] inbuf); - - /** - * Finalize the current hash computation and store the hash value - * in the provided output buffer. The {@code len} parameter - * contains the maximum number of bytes that should be written; - * no more bytes than the natural hash function output length will - * be produced. If {@code len} is smaller than the natural - * hash output length, the hash output is truncated to its first - * {@code len} bytes. The object is resetted. - * - * @param outbuf the output buffer - * @param off the output offset within {@code outbuf} - * @param len the requested hash output length (in bytes) - * @return the number of bytes actually written in {@code outbuf} - */ - int digest(byte[] outbuf, int off, int len); - - /** - * Get the natural hash function output length (in bytes). - * - * @return the digest output length (in bytes) - */ - int getDigestLength(); - - /** - * Reset the object: this makes it suitable for a new hash - * computation. The current computation, if any, is discarded. - */ - void reset(); - - /** - * Clone the current state. The returned object evolves independantly - * of this object. - * - * @return the clone - */ - Digest copy(); - - /** - *

Return the "block length" for the hash function. This - * value is naturally defined for iterated hash functions - * (Merkle-Damgard). It is used in HMAC (that's what the - * HMAC specification - * names the "{@code B}" parameter).

- * - *

If the function is "block-less" then this function may - * return {@code -n} where {@code n} is an integer such that the - * block length for HMAC ("{@code B}") will be inferred from the - * key length, by selecting the smallest multiple of {@code n} - * which is no smaller than the key length. For instance, for - * the Fugue-xxx hash functions, this function returns -4: the - * virtual block length B is the HMAC key length, rounded up to - * the next multiple of 4.

- * - * @return the internal block length (in bytes), or {@code -n} - */ - int getBlockLength(); - - /** - *

Get the display name for this function (e.g. {@code "SHA-1"} - * for SHA-1).

- * - * @see Object - */ - String toString(); +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 18.12.2017. + */ + +public interface Digest{ + + /** + * Insert one more input data byte. + * + * @param in the input byte + */ + void update(byte in); + + /** + * Insert some more bytes. + * + * @param inbuf the data bytes + */ + void update(byte[] inbuf); + + /** + * Insert some more bytes. + * + * @param inbuf the data buffer + * @param off the data offset in {@code inbuf} + * @param len the data length (in bytes) + */ + void update(byte[] inbuf, int off, int len); + + /** + * Finalize the current hash computation and return the hash value + * in a newly-allocated array. The object is resetted. + * + * @return the hash output + */ + byte[] digest(); + + /** + * Input some bytes, then finalize the current hash computation + * and return the hash value in a newly-allocated array. The object + * is resetted. + * + * @param inbuf the input data + * @return the hash output + */ + byte[] digest(byte[] inbuf); + + /** + * Finalize the current hash computation and store the hash value + * in the provided output buffer. The {@code len} parameter + * contains the maximum number of bytes that should be written; + * no more bytes than the natural hash function output length will + * be produced. If {@code len} is smaller than the natural + * hash output length, the hash output is truncated to its first + * {@code len} bytes. The object is resetted. + * + * @param outbuf the output buffer + * @param off the output offset within {@code outbuf} + * @param len the requested hash output length (in bytes) + * @return the number of bytes actually written in {@code outbuf} + */ + int digest(byte[] outbuf, int off, int len); + + /** + * Get the natural hash function output length (in bytes). + * + * @return the digest output length (in bytes) + */ + int getDigestLength(); + + /** + * Reset the object: this makes it suitable for a new hash + * computation. The current computation, if any, is discarded. + */ + void reset(); + + /** + * Clone the current state. The returned object evolves independantly + * of this object. + * + * @return the clone + */ + Digest copy(); + + /** + *

Return the "block length" for the hash function. This + * value is naturally defined for iterated hash functions + * (Merkle-Damgard). It is used in HMAC (that's what the + * HMAC specification + * names the "{@code B}" parameter).

+ * + *

If the function is "block-less" then this function may + * return {@code -n} where {@code n} is an integer such that the + * block length for HMAC ("{@code B}") will be inferred from the + * key length, by selecting the smallest multiple of {@code n} + * which is no smaller than the key length. For instance, for + * the Fugue-xxx hash functions, this function returns -4: the + * virtual block length B is the HMAC key length, rounded up to + * the next multiple of 4.

+ * + * @return the internal block length (in bytes), or {@code -n} + */ + int getBlockLength(); + + /** + *

Get the display name for this function (e.g. {@code "SHA-1"} + * for SHA-1).

+ * + * @see Object + */ + String toString(); } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/DigestEngine.java b/app/src/main/java/com/tangem/domain/wallet/DigestEngine.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/DigestEngine.java rename to app/src/main/java/com/tangem/domain/wallet/DigestEngine.java index 3eba8e60c8..5d7f092f82 100644 --- a/app/src/main/java/com/tangem/wallet/DigestEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/DigestEngine.java @@ -1,220 +1,220 @@ -package com.tangem.wallet; - - -import java.security.MessageDigest; - -/** - * Created by Ilia on 18.12.2017. - */ - -public abstract class DigestEngine extends MessageDigest implements Digest { - - /** - * Reset the hash algorithm state. - */ - protected abstract void engineReset(); - - /** - * Process one block of data. - * - * @param data the data block - */ - protected abstract void processBlock(byte[] data); - - /** - * Perform the final padding and store the result in the - * provided buffer. This method shall call {@link #flush} - * and then {@link #update} with the appropriate padding - * data in order to get the full input data. - * - * @param buf the output buffer - * @param off the output offset - */ - protected abstract void doPadding(byte[] buf, int off); - - /** - * This function is called at object creation time; the - * implementation should use it to perform initialization tasks. - * After this method is called, the implementation should be ready - * to process data or meaningfully honour calls such as - * {@link #engineGetDigestLength} - */ - protected abstract void doInit(); - - private int digestLen, blockLen, inputLen; - private byte[] inputBuf, outputBuf; - private long blockCount; - - /** - * Instantiate the engine. - */ - public DigestEngine(String alg) - { - super(alg); - doInit(); - digestLen = engineGetDigestLength(); - blockLen = getInternalBlockLength(); - inputBuf = new byte[blockLen]; - outputBuf = new byte[digestLen]; - inputLen = 0; - blockCount = 0; - } - - private void adjustDigestLen() - { - if (digestLen == 0) { - digestLen = engineGetDigestLength(); - outputBuf = new byte[digestLen]; - } - } - - public byte[] digest() - { - adjustDigestLen(); - byte[] result = new byte[digestLen]; - digest(result, 0, digestLen); - return result; - } - - public byte[] digest(byte[] input) - { - update(input, 0, input.length); - return digest(); - } - - public int digest(byte[] buf, int offset, int len) - { - adjustDigestLen(); - if (len >= digestLen) { - doPadding(buf, offset); - reset(); - return digestLen; - } else { - doPadding(outputBuf, 0); - System.arraycopy(outputBuf, 0, buf, offset, len); - reset(); - return len; - } - } - - public void reset() - { - engineReset(); - inputLen = 0; - blockCount = 0; - } - - public void update(byte input) - { - inputBuf[inputLen ++] = (byte)input; - if (inputLen == blockLen) { - processBlock(inputBuf); - blockCount ++; - inputLen = 0; - } - } - - public void update(byte[] input) - { - update(input, 0, input.length); - } - - public void update(byte[] input, int offset, int len) - { - while (len > 0) { - int copyLen = blockLen - inputLen; - if (copyLen > len) - copyLen = len; - System.arraycopy(input, offset, inputBuf, inputLen, - copyLen); - offset += copyLen; - inputLen += copyLen; - len -= copyLen; - if (inputLen == blockLen) { - processBlock(inputBuf); - blockCount ++; - inputLen = 0; - } - } - } - - /** - * Get the internal block length. This is the length (in - * bytes) of the array which will be passed as parameter to - * {@link #processBlock}. The default implementation of this - * method calls {@link #getBlockLength} and returns the same - * value. Overriding this method is useful when the advertised - * block length (which is used, for instance, by HMAC) is - * suboptimal with regards to internal buffering needs. - * - * @return the internal block length (in bytes) - */ - protected int getInternalBlockLength() - { - return getBlockLength(); - } - - /** - * Flush internal buffers, so that less than a block of data - * may at most be upheld. - * - * @return the number of bytes still unprocessed after the flush - */ - protected final int flush() - { - return inputLen; - } - - /** - * Get a reference to an internal buffer with the same size - * than a block. The contents of that buffer are defined only - * immediately after a call to {@link #flush()}: if - * {@link #flush()} return the value {@code n}, then the - * first {@code n} bytes of the array returned by this method - * are the {@code n} bytes of input data which are still - * unprocessed. The values of the remaining bytes are - * undefined and may be altered at will. - * - * @return a block-sized internal buffer - */ - protected final byte[] getBlockBuffer() - { - return inputBuf; - } - - /** - * Get the "block count": this is the number of times the - * {@link #processBlock} method has been invoked for the - * current hash operation. That counter is incremented - * after the call to {@link #processBlock}. - * - * @return the block count - */ - protected long getBlockCount() - { - return blockCount; - } - - /** - * This function copies the internal buffering state to some - * other instance of a class extending {@code DigestEngine}. - * It returns a reference to the copy. This method is intended - * to be called by the implementation of the {@link #copy} - * method. - * - * @param dest the copy - * @return the value {@code dest} - */ - protected Digest copyState(DigestEngine dest) - { - dest.inputLen = inputLen; - dest.blockCount = blockCount; - System.arraycopy(inputBuf, 0, dest.inputBuf, 0, - inputBuf.length); - adjustDigestLen(); - dest.adjustDigestLen(); - System.arraycopy(outputBuf, 0, dest.outputBuf, 0, - outputBuf.length); - return dest; - } -} +package com.tangem.domain.wallet; + + +import java.security.MessageDigest; + +/** + * Created by Ilia on 18.12.2017. + */ + +public abstract class DigestEngine extends MessageDigest implements Digest { + + /** + * Reset the hash algorithm state. + */ + protected abstract void engineReset(); + + /** + * Process one block of data. + * + * @param data the data block + */ + protected abstract void processBlock(byte[] data); + + /** + * Perform the final padding and store the result in the + * provided buffer. This method shall call {@link #flush} + * and then {@link #update} with the appropriate padding + * data in order to get the full input data. + * + * @param buf the output buffer + * @param off the output offset + */ + protected abstract void doPadding(byte[] buf, int off); + + /** + * This function is called at object creation time; the + * implementation should use it to perform initialization tasks. + * After this method is called, the implementation should be ready + * to process data or meaningfully honour calls such as + * {@link #engineGetDigestLength} + */ + protected abstract void doInit(); + + private int digestLen, blockLen, inputLen; + private byte[] inputBuf, outputBuf; + private long blockCount; + + /** + * Instantiate the engine. + */ + public DigestEngine(String alg) + { + super(alg); + doInit(); + digestLen = engineGetDigestLength(); + blockLen = getInternalBlockLength(); + inputBuf = new byte[blockLen]; + outputBuf = new byte[digestLen]; + inputLen = 0; + blockCount = 0; + } + + private void adjustDigestLen() + { + if (digestLen == 0) { + digestLen = engineGetDigestLength(); + outputBuf = new byte[digestLen]; + } + } + + public byte[] digest() + { + adjustDigestLen(); + byte[] result = new byte[digestLen]; + digest(result, 0, digestLen); + return result; + } + + public byte[] digest(byte[] input) + { + update(input, 0, input.length); + return digest(); + } + + public int digest(byte[] buf, int offset, int len) + { + adjustDigestLen(); + if (len >= digestLen) { + doPadding(buf, offset); + reset(); + return digestLen; + } else { + doPadding(outputBuf, 0); + System.arraycopy(outputBuf, 0, buf, offset, len); + reset(); + return len; + } + } + + public void reset() + { + engineReset(); + inputLen = 0; + blockCount = 0; + } + + public void update(byte input) + { + inputBuf[inputLen ++] = (byte)input; + if (inputLen == blockLen) { + processBlock(inputBuf); + blockCount ++; + inputLen = 0; + } + } + + public void update(byte[] input) + { + update(input, 0, input.length); + } + + public void update(byte[] input, int offset, int len) + { + while (len > 0) { + int copyLen = blockLen - inputLen; + if (copyLen > len) + copyLen = len; + System.arraycopy(input, offset, inputBuf, inputLen, + copyLen); + offset += copyLen; + inputLen += copyLen; + len -= copyLen; + if (inputLen == blockLen) { + processBlock(inputBuf); + blockCount ++; + inputLen = 0; + } + } + } + + /** + * Get the internal block length. This is the length (in + * bytes) of the array which will be passed as parameter to + * {@link #processBlock}. The default implementation of this + * method calls {@link #getBlockLength} and returns the same + * value. Overriding this method is useful when the advertised + * block length (which is used, for instance, by HMAC) is + * suboptimal with regards to internal buffering needs. + * + * @return the internal block length (in bytes) + */ + protected int getInternalBlockLength() + { + return getBlockLength(); + } + + /** + * Flush internal buffers, so that less than a block of data + * may at most be upheld. + * + * @return the number of bytes still unprocessed after the flush + */ + protected final int flush() + { + return inputLen; + } + + /** + * Get a reference to an internal buffer with the same size + * than a block. The contents of that buffer are defined only + * immediately after a call to {@link #flush()}: if + * {@link #flush()} return the value {@code n}, then the + * first {@code n} bytes of the array returned by this method + * are the {@code n} bytes of input data which are still + * unprocessed. The values of the remaining bytes are + * undefined and may be altered at will. + * + * @return a block-sized internal buffer + */ + protected final byte[] getBlockBuffer() + { + return inputBuf; + } + + /** + * Get the "block count": this is the number of times the + * {@link #processBlock} method has been invoked for the + * current hash operation. That counter is incremented + * after the call to {@link #processBlock}. + * + * @return the block count + */ + protected long getBlockCount() + { + return blockCount; + } + + /** + * This function copies the internal buffering state to some + * other instance of a class extending {@code DigestEngine}. + * It returns a reference to the copy. This method is intended + * to be called by the implementation of the {@link #copy} + * method. + * + * @param dest the copy + * @return the value {@code dest} + */ + protected Digest copyState(DigestEngine dest) + { + dest.inputLen = inputLen; + dest.blockCount = blockCount; + System.arraycopy(inputBuf, 0, dest.inputBuf, 0, + inputBuf.length); + adjustDigestLen(); + dest.adjustDigestLen(); + System.arraycopy(outputBuf, 0, dest.outputBuf, 0, + outputBuf.length); + return dest; + } +} diff --git a/app/src/main/java/com/tangem/wallet/ECDSASignature_ETH.java b/app/src/main/java/com/tangem/domain/wallet/ECDSASignature_ETH.java similarity index 92% rename from app/src/main/java/com/tangem/wallet/ECDSASignature_ETH.java rename to app/src/main/java/com/tangem/domain/wallet/ECDSASignature_ETH.java index 1ad20a2d6f..ab6ba9861c 100644 --- a/app/src/main/java/com/tangem/wallet/ECDSASignature_ETH.java +++ b/app/src/main/java/com/tangem/domain/wallet/ECDSASignature_ETH.java @@ -1,52 +1,52 @@ -package com.tangem.wallet; - -import java.math.BigInteger; - -/** - * Created by Ilia on 07.01.2018. - */ - -public class ECDSASignature_ETH { - /** - * The two components of the signature. - */ - public final BigInteger r, s; - public byte v; - - /** - * Constructs a signature with the given components. Does NOT automatically canonicalise the signature. - * - * @param r - - * @param s - - */ - public ECDSASignature_ETH(BigInteger r, BigInteger s) { - this.r = r; - this.s = s; - } - - /** - *t - * @param r - * @param s - * @return - - */ - private static ECDSASignature_ETH fromComponents(byte[] r, byte[] s) { - return new ECDSASignature_ETH(new BigInteger(1, r), new BigInteger(1, s)); - } - - /** - * - * @param r - - * @param s - - * @param v - - * @return - - */ - public static ECDSASignature_ETH fromComponents(byte[] r, byte[] s, byte v) { - ECDSASignature_ETH signature = fromComponents(r, s); - signature.v = v; - return signature; - } - - -} - +package com.tangem.domain.wallet; + +import java.math.BigInteger; + +/** + * Created by Ilia on 07.01.2018. + */ + +public class ECDSASignature_ETH { + /** + * The two components of the signature. + */ + public final BigInteger r, s; + public byte v; + + /** + * Constructs a signature with the given components. Does NOT automatically canonicalise the signature. + * + * @param r - + * @param s - + */ + public ECDSASignature_ETH(BigInteger r, BigInteger s) { + this.r = r; + this.s = s; + } + + /** + *t + * @param r + * @param s + * @return - + */ + private static ECDSASignature_ETH fromComponents(byte[] r, byte[] s) { + return new ECDSASignature_ETH(new BigInteger(1, r), new BigInteger(1, s)); + } + + /** + * + * @param r - + * @param s - + * @param v - + * @return - + */ + public static ECDSASignature_ETH fromComponents(byte[] r, byte[] s, byte v) { + ECDSASignature_ETH signature = fromComponents(r, s); + signature.v = v; + return signature; + } + + +} + diff --git a/app/src/main/java/com/tangem/wallet/ETH_Transaction.java b/app/src/main/java/com/tangem/domain/wallet/ETH_Transaction.java similarity index 95% rename from app/src/main/java/com/tangem/wallet/ETH_Transaction.java rename to app/src/main/java/com/tangem/domain/wallet/ETH_Transaction.java index 0f60b28c50..8fd7ed79e8 100644 --- a/app/src/main/java/com/tangem/wallet/ETH_Transaction.java +++ b/app/src/main/java/com/tangem/domain/wallet/ETH_Transaction.java @@ -1,229 +1,229 @@ -package com.tangem.wallet; - - -import android.util.Log; - -import org.bitcoinj.core.ECKey; -import org.bitcoinj.core.Sha256Hash; -import org.spongycastle.util.BigIntegers; -import org.spongycastle.util.encoders.Hex; - -import java.math.BigInteger; -import java.util.Arrays; - -import static com.tangem.wallet.ByteUtil.EMPTY_BYTE_ARRAY; - -/** - * Created by Ilia on 07.01.2018. - */ - -public class ETH_Transaction { - byte[] nonce; - byte[] gasPrice; - byte[] gasLimit; - byte[] receiveAddress; - byte[] value; - byte[] data; - Integer chainId; - byte[] rlpRaw; - public ECDSASignature_ETH signature; - byte[] rlpEncoded; - - private static final int CHAIN_ID_INC = 35; - private static final int LOWER_REAL_V = 27; - - public static ETH_Transaction create(String to, BigInteger amount, BigInteger nonce, BigInteger gasPrice, - BigInteger gasLimit, Integer chainId){ - return new ETH_Transaction(BigIntegers.asUnsignedByteArray(nonce), - BigIntegers.asUnsignedByteArray(gasPrice), - BigIntegers.asUnsignedByteArray(gasLimit), - Hex.decode(to), - BigIntegers.asUnsignedByteArray(amount), - null, - chainId); - } - - - public static ETH_Transaction create(String to, BigInteger amount, BigInteger nonce, BigInteger gasPrice, - BigInteger gasLimit, Integer chainId, byte[] data){ - return new ETH_Transaction(BigIntegers.asUnsignedByteArray(nonce), - BigIntegers.asUnsignedByteArray(gasPrice), - BigIntegers.asUnsignedByteArray(gasLimit), - Hex.decode(to), - BigIntegers.asUnsignedByteArray(amount), - data, - chainId); - } - - public ETH_Transaction(byte[] nonce, byte[] gasPrice, byte[] gasLimit, byte[] receiveAddress, byte[] value, byte[] data, - Integer chainId) { - this.nonce = nonce; - this.gasPrice = gasPrice; - this.gasLimit = gasLimit; - this.receiveAddress = receiveAddress; - if (ByteUtil.isSingleZero(value)) { - this.value = EMPTY_BYTE_ARRAY; - } else { - this.value = value; - } - this.data = data; - this.chainId = chainId; - - if (receiveAddress == null) { - this.receiveAddress = ByteUtil.EMPTY_BYTE_ARRAY; - } - } - - public enum ChainEnum - { - Mainnet(1), - Morden(2), - Ropsten(3), - Rinkeby(4), - Rootstock_mainnet(30), - Rootstock_testnet (31), - Kovan (42), - Ethereum_Classic_mainnet(61), - Ethereum_Classic_testnet(62), - Geth_private_chains (1337); - - private int value; - - ChainEnum(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - public byte[] getRawHash() { - - byte[] plainMsg = this.getEncodedRaw(); - Keccak256 kec = new Keccak256(); - return kec.digest(plainMsg); - } - - public byte[] getHash() { - - byte[] plainMsg = this.getEncoded(); - Keccak256 kec = new Keccak256(); - return kec.digest(plainMsg); - } - - public int BruteRecoveryID2(ECDSASignature_ETH sig, byte[] messageHash, byte[] thisKey) - { - Log.e("ETH_KZ", BTCUtils.toHex(thisKey)); - int recId = -1; - for (int i = 0; i < 4; i++) { - byte[] recK = CryptoUtil.recoverPubBytesFromSignature(i, sig, messageHash); - - if(recK == null) - { - continue; - } - - Log.e("ETH_k "+String.valueOf(i), BTCUtils.toHex(recK)); - if (Arrays.equals(recK, thisKey)) { - recId = i; - recId +=27; - break; - } - } - return recId; - } - - public int BruteRecoveryID(ECKey.ECDSASignature sig, Sha256Hash messageHash, byte[] thisKey) - { - Log.e("ETH_KZ", BTCUtils.toHex(thisKey)); - int recId = -1; - for (int i = 0; i < 4; i++) { - ECKey k = ECKey.recoverFromSignature(i, sig, messageHash, false); - - if(k == null) - continue; - byte[] recK = k.getPubKey(); - Log.e("ETH_k "+String.valueOf(i), BTCUtils.toHex(recK)); - if (k != null && Arrays.equals(recK, thisKey)) { - recId = i; - break; - } - } - return recId; - } - - // signed TX - public byte[] getEncoded() { - - // parse null as 0 for nonce - byte[] nonce = null; - if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) { - nonce = RLP.encodeElement(null); - } else { - nonce = RLP.encodeElement(this.nonce); - } - byte[] gasPrice = RLP.encodeElement(this.gasPrice); - byte[] gasLimit = RLP.encodeElement(this.gasLimit); - byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); - byte[] value = RLP.encodeElement(this.value); - byte[] data = RLP.encodeElement(this.data); - - byte[] v, r, s; - - if (signature != null) { - int encodeV; - if (chainId == null) { - encodeV = signature.v; - } else { - encodeV = signature.v - LOWER_REAL_V; - encodeV += chainId * 2 + CHAIN_ID_INC; - } - v = RLP.encodeInt(encodeV); - r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r)); - s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s)); - } else { - // Since EIP-155 use chainId for v - v = chainId == null ? RLP.encodeElement(EMPTY_BYTE_ARRAY) : RLP.encodeInt(chainId); - r = RLP.encodeElement(EMPTY_BYTE_ARRAY); - s = RLP.encodeElement(EMPTY_BYTE_ARRAY); - } - - this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, - receiveAddress, value, data, v, r, s); - - //this.hash = this.getHash(); - - return rlpEncoded; - } - - // unsigned TX - public byte[] getEncodedRaw() { - // parse null as 0 for nonce - byte[] nonce = null; - if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) { - nonce = RLP.encodeElement(null); - } else { - nonce = RLP.encodeElement(this.nonce); - } - byte[] gasPrice = RLP.encodeElement(this.gasPrice); - byte[] gasLimit = RLP.encodeElement(this.gasLimit); - byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); - byte[] value = RLP.encodeElement(this.value); - byte[] data = RLP.encodeElement(this.data); - - // Since EIP-155 use chainId for v - if (chainId == null) { - rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, - value, data); - } else { - byte[] v, r, s; - v = RLP.encodeInt(chainId); - r = RLP.encodeElement(EMPTY_BYTE_ARRAY); - s = RLP.encodeElement(EMPTY_BYTE_ARRAY); - rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, - value, data, v, r, s); - } - return rlpRaw; - } -} +package com.tangem.domain.wallet; + + +import android.util.Log; + +import org.bitcoinj.core.ECKey; +import org.bitcoinj.core.Sha256Hash; +import org.spongycastle.util.BigIntegers; +import org.spongycastle.util.encoders.Hex; + +import java.math.BigInteger; +import java.util.Arrays; + +import static com.tangem.domain.wallet.ByteUtil.EMPTY_BYTE_ARRAY; + +/** + * Created by Ilia on 07.01.2018. + */ + +public class ETH_Transaction { + byte[] nonce; + byte[] gasPrice; + byte[] gasLimit; + byte[] receiveAddress; + byte[] value; + byte[] data; + Integer chainId; + byte[] rlpRaw; + public ECDSASignature_ETH signature; + byte[] rlpEncoded; + + private static final int CHAIN_ID_INC = 35; + private static final int LOWER_REAL_V = 27; + + public static ETH_Transaction create(String to, BigInteger amount, BigInteger nonce, BigInteger gasPrice, + BigInteger gasLimit, Integer chainId){ + return new ETH_Transaction(BigIntegers.asUnsignedByteArray(nonce), + BigIntegers.asUnsignedByteArray(gasPrice), + BigIntegers.asUnsignedByteArray(gasLimit), + Hex.decode(to), + BigIntegers.asUnsignedByteArray(amount), + null, + chainId); + } + + + public static ETH_Transaction create(String to, BigInteger amount, BigInteger nonce, BigInteger gasPrice, + BigInteger gasLimit, Integer chainId, byte[] data){ + return new ETH_Transaction(BigIntegers.asUnsignedByteArray(nonce), + BigIntegers.asUnsignedByteArray(gasPrice), + BigIntegers.asUnsignedByteArray(gasLimit), + Hex.decode(to), + BigIntegers.asUnsignedByteArray(amount), + data, + chainId); + } + + public ETH_Transaction(byte[] nonce, byte[] gasPrice, byte[] gasLimit, byte[] receiveAddress, byte[] value, byte[] data, + Integer chainId) { + this.nonce = nonce; + this.gasPrice = gasPrice; + this.gasLimit = gasLimit; + this.receiveAddress = receiveAddress; + if (ByteUtil.isSingleZero(value)) { + this.value = EMPTY_BYTE_ARRAY; + } else { + this.value = value; + } + this.data = data; + this.chainId = chainId; + + if (receiveAddress == null) { + this.receiveAddress = ByteUtil.EMPTY_BYTE_ARRAY; + } + } + + public enum ChainEnum + { + Mainnet(1), + Morden(2), + Ropsten(3), + Rinkeby(4), + Rootstock_mainnet(30), + Rootstock_testnet (31), + Kovan (42), + Ethereum_Classic_mainnet(61), + Ethereum_Classic_testnet(62), + Geth_private_chains (1337); + + private int value; + + ChainEnum(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public byte[] getRawHash() { + + byte[] plainMsg = this.getEncodedRaw(); + Keccak256 kec = new Keccak256(); + return kec.digest(plainMsg); + } + + public byte[] getHash() { + + byte[] plainMsg = this.getEncoded(); + Keccak256 kec = new Keccak256(); + return kec.digest(plainMsg); + } + + public int BruteRecoveryID2(ECDSASignature_ETH sig, byte[] messageHash, byte[] thisKey) + { + Log.e("ETH_KZ", BTCUtils.toHex(thisKey)); + int recId = -1; + for (int i = 0; i < 4; i++) { + byte[] recK = CryptoUtil.recoverPubBytesFromSignature(i, sig, messageHash); + + if(recK == null) + { + continue; + } + + Log.e("ETH_k "+String.valueOf(i), BTCUtils.toHex(recK)); + if (Arrays.equals(recK, thisKey)) { + recId = i; + recId +=27; + break; + } + } + return recId; + } + + public int BruteRecoveryID(ECKey.ECDSASignature sig, Sha256Hash messageHash, byte[] thisKey) + { + Log.e("ETH_KZ", BTCUtils.toHex(thisKey)); + int recId = -1; + for (int i = 0; i < 4; i++) { + ECKey k = ECKey.recoverFromSignature(i, sig, messageHash, false); + + if(k == null) + continue; + byte[] recK = k.getPubKey(); + Log.e("ETH_k "+String.valueOf(i), BTCUtils.toHex(recK)); + if (k != null && Arrays.equals(recK, thisKey)) { + recId = i; + break; + } + } + return recId; + } + + // signed TX + public byte[] getEncoded() { + + // parse null as 0 for nonce + byte[] nonce = null; + if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) { + nonce = RLP.encodeElement(null); + } else { + nonce = RLP.encodeElement(this.nonce); + } + byte[] gasPrice = RLP.encodeElement(this.gasPrice); + byte[] gasLimit = RLP.encodeElement(this.gasLimit); + byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); + byte[] value = RLP.encodeElement(this.value); + byte[] data = RLP.encodeElement(this.data); + + byte[] v, r, s; + + if (signature != null) { + int encodeV; + if (chainId == null) { + encodeV = signature.v; + } else { + encodeV = signature.v - LOWER_REAL_V; + encodeV += chainId * 2 + CHAIN_ID_INC; + } + v = RLP.encodeInt(encodeV); + r = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.r)); + s = RLP.encodeElement(BigIntegers.asUnsignedByteArray(signature.s)); + } else { + // Since EIP-155 use chainId for v + v = chainId == null ? RLP.encodeElement(EMPTY_BYTE_ARRAY) : RLP.encodeInt(chainId); + r = RLP.encodeElement(EMPTY_BYTE_ARRAY); + s = RLP.encodeElement(EMPTY_BYTE_ARRAY); + } + + this.rlpEncoded = RLP.encodeList(nonce, gasPrice, gasLimit, + receiveAddress, value, data, v, r, s); + + //this.hash = this.getHash(); + + return rlpEncoded; + } + + // unsigned TX + public byte[] getEncodedRaw() { + // parse null as 0 for nonce + byte[] nonce = null; + if (this.nonce == null || this.nonce.length == 1 && this.nonce[0] == 0) { + nonce = RLP.encodeElement(null); + } else { + nonce = RLP.encodeElement(this.nonce); + } + byte[] gasPrice = RLP.encodeElement(this.gasPrice); + byte[] gasLimit = RLP.encodeElement(this.gasLimit); + byte[] receiveAddress = RLP.encodeElement(this.receiveAddress); + byte[] value = RLP.encodeElement(this.value); + byte[] data = RLP.encodeElement(this.data); + + // Since EIP-155 use chainId for v + if (chainId == null) { + rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, + value, data); + } else { + byte[] v, r, s; + v = RLP.encodeInt(chainId); + r = RLP.encodeElement(EMPTY_BYTE_ARRAY); + s = RLP.encodeElement(EMPTY_BYTE_ARRAY); + rlpRaw = RLP.encodeList(nonce, gasPrice, gasLimit, receiveAddress, + value, data, v, r, s); + } + return rlpRaw; + } +} diff --git a/app/src/main/java/com/tangem/wallet/EthEngine.java b/app/src/main/java/com/tangem/domain/wallet/EthEngine.java similarity index 77% rename from app/src/main/java/com/tangem/wallet/EthEngine.java rename to app/src/main/java/com/tangem/domain/wallet/EthEngine.java index 46f0e9acab..541dc1c4aa 100644 --- a/app/src/main/java/com/tangem/wallet/EthEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/EthEngine.java @@ -1,392 +1,392 @@ -package com.tangem.wallet; - -import android.net.Uri; -import android.util.Log; - -import com.tangem.domain.cardReader.CardProtocol; -import com.tangem.domain.cardReader.TLV; - -import org.bitcoinj.core.ECKey; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.Date; - -import static com.tangem.wallet.FormatUtil.GetDecimalFormat; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class EthEngine extends CoinEngine{ - - public String GetNextNode(Tangem_Card mCard) - { - return "abc1.hsmiths.com"; - } - - public int GetNextNodePort(Tangem_Card mCard) - { - return 60001; - } - - public String GetNode(Tangem_Card mCard) - { - return "abc1.hsmiths.com"; - } - - public int GetNodePort(Tangem_Card mCard) - { - return 60001; - } - - public void SwitchNode(Tangem_Card mCard) - { - } - - public boolean InOutPutVisible() - { - return false; - } - - public String GetBalanceCurrency(Tangem_Card card) - { - return "ETH"; - } - - public boolean AwaitingConfirmation(Tangem_Card card) - { - return false; - } - - public String GetFeeCurrency() - { - return "Gwei"; - } - - public boolean IsNeedCheckNode() - { - return false; - } - - BigDecimal convertToEth(String value) - { - BigInteger m = new BigInteger(value, 10); - BigDecimal n = new BigDecimal(m); - BigDecimal d = n.divide(new BigDecimal("1000000000000000000")); - d = d.setScale(8, RoundingMode.DOWN); - return d; - } - - public int GetTokenDecimals(Tangem_Card card) - { - return 0; - } - - public String GetContractAddress(Tangem_Card card) - { - return ""; - } - - public boolean ValdateAddress(String address, Tangem_Card card) { - - if (address == null || address.isEmpty()) - { - return false; - } - - if(!address.startsWith("0x")&&!address.startsWith("0X")) - { - return false; - } - - if(address.length()!=42) - { - return false; - } - - return true; - } - public String GetBalanceValue(Tangem_Card mCard) - { - String dec = mCard.getDecimalBalance(); - BigDecimal d = convertToEth(dec); - String s = d.toString(); - - String pattern = "#0.000"; // If you like 4 zeros - DecimalFormat myFormatter = new DecimalFormat(pattern); - String output = myFormatter.format(d); - return output; - } - - public static String getAmountEquivalentDescriptionETH(BigDecimal amount, float rateValue) { - if (amount == null || amount.compareTo(BigDecimal.ZERO) == 0) - return ""; - - if (rateValue > 0) { - BigDecimal biRate = new BigDecimal(rateValue); - BigDecimal exchangeCurs = biRate.multiply(amount); - exchangeCurs = exchangeCurs.setScale(2, RoundingMode.DOWN); - return "≈ USD  " + exchangeCurs.toString(); - } else { - return "≈ USD  ---"; - } - } - - public static String getAmountEquivalentDescriptionETH(Double amount, float rate) { - if (amount == 0) - return ""; - amount = amount / 100000; - if (rate > 0) { - return String.format("≈ USD %.2f", amount * rate); - } else { - return "≈ USD  ---"; - } - } - - - - @Override - public String GetBalanceEquivalent(Tangem_Card mCard) { - String dec = mCard.getDecimalBalance(); - BigDecimal d = convertToEth(dec); - return getAmountEquivalentDescriptionETH(d, mCard.getRate()); - } - - @Override - public String GetBalance(Tangem_Card mCard) { - if(!HasBalanceInfo(mCard)){ - return "-- -- -- " + GetBalanceCurrency(mCard); - } - - String output = GetBalanceValue(mCard); - String s = output + " " + GetBalanceCurrency(mCard); - return s; - } - - public Long GetBalanceLong(Tangem_Card mCard) - { - return mCard.getBalance(); - } - - public String GetBalanceWithAlter(Tangem_Card mCard) - { - return GetBalance(mCard); - } - - public boolean IsBalanceAlterNotZero(Tangem_Card card) - { - return true; - } - - public boolean IsBalanceNotZero(Tangem_Card card) - { - String balance = card.getDecimalBalance(); - if(balance == null || balance == "") - return false; - - BigDecimal bi = new BigDecimal(balance); - - if (BigDecimal.ZERO.compareTo(bi) == 0) - return false; - - return true; - } - - @Override - public String ConvertByteArrayToAmount(Tangem_Card mCard, byte[] bytes) throws Exception { - throw new Exception("Not implemented"); - } - - @Override - public byte[] ConvertAmountToByteArray(Tangem_Card mCard, String amount) throws Exception { - throw new Exception("Not implemented"); - } - - @Override - public String GetAmountDescription(Tangem_Card mCard, String amount) throws Exception { - throw new Exception("Not implemented"); - } - - public String GetAmountEqualentDescriptor(Tangem_Card mCard, String value) - { - BigDecimal d = new BigDecimal(value); - return getAmountEquivalentDescriptionETH(d, mCard.getRate()); - } - - 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 ) - { - return false; - } - - return true; - } - - public boolean HasBalanceInfo(Tangem_Card card) - { - return card.hasBalanceInfo(); - } - - public Uri getShareWalletURI(Tangem_Card mCard) - { - return Uri.parse("" + mCard.getWallet()); - } - - public Uri getShareWalletURIExplorer(Tangem_Card mCard) - { - if(mCard.getBlockchain() == Blockchain.EthereumTestNet) - return Uri.parse("https://rinkeby.etherscan.io/address/" + mCard.getWallet()); - else - return Uri.parse("https://etherscan.io/address/" + mCard.getWallet()); - } - - public boolean CheckUnspentTransaction(Tangem_Card mCard) - { - return true; - } - - - public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) - { - Long fee = null; - Long amount = null; - try { - amount = mCard.InternalUnitsFromString(amountValue); - fee = mCard.InternalUnitsFromString(feeValue); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - - if(fee == null || amount == null) - return false; - - if(fee == 0 || amount ==0) - return false; - - - if(fee < minFeeInInternalUnits) - return false; - - - BigDecimal tmpFee = new BigDecimal(feeValue); - BigDecimal tmpAmount = new BigDecimal(amountValue); - tmpAmount = tmpAmount.multiply(new BigDecimal("1000000000")); - - if (tmpFee.compareTo(tmpAmount) > 0) - return false; - - return true; - } - - 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); - return GetAmountEqualentDescriptor(mCard, gweFee.toString()); - } - - public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { - Keccak256 kec = new Keccak256(); - int lenPk = pkUncompressed.length; - if (lenPk < 2) { - throw new IllegalArgumentException("Uncompress public key length is invald"); - } - byte[] cleanKey = new byte[lenPk - 1]; - for (int i = 0; i < cleanKey.length; ++i) { - cleanKey[i] = pkUncompressed[i + 1]; - } - byte[] r = kec.digest(cleanKey); - - byte[] address = new byte[20]; - for (int i = 0; i < 20; ++i) { - address[i] = r[i + 12]; - } - - return String.format("0x%s", BTCUtils.toHex(address)); - } - - public byte[] Sign(String feeValue, String amountValue, String toValue, Tangem_Card mCard, CardProtocol protocol) throws Exception { - - BigInteger nonceValue = mCard.GetConfirmTXCount(); - byte[] pbKey = mCard.getWalletPublicKey(); - boolean flag = (mCard.getSigningMethod()== Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer); - Issuer issuer = mCard.getIssuer(); - - - BigInteger fee = new BigInteger(feeValue, 10); - - BigDecimal amountDec = new BigDecimal(amountValue); - amountDec = amountDec.multiply(new BigDecimal("1000000000")); - - - BigInteger amount = amountDec.toBigInteger(); //new BigInteger(amountValue, 10); - amount = amount.subtract(fee); - - BigInteger nonce = nonceValue; - BigInteger gasPrice = fee.divide(BigInteger.valueOf(21000)); - BigInteger gasLimit = BigInteger.valueOf(21000); - Integer chainId = mCard.getBlockchain() == Blockchain.Ethereum ? ETH_Transaction.ChainEnum.Mainnet.getValue() : ETH_Transaction.ChainEnum.Rinkeby.getValue(); - - Long multiplicator = 1000000000L; - amount = amount.multiply(BigInteger.valueOf(multiplicator)); - gasPrice = gasPrice.multiply(BigInteger.valueOf(multiplicator)); - - String to = toValue; - - if (to.startsWith("0x") || to.startsWith("0X")) { - to = to.substring(2); - } - - ETH_Transaction tx = ETH_Transaction.create(to, amount, nonce, gasPrice, gasLimit, chainId); - - byte[][] hashesForSign = new byte[1][]; - byte[] for_hash = tx.getRawHash(); - hashesForSign[0] = for_hash; - - byte[] signFromCard = null; - try { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value; - // TODO slice signFromCard to hashes.length parts - } catch (Exception ex) { - Log.e("ETH", ex.getMessage()); - return null; - } - - LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); - - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, 32)); - BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32, 64)); - s = CryptoUtil.toCanonicalised(s); - - boolean f = ECKey.verify(for_hash, new ECKey.ECDSASignature(r, s), pbKey); - - if(!f) - { - Log.e("ETH-CHECK", "Sign Failed."); - } - - tx.signature = new ECDSASignature_ETH(r, s); - int v = tx.BruteRecoveryID2(tx.signature, for_hash, pbKey); - if (v != 27 && v != 28) { - Log.e("ETH", "invalid v"); - return null; - } - tx.signature.v = (byte) v; - Log.e("ETH_v", String.valueOf(v)); - - byte[] realTX = tx.getEncoded(); - return realTX; - } -} +package com.tangem.domain.wallet; + +import android.net.Uri; +import android.util.Log; + +import com.tangem.domain.cardReader.CardProtocol; +import com.tangem.domain.cardReader.TLV; + +import org.bitcoinj.core.ECKey; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.Date; + +import static com.tangem.domain.wallet.FormatUtil.GetDecimalFormat; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class EthEngine extends CoinEngine { + + public String GetNextNode(TangemCard mCard) + { + return "abc1.hsmiths.com"; + } + + public int GetNextNodePort(TangemCard mCard) + { + return 60001; + } + + public String GetNode(TangemCard mCard) + { + return "abc1.hsmiths.com"; + } + + public int GetNodePort(TangemCard mCard) + { + return 60001; + } + + public void SwitchNode(TangemCard mCard) + { + } + + public boolean InOutPutVisible() + { + return false; + } + + public String GetBalanceCurrency(TangemCard card) + { + return "ETH"; + } + + public boolean AwaitingConfirmation(TangemCard card) + { + return false; + } + + public String GetFeeCurrency() + { + return "Gwei"; + } + + public boolean IsNeedCheckNode() + { + return false; + } + + BigDecimal convertToEth(String value) + { + BigInteger m = new BigInteger(value, 10); + BigDecimal n = new BigDecimal(m); + BigDecimal d = n.divide(new BigDecimal("1000000000000000000")); + d = d.setScale(8, RoundingMode.DOWN); + return d; + } + + public int GetTokenDecimals(TangemCard card) + { + return 0; + } + + public String GetContractAddress(TangemCard card) + { + return ""; + } + + public boolean ValdateAddress(String address, TangemCard card) { + + if (address == null || address.isEmpty()) + { + return false; + } + + if(!address.startsWith("0x")&&!address.startsWith("0X")) + { + return false; + } + + if(address.length()!=42) + { + return false; + } + + return true; + } + public String GetBalanceValue(TangemCard mCard) + { + String dec = mCard.getDecimalBalance(); + BigDecimal d = convertToEth(dec); + String s = d.toString(); + + String pattern = "#0.000"; // If you like 4 zeros + DecimalFormat myFormatter = new DecimalFormat(pattern); + String output = myFormatter.format(d); + return output; + } + + public static String getAmountEquivalentDescriptionETH(BigDecimal amount, float rateValue) { + if (amount == null || amount.compareTo(BigDecimal.ZERO) == 0) + return ""; + + if (rateValue > 0) { + BigDecimal biRate = new BigDecimal(rateValue); + BigDecimal exchangeCurs = biRate.multiply(amount); + exchangeCurs = exchangeCurs.setScale(2, RoundingMode.DOWN); + return "≈ USD  " + exchangeCurs.toString(); + } else { + return "≈ USD  ---"; + } + } + + public static String getAmountEquivalentDescriptionETH(Double amount, float rate) { + if (amount == 0) + return ""; + amount = amount / 100000; + if (rate > 0) { + return String.format("≈ USD %.2f", amount * rate); + } else { + return "≈ USD  ---"; + } + } + + + + @Override + public String GetBalanceEquivalent(TangemCard mCard) { + String dec = mCard.getDecimalBalance(); + BigDecimal d = convertToEth(dec); + return getAmountEquivalentDescriptionETH(d, mCard.getRate()); + } + + @Override + public String GetBalance(TangemCard mCard) { + if(!HasBalanceInfo(mCard)){ + return "-- -- -- " + GetBalanceCurrency(mCard); + } + + String output = GetBalanceValue(mCard); + String s = output + " " + GetBalanceCurrency(mCard); + return s; + } + + public Long GetBalanceLong(TangemCard mCard) + { + return mCard.getBalance(); + } + + public String GetBalanceWithAlter(TangemCard mCard) + { + return GetBalance(mCard); + } + + public boolean IsBalanceAlterNotZero(TangemCard card) + { + return true; + } + + public boolean IsBalanceNotZero(TangemCard card) + { + String balance = card.getDecimalBalance(); + if(balance == null || balance == "") + return false; + + BigDecimal bi = new BigDecimal(balance); + + if (BigDecimal.ZERO.compareTo(bi) == 0) + return false; + + return true; + } + + @Override + public String ConvertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception { + throw new Exception("Not implemented"); + } + + @Override + public byte[] ConvertAmountToByteArray(TangemCard mCard, String amount) throws Exception { + throw new Exception("Not implemented"); + } + + @Override + public String GetAmountDescription(TangemCard mCard, String amount) throws Exception { + throw new Exception("Not implemented"); + } + + public String GetAmountEqualentDescriptor(TangemCard mCard, String value) + { + BigDecimal d = new BigDecimal(value); + return getAmountEquivalentDescriptionETH(d, mCard.getRate()); + } + + public boolean CheckAmount(TangemCard 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 ) + { + return false; + } + + return true; + } + + public boolean HasBalanceInfo(TangemCard card) + { + return card.hasBalanceInfo(); + } + + public Uri getShareWalletURI(TangemCard mCard) + { + return Uri.parse("" + mCard.getWallet()); + } + + public Uri getShareWalletURIExplorer(TangemCard mCard) + { + if(mCard.getBlockchain() == Blockchain.EthereumTestNet) + return Uri.parse("https://rinkeby.etherscan.io/address/" + mCard.getWallet()); + else + return Uri.parse("https://etherscan.io/address/" + mCard.getWallet()); + } + + public boolean CheckUnspentTransaction(TangemCard mCard) + { + return true; + } + + + public boolean CheckAmountValie(TangemCard mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) + { + Long fee = null; + Long amount = null; + try { + amount = mCard.InternalUnitsFromString(amountValue); + fee = mCard.InternalUnitsFromString(feeValue); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + if(fee == null || amount == null) + return false; + + if(fee == 0 || amount ==0) + return false; + + + if(fee < minFeeInInternalUnits) + return false; + + + BigDecimal tmpFee = new BigDecimal(feeValue); + BigDecimal tmpAmount = new BigDecimal(amountValue); + tmpAmount = tmpAmount.multiply(new BigDecimal("1000000000")); + + if (tmpFee.compareTo(tmpAmount) > 0) + return false; + + return true; + } + + public String EvaluteFeeEquivalent(TangemCard mCard, String fee) + { + BigDecimal gweFee = new BigDecimal(fee); + gweFee = gweFee.divide(new BigDecimal("1000000000")); + gweFee = gweFee.setScale(18, RoundingMode.DOWN); + return GetAmountEqualentDescriptor(mCard, gweFee.toString()); + } + + public String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + Keccak256 kec = new Keccak256(); + int lenPk = pkUncompressed.length; + if (lenPk < 2) { + throw new IllegalArgumentException("Uncompress public key length is invald"); + } + byte[] cleanKey = new byte[lenPk - 1]; + for (int i = 0; i < cleanKey.length; ++i) { + cleanKey[i] = pkUncompressed[i + 1]; + } + byte[] r = kec.digest(cleanKey); + + byte[] address = new byte[20]; + for (int i = 0; i < 20; ++i) { + address[i] = r[i + 12]; + } + + return String.format("0x%s", BTCUtils.toHex(address)); + } + + public byte[] Sign(String feeValue, String amountValue, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { + + BigInteger nonceValue = mCard.GetConfirmTXCount(); + byte[] pbKey = mCard.getWalletPublicKey(); + boolean flag = (mCard.getSigningMethod()== TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer); + Issuer issuer = mCard.getIssuer(); + + + BigInteger fee = new BigInteger(feeValue, 10); + + BigDecimal amountDec = new BigDecimal(amountValue); + amountDec = amountDec.multiply(new BigDecimal("1000000000")); + + + BigInteger amount = amountDec.toBigInteger(); //new BigInteger(amountValue, 10); + amount = amount.subtract(fee); + + BigInteger nonce = nonceValue; + BigInteger gasPrice = fee.divide(BigInteger.valueOf(21000)); + BigInteger gasLimit = BigInteger.valueOf(21000); + Integer chainId = mCard.getBlockchain() == Blockchain.Ethereum ? ETH_Transaction.ChainEnum.Mainnet.getValue() : ETH_Transaction.ChainEnum.Rinkeby.getValue(); + + Long multiplicator = 1000000000L; + amount = amount.multiply(BigInteger.valueOf(multiplicator)); + gasPrice = gasPrice.multiply(BigInteger.valueOf(multiplicator)); + + String to = toValue; + + if (to.startsWith("0x") || to.startsWith("0X")) { + to = to.substring(2); + } + + ETH_Transaction tx = ETH_Transaction.create(to, amount, nonce, gasPrice, gasLimit, chainId); + + byte[][] hashesForSign = new byte[1][]; + byte[] for_hash = tx.getRawHash(); + hashesForSign[0] = for_hash; + + byte[] signFromCard = null; + try { + signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value; + // TODO slice signFromCard to hashes.length parts + } catch (Exception ex) { + Log.e("ETH", ex.getMessage()); + return null; + } + + LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); + + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, 32)); + BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32, 64)); + s = CryptoUtil.toCanonicalised(s); + + boolean f = ECKey.verify(for_hash, new ECKey.ECDSASignature(r, s), pbKey); + + if(!f) + { + Log.e("ETH-CHECK", "Sign Failed."); + } + + tx.signature = new ECDSASignature_ETH(r, s); + int v = tx.BruteRecoveryID2(tx.signature, for_hash, pbKey); + if (v != 27 && v != 28) { + Log.e("ETH", "invalid v"); + return null; + } + tx.signature.v = (byte) v; + Log.e("ETH_v", String.valueOf(v)); + + byte[] realTX = tx.getEncoded(); + return realTX; + } +} diff --git a/app/src/main/java/com/tangem/wallet/FingerprintHelper.java b/app/src/main/java/com/tangem/domain/wallet/FingerprintHelper.java similarity index 98% rename from app/src/main/java/com/tangem/wallet/FingerprintHelper.java rename to app/src/main/java/com/tangem/domain/wallet/FingerprintHelper.java index 0f61ac1853..438e6b833a 100644 --- a/app/src/main/java/com/tangem/wallet/FingerprintHelper.java +++ b/app/src/main/java/com/tangem/domain/wallet/FingerprintHelper.java @@ -1,4 +1,4 @@ -package com.tangem.wallet; +package com.tangem.domain.wallet; import android.annotation.TargetApi; import android.hardware.fingerprint.FingerprintManager; diff --git a/app/src/main/java/com/tangem/wallet/FormatUtil.java b/app/src/main/java/com/tangem/domain/wallet/FormatUtil.java similarity index 94% rename from app/src/main/java/com/tangem/wallet/FormatUtil.java rename to app/src/main/java/com/tangem/domain/wallet/FormatUtil.java index b11db9a2a8..2ba8a9efa4 100644 --- a/app/src/main/java/com/tangem/wallet/FormatUtil.java +++ b/app/src/main/java/com/tangem/domain/wallet/FormatUtil.java @@ -1,51 +1,51 @@ -package com.tangem.wallet; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.Locale; -import java.util.regex.Pattern; - -/** - * Created by Ilia on 15.02.2018. - */ - -public class FormatUtil { - public static long parseValue(String valueStr) throws NumberFormatException { - return new BigDecimal(valueStr).multiply(BigDecimal.valueOf(1_0000_0000)).setScale(0, BigDecimal.ROUND_HALF_DOWN).longValueExact(); - } - - public static String DoubleToString(double amount) - { - DecimalFormat myFormatter = GetDecimalFormat(); - String output = myFormatter.format(amount); - return output; - } - - public static DecimalFormat GetDecimalFormat() - { - DecimalFormatSymbols symbols = new DecimalFormatSymbols(); - symbols.setDecimalSeparator('.'); - - String pattern = "#0.######"; - DecimalFormat myFormatter = new DecimalFormat(pattern, symbols); - - myFormatter.setParseBigDecimal(true); - - return myFormatter; - } - - - public static long ConvertStringToLong(String caption) throws Exception { - - - BigDecimal d = new BigDecimal(caption); - d = d.multiply(new BigDecimal(100000)); - d = d.setScale(5); - BigInteger b = d.toBigInteger(); - long l = b.longValue(); - return l; - - } -} +package com.tangem.domain.wallet; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.Locale; +import java.util.regex.Pattern; + +/** + * Created by Ilia on 15.02.2018. + */ + +public class FormatUtil { + public static long parseValue(String valueStr) throws NumberFormatException { + return new BigDecimal(valueStr).multiply(BigDecimal.valueOf(1_0000_0000)).setScale(0, BigDecimal.ROUND_HALF_DOWN).longValueExact(); + } + + public static String DoubleToString(double amount) + { + DecimalFormat myFormatter = GetDecimalFormat(); + String output = myFormatter.format(amount); + return output; + } + + public static DecimalFormat GetDecimalFormat() + { + DecimalFormatSymbols symbols = new DecimalFormatSymbols(); + symbols.setDecimalSeparator('.'); + + String pattern = "#0.######"; + DecimalFormat myFormatter = new DecimalFormat(pattern, symbols); + + myFormatter.setParseBigDecimal(true); + + return myFormatter; + } + + + public static long ConvertStringToLong(String caption) throws Exception { + + + BigDecimal d = new BigDecimal(caption); + d = d.multiply(new BigDecimal(100000)); + d = d.setScale(5); + BigInteger b = d.toBigInteger(); + long l = b.longValue(); + return l; + + } +} diff --git a/app/src/main/java/com/tangem/wallet/Infura_Request.java b/app/src/main/java/com/tangem/domain/wallet/Infura_Request.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/Infura_Request.java rename to app/src/main/java/com/tangem/domain/wallet/Infura_Request.java index 1828cdcf35..5ca8dcae70 100644 --- a/app/src/main/java/com/tangem/wallet/Infura_Request.java +++ b/app/src/main/java/com/tangem/domain/wallet/Infura_Request.java @@ -1,197 +1,197 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 19.12.2017. - */ - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - - -public class Infura_Request { - public static final String METHOD_ETH_GetBalance = "eth_getBalance"; - public static final String METHOD_ETH_GetOutTransactionCount = "eth_getTransactionCount"; - public static final String METHOD_ETH_GetGasPrice = "eth_gasPrice"; - public static final String METHOD_ETH_SendRawTransaction = "eth_sendRawTransaction"; - public static final String METHOD_ETH_Call = "eth_call"; - - public JSONObject jsRequestData; - public String answerData; - public String error; - public String WalletAddress; - public int Dec; - public String amount; - public Blockchain blockchain; - - public void setBlockchain(Blockchain value) { - blockchain = value; - } - - public Blockchain getBlockchain() - { - return blockchain; - } - - private Infura_Request() { - } - - public Infura_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", value/*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 boolean isMethod(String methodName) throws JSONException { - return jsRequestData.getString("method").equals(methodName); - } - - public static Infura_Request GetBalance(String wallet) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetBalance + "\", \"params\":[\"" + wallet + "\", \"latest\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - public static Infura_Request GetTokenBalance(String wallet, String contract, int dec) - { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.Dec = dec; - String address = wallet.substring(2); - String dataValue = String.format("{\"data\": \"0x70a08231000000000000000000000000%s\", \"to\": \"%s\"}", address, contract); - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_Call + "\", \"params\":[" +dataValue+", \"latest\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - public static Infura_Request SendTransaction(String wallet, String tx) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_SendRawTransaction + "\", \"params\":[\"" + tx + "\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - - - public static Infura_Request GetOutTransactionCount(String wallet) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetOutTransactionCount + "\", \"params\":[\"" + wallet + "\", \"latest\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - public static Infura_Request GetPendingTransactionCount(String wallet) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetOutTransactionCount + "\", \"params\":[\"" + wallet + "\", \"pending\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - public static Infura_Request GetGasPrise(String wallet) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetGasPrice + "\", \"params\":[] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - - public static Infura_Request SendTransactionCount(String wallet, String TX) { - Infura_Request request = new Infura_Request(); - try { - request.WalletAddress=wallet; - request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_SendRawTransaction + "\", \"params\":[\"" + TX + "\"] }"); - } catch (JSONException e) { - e.printStackTrace(); - request.error = e.toString(); - } - return request; - } - - - - //METHOD_ETH_GetOutTransactionCount - - - 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.domain.wallet; + +/** + * Created by Ilia on 19.12.2017. + */ + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + + +public class Infura_Request { + public static final String METHOD_ETH_GetBalance = "eth_getBalance"; + public static final String METHOD_ETH_GetOutTransactionCount = "eth_getTransactionCount"; + public static final String METHOD_ETH_GetGasPrice = "eth_gasPrice"; + public static final String METHOD_ETH_SendRawTransaction = "eth_sendRawTransaction"; + public static final String METHOD_ETH_Call = "eth_call"; + + public JSONObject jsRequestData; + public String answerData; + public String error; + public String WalletAddress; + public int Dec; + public String amount; + public Blockchain blockchain; + + public void setBlockchain(Blockchain value) { + blockchain = value; + } + + public Blockchain getBlockchain() + { + return blockchain; + } + + private Infura_Request() { + } + + public Infura_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", value/*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 boolean isMethod(String methodName) throws JSONException { + return jsRequestData.getString("method").equals(methodName); + } + + public static Infura_Request GetBalance(String wallet) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetBalance + "\", \"params\":[\"" + wallet + "\", \"latest\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + public static Infura_Request GetTokenBalance(String wallet, String contract, int dec) + { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.Dec = dec; + String address = wallet.substring(2); + String dataValue = String.format("{\"data\": \"0x70a08231000000000000000000000000%s\", \"to\": \"%s\"}", address, contract); + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_Call + "\", \"params\":[" +dataValue+", \"latest\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + public static Infura_Request SendTransaction(String wallet, String tx) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_SendRawTransaction + "\", \"params\":[\"" + tx + "\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + + + public static Infura_Request GetOutTransactionCount(String wallet) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetOutTransactionCount + "\", \"params\":[\"" + wallet + "\", \"latest\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + public static Infura_Request GetPendingTransactionCount(String wallet) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetOutTransactionCount + "\", \"params\":[\"" + wallet + "\", \"pending\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + public static Infura_Request GetGasPrise(String wallet) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_GetGasPrice + "\", \"params\":[] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + + public static Infura_Request SendTransactionCount(String wallet, String TX) { + Infura_Request request = new Infura_Request(); + try { + request.WalletAddress=wallet; + request.jsRequestData = new JSONObject("{ \"method\":\"" + METHOD_ETH_SendRawTransaction + "\", \"params\":[\"" + TX + "\"] }"); + } catch (JSONException e) { + e.printStackTrace(); + request.error = e.toString(); + } + return request; + } + + + + //METHOD_ETH_GetOutTransactionCount + + + 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"); + } +} + diff --git a/app/src/main/java/com/tangem/wallet/Issuer.java b/app/src/main/java/com/tangem/domain/wallet/Issuer.java similarity index 97% rename from app/src/main/java/com/tangem/wallet/Issuer.java rename to app/src/main/java/com/tangem/domain/wallet/Issuer.java index a6dd2539c2..cf37b68369 100644 --- a/app/src/main/java/com/tangem/wallet/Issuer.java +++ b/app/src/main/java/com/tangem/domain/wallet/Issuer.java @@ -1,120 +1,120 @@ -package com.tangem.wallet; - -import com.tangem.domain.cardReader.CardCrypto; - -import java.util.Arrays; - -/** - * Created by dvol on 14.11.2017. - */ - -public enum Issuer { - Unknown("Unknown", "Unknown", null, null, null, null), - SMART_CASH_AG("SMART CASH AG", "SMART CASH AG", - IssuerKeyStorage.sdkPrivateDataKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateDataKey), - IssuerKeyStorage.sdkPrivateTransactionKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateTransactionKey)), - TANGEM_SDK("TANGEM SDK", "TANGEM SDK", - IssuerKeyStorage.sdkPrivateDataKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateDataKey), - IssuerKeyStorage.sdkPrivateTransactionKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateTransactionKey)), - TANGEM("TANGEM", "TANGEM", null, IssuerKeyStorage.tangemPublicDataKey, null, IssuerKeyStorage.tangemPublicTransactionKey) - ; - - - static class IssuerKeyStorage { - private static final byte[] sdkPrivateDataKey = new byte[]{ - (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18, - (byte) 0x47, (byte) 0x71, (byte) 0xED, (byte) 0x81, (byte) 0xF2, (byte) 0xBA, (byte) 0xCF, (byte) 0x57, - (byte) 0x47, (byte) 0x9E, (byte) 0x47, (byte) 0x35, (byte) 0xEB, (byte) 0x14, (byte) 0x05, (byte) 0x08, - (byte) 0x39, (byte) 0x27, (byte) 0x37, (byte) 0x2D, (byte) 0x40, (byte) 0xDA, (byte) 0x9E, (byte) 0x92}; - - private static final byte[] sdkPrivateTransactionKey = new byte[]{ - (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18, - (byte) 0x47, (byte) 0x71, (byte) 0xED, (byte) 0x81, (byte) 0xF2, (byte) 0xBA, (byte) 0xCF, (byte) 0x57, - (byte) 0x47, (byte) 0x9E, (byte) 0x47, (byte) 0x35, (byte) 0xEB, (byte) 0x14, (byte) 0x05, (byte) 0x08, - (byte) 0x19, (byte) 0x18, (byte) 0x17, (byte) 0x16, (byte) 0x15, (byte) 0x14, (byte) 0x13, (byte) 0x12}; - - private static byte[] tangemPublicDataKey = { - (byte) 0x04 , - (byte) 0x81 ,(byte) 0x96 ,(byte) 0xAA ,(byte) 0x4B ,(byte) 0x41 ,(byte) 0x0A ,(byte) 0xC4 ,(byte) 0x4A, - (byte) 0x3B ,(byte) 0x9C ,(byte) 0xCE ,(byte) 0x18 ,(byte) 0xE7 ,(byte) 0xBE ,(byte) 0x22 ,(byte) 0x6A, - (byte) 0xEA ,(byte) 0x07 ,(byte) 0x0A ,(byte) 0xCC ,(byte) 0x83 ,(byte) 0xA9 ,(byte) 0xCF ,(byte) 0x67, - (byte) 0x54 ,(byte) 0x0F ,(byte) 0xAC ,(byte) 0x49 ,(byte) 0xAF ,(byte) 0x25 ,(byte) 0x12 ,(byte) 0x9F, - (byte) 0x6A ,(byte) 0x53 ,(byte) 0x8A ,(byte) 0x28 ,(byte) 0xAD ,(byte) 0x63 ,(byte) 0x41 ,(byte) 0x35, - (byte) 0x8E ,(byte) 0x3C ,(byte) 0x4F ,(byte) 0x99 ,(byte) 0x63 ,(byte) 0x06 ,(byte) 0x4F ,(byte) 0x7E, - (byte) 0x36 ,(byte) 0x53 ,(byte) 0x72 ,(byte) 0xA6 ,(byte) 0x51 ,(byte) 0xD3 ,(byte) 0x74 ,(byte) 0xE5, - (byte) 0xC2 ,(byte) 0x3C ,(byte) 0xDD ,(byte) 0x37 ,(byte) 0xFD ,(byte) 0x09 ,(byte) 0x9B ,(byte) 0xF2}; - - private static byte[] tangemPublicTransactionKey = { - (byte) 0x04 , - (byte) 0x34 ,(byte) 0x3D ,(byte) 0x40 ,(byte) 0x49 ,(byte) 0x6C ,(byte) 0xBE ,(byte) 0x1F ,(byte) 0xE8, - (byte) 0xA8 ,(byte) 0xC0 ,(byte) 0x26 ,(byte) 0x57 ,(byte) 0x5C ,(byte) 0x43 ,(byte) 0x5A ,(byte) 0x29, - (byte) 0x14 ,(byte) 0x1E ,(byte) 0xA3 ,(byte) 0xBC ,(byte) 0x33 ,(byte) 0x5D ,(byte) 0xA5 ,(byte) 0x54, - (byte) 0x9A ,(byte) 0xB6 ,(byte) 0xC6 ,(byte) 0x46 ,(byte) 0x85 ,(byte) 0xA6 ,(byte) 0x46 ,(byte) 0x84, - (byte) 0x80 ,(byte) 0x36 ,(byte) 0xD4 ,(byte) 0x81 ,(byte) 0xCF ,(byte) 0x9A ,(byte) 0x98 ,(byte) 0x93, - (byte) 0x90 ,(byte) 0xA8 ,(byte) 0xB0 ,(byte) 0x34 ,(byte) 0xB2 ,(byte) 0x29 ,(byte) 0xD9 ,(byte) 0x9B, - (byte) 0xD4 ,(byte) 0x9E ,(byte) 0x6F ,(byte) 0x07 ,(byte) 0xD2 ,(byte) 0xFF ,(byte) 0x02 ,(byte) 0x74, - (byte) 0x6E ,(byte) 0xA2 ,(byte) 0x65 ,(byte) 0xEF ,(byte) 0x99 ,(byte) 0x38 ,(byte) 0x0A ,(byte) 0x80}; - - public static byte[] GeneratePublicKey(byte[] privateKey) { - try { - return CardCrypto.GeneratePublicKey(privateKey); - } - catch (Exception e) - { - e.printStackTrace(); - return null; - } - } - } - - private String ID; - private String officialName; - private byte[] privateDataKeyArray; - private byte[] publicDataKeyArray; - private byte[] privateTransactionKeyArray; - private byte[] publicTransactionKeyArray; - - Issuer(String id, String officialName, byte[] privateDataKey, byte[] publicDataKey, byte[] privateTransactionKey, byte[] publicTransactionKey) { - this.ID = id; - this.officialName = officialName; - this.privateDataKeyArray = privateDataKey; - this.privateTransactionKeyArray = privateTransactionKey; - this.publicDataKeyArray = publicDataKey; - this.publicTransactionKeyArray = publicTransactionKey; - } - - public byte[] getPublicDataKey() { - return publicDataKeyArray; - } - - public byte[] getPublicTransactionKey() { - return publicTransactionKeyArray; - } - - public byte[] getPrivateDataKey() { - return privateDataKeyArray; - } - - public byte[] getPrivateTransactionKey() { - return privateTransactionKeyArray; - } - - public byte[] getID() { - return ID.getBytes(); - } - - public String getOfficialName() { - return officialName; - } - - public static Issuer FindIssuer(String ID, byte[] publicDataKey) { - Issuer[] issuers = Issuer.values(); - for (int i = 1; i < issuers.length; i++) { - if (issuers[i].ID.equals(ID) && Arrays.equals(issuers[i].getPublicDataKey(), publicDataKey)) { - return issuers[i]; - } - } - return Issuer.Unknown; - } - -} +package com.tangem.domain.wallet; + +import com.tangem.domain.cardReader.CardCrypto; + +import java.util.Arrays; + +/** + * Created by dvol on 14.11.2017. + */ + +public enum Issuer { + Unknown("Unknown", "Unknown", null, null, null, null), + SMART_CASH_AG("SMART CASH AG", "SMART CASH AG", + IssuerKeyStorage.sdkPrivateDataKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateDataKey), + IssuerKeyStorage.sdkPrivateTransactionKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateTransactionKey)), + TANGEM_SDK("TANGEM SDK", "TANGEM SDK", + IssuerKeyStorage.sdkPrivateDataKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateDataKey), + IssuerKeyStorage.sdkPrivateTransactionKey, IssuerKeyStorage.GeneratePublicKey(IssuerKeyStorage.sdkPrivateTransactionKey)), + TANGEM("TANGEM", "TANGEM", null, IssuerKeyStorage.tangemPublicDataKey, null, IssuerKeyStorage.tangemPublicTransactionKey) + ; + + + static class IssuerKeyStorage { + private static final byte[] sdkPrivateDataKey = new byte[]{ + (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18, + (byte) 0x47, (byte) 0x71, (byte) 0xED, (byte) 0x81, (byte) 0xF2, (byte) 0xBA, (byte) 0xCF, (byte) 0x57, + (byte) 0x47, (byte) 0x9E, (byte) 0x47, (byte) 0x35, (byte) 0xEB, (byte) 0x14, (byte) 0x05, (byte) 0x08, + (byte) 0x39, (byte) 0x27, (byte) 0x37, (byte) 0x2D, (byte) 0x40, (byte) 0xDA, (byte) 0x9E, (byte) 0x92}; + + private static final byte[] sdkPrivateTransactionKey = new byte[]{ + (byte) 0x11, (byte) 0x12, (byte) 0x13, (byte) 0x14, (byte) 0x15, (byte) 0x16, (byte) 0x17, (byte) 0x18, + (byte) 0x47, (byte) 0x71, (byte) 0xED, (byte) 0x81, (byte) 0xF2, (byte) 0xBA, (byte) 0xCF, (byte) 0x57, + (byte) 0x47, (byte) 0x9E, (byte) 0x47, (byte) 0x35, (byte) 0xEB, (byte) 0x14, (byte) 0x05, (byte) 0x08, + (byte) 0x19, (byte) 0x18, (byte) 0x17, (byte) 0x16, (byte) 0x15, (byte) 0x14, (byte) 0x13, (byte) 0x12}; + + private static byte[] tangemPublicDataKey = { + (byte) 0x04 , + (byte) 0x81 ,(byte) 0x96 ,(byte) 0xAA ,(byte) 0x4B ,(byte) 0x41 ,(byte) 0x0A ,(byte) 0xC4 ,(byte) 0x4A, + (byte) 0x3B ,(byte) 0x9C ,(byte) 0xCE ,(byte) 0x18 ,(byte) 0xE7 ,(byte) 0xBE ,(byte) 0x22 ,(byte) 0x6A, + (byte) 0xEA ,(byte) 0x07 ,(byte) 0x0A ,(byte) 0xCC ,(byte) 0x83 ,(byte) 0xA9 ,(byte) 0xCF ,(byte) 0x67, + (byte) 0x54 ,(byte) 0x0F ,(byte) 0xAC ,(byte) 0x49 ,(byte) 0xAF ,(byte) 0x25 ,(byte) 0x12 ,(byte) 0x9F, + (byte) 0x6A ,(byte) 0x53 ,(byte) 0x8A ,(byte) 0x28 ,(byte) 0xAD ,(byte) 0x63 ,(byte) 0x41 ,(byte) 0x35, + (byte) 0x8E ,(byte) 0x3C ,(byte) 0x4F ,(byte) 0x99 ,(byte) 0x63 ,(byte) 0x06 ,(byte) 0x4F ,(byte) 0x7E, + (byte) 0x36 ,(byte) 0x53 ,(byte) 0x72 ,(byte) 0xA6 ,(byte) 0x51 ,(byte) 0xD3 ,(byte) 0x74 ,(byte) 0xE5, + (byte) 0xC2 ,(byte) 0x3C ,(byte) 0xDD ,(byte) 0x37 ,(byte) 0xFD ,(byte) 0x09 ,(byte) 0x9B ,(byte) 0xF2}; + + private static byte[] tangemPublicTransactionKey = { + (byte) 0x04 , + (byte) 0x34 ,(byte) 0x3D ,(byte) 0x40 ,(byte) 0x49 ,(byte) 0x6C ,(byte) 0xBE ,(byte) 0x1F ,(byte) 0xE8, + (byte) 0xA8 ,(byte) 0xC0 ,(byte) 0x26 ,(byte) 0x57 ,(byte) 0x5C ,(byte) 0x43 ,(byte) 0x5A ,(byte) 0x29, + (byte) 0x14 ,(byte) 0x1E ,(byte) 0xA3 ,(byte) 0xBC ,(byte) 0x33 ,(byte) 0x5D ,(byte) 0xA5 ,(byte) 0x54, + (byte) 0x9A ,(byte) 0xB6 ,(byte) 0xC6 ,(byte) 0x46 ,(byte) 0x85 ,(byte) 0xA6 ,(byte) 0x46 ,(byte) 0x84, + (byte) 0x80 ,(byte) 0x36 ,(byte) 0xD4 ,(byte) 0x81 ,(byte) 0xCF ,(byte) 0x9A ,(byte) 0x98 ,(byte) 0x93, + (byte) 0x90 ,(byte) 0xA8 ,(byte) 0xB0 ,(byte) 0x34 ,(byte) 0xB2 ,(byte) 0x29 ,(byte) 0xD9 ,(byte) 0x9B, + (byte) 0xD4 ,(byte) 0x9E ,(byte) 0x6F ,(byte) 0x07 ,(byte) 0xD2 ,(byte) 0xFF ,(byte) 0x02 ,(byte) 0x74, + (byte) 0x6E ,(byte) 0xA2 ,(byte) 0x65 ,(byte) 0xEF ,(byte) 0x99 ,(byte) 0x38 ,(byte) 0x0A ,(byte) 0x80}; + + public static byte[] GeneratePublicKey(byte[] privateKey) { + try { + return CardCrypto.GeneratePublicKey(privateKey); + } + catch (Exception e) + { + e.printStackTrace(); + return null; + } + } + } + + private String ID; + private String officialName; + private byte[] privateDataKeyArray; + private byte[] publicDataKeyArray; + private byte[] privateTransactionKeyArray; + private byte[] publicTransactionKeyArray; + + Issuer(String id, String officialName, byte[] privateDataKey, byte[] publicDataKey, byte[] privateTransactionKey, byte[] publicTransactionKey) { + this.ID = id; + this.officialName = officialName; + this.privateDataKeyArray = privateDataKey; + this.privateTransactionKeyArray = privateTransactionKey; + this.publicDataKeyArray = publicDataKey; + this.publicTransactionKeyArray = publicTransactionKey; + } + + public byte[] getPublicDataKey() { + return publicDataKeyArray; + } + + public byte[] getPublicTransactionKey() { + return publicTransactionKeyArray; + } + + public byte[] getPrivateDataKey() { + return privateDataKeyArray; + } + + public byte[] getPrivateTransactionKey() { + return privateTransactionKeyArray; + } + + public byte[] getID() { + return ID.getBytes(); + } + + public String getOfficialName() { + return officialName; + } + + public static Issuer FindIssuer(String ID, byte[] publicDataKey) { + Issuer[] issuers = Issuer.values(); + for (int i = 1; i < issuers.length; i++) { + if (issuers[i].ID.equals(ID) && Arrays.equals(issuers[i].getPublicDataKey(), publicDataKey)) { + return issuers[i]; + } + } + return Issuer.Unknown; + } + +} diff --git a/app/src/main/java/com/tangem/wallet/Keccak256.java b/app/src/main/java/com/tangem/domain/wallet/Keccak256.java similarity index 90% rename from app/src/main/java/com/tangem/wallet/Keccak256.java rename to app/src/main/java/com/tangem/domain/wallet/Keccak256.java index b3162f63a8..ba0d30fe41 100644 --- a/app/src/main/java/com/tangem/wallet/Keccak256.java +++ b/app/src/main/java/com/tangem/domain/wallet/Keccak256.java @@ -1,39 +1,39 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 18.12.2017. - */ - -public class Keccak256 extends KeccakCore { - - /** - * Create the engine. - */ - public Keccak256() - { - super("eth-keccak-256"); - } - - public Digest copy() - { - return copyState(new Keccak256()); - } - - public int engineGetDigestLength() - { - return 32; - } - - @Override - protected byte[] engineDigest() { - return null; - } - - @Override - protected void engineUpdate(byte arg0) { - } - - @Override - protected void engineUpdate(byte[] arg0, int arg1, int arg2) { - } +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 18.12.2017. + */ + +public class Keccak256 extends KeccakCore { + + /** + * Create the engine. + */ + public Keccak256() + { + super("eth-keccak-256"); + } + + public Digest copy() + { + return copyState(new Keccak256()); + } + + public int engineGetDigestLength() + { + return 32; + } + + @Override + protected byte[] engineDigest() { + return null; + } + + @Override + protected void engineUpdate(byte arg0) { + } + + @Override + protected void engineUpdate(byte[] arg0, int arg1, int arg2) { + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/KeccakCore.java b/app/src/main/java/com/tangem/domain/wallet/KeccakCore.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/KeccakCore.java rename to app/src/main/java/com/tangem/domain/wallet/KeccakCore.java index 0f02ef6f79..7b5fe7a76e 100644 --- a/app/src/main/java/com/tangem/wallet/KeccakCore.java +++ b/app/src/main/java/com/tangem/domain/wallet/KeccakCore.java @@ -1,546 +1,546 @@ -package com.tangem.wallet; - - -/** - * Created by Ilia on 18.12.2017. - */ -abstract class KeccakCore extends DigestEngine{ - KeccakCore(String alg) - { - super(alg); - } - - private long[] A; - private byte[] tmpOut; - - private static final long[] RC = { - 0x0000000000000001L, 0x0000000000008082L, - 0x800000000000808AL, 0x8000000080008000L, - 0x000000000000808BL, 0x0000000080000001L, - 0x8000000080008081L, 0x8000000000008009L, - 0x000000000000008AL, 0x0000000000000088L, - 0x0000000080008009L, 0x000000008000000AL, - 0x000000008000808BL, 0x800000000000008BL, - 0x8000000000008089L, 0x8000000000008003L, - 0x8000000000008002L, 0x8000000000000080L, - 0x000000000000800AL, 0x800000008000000AL, - 0x8000000080008081L, 0x8000000000008080L, - 0x0000000080000001L, 0x8000000080008008L - }; - - /** - * Encode the 64-bit word {@code val} into the array - * {@code buf} at offset {@code off}, in little-endian - * convention (least significant byte first). - * - * @param val the value to encode - * @param buf the destination buffer - * @param off the destination offset - */ - private static void encodeLELong(long val, byte[] buf, int off) - { - buf[off + 0] = (byte)val; - buf[off + 1] = (byte)(val >>> 8); - buf[off + 2] = (byte)(val >>> 16); - buf[off + 3] = (byte)(val >>> 24); - buf[off + 4] = (byte)(val >>> 32); - buf[off + 5] = (byte)(val >>> 40); - buf[off + 6] = (byte)(val >>> 48); - buf[off + 7] = (byte)(val >>> 56); - } - - /** - * Decode a 64-bit little-endian word from the array {@code buf} - * at offset {@code off}. - * - * @param buf the source buffer - * @param off the source offset - * @return the decoded value - */ - private static long decodeLELong(byte[] buf, int off) - { - return (buf[off + 0] & 0xFFL) - | ((buf[off + 1] & 0xFFL) << 8) - | ((buf[off + 2] & 0xFFL) << 16) - | ((buf[off + 3] & 0xFFL) << 24) - | ((buf[off + 4] & 0xFFL) << 32) - | ((buf[off + 5] & 0xFFL) << 40) - | ((buf[off + 6] & 0xFFL) << 48) - | ((buf[off + 7] & 0xFFL) << 56); - } - - protected void engineReset() - { - doReset(); - } - - protected void processBlock(byte[] data) - { - /* Input block */ - for (int i = 0; i < data.length; i += 8) - A[i >>> 3] ^= decodeLELong(data, i); - - long t0, t1, t2, t3, t4; - long tt0, tt1, tt2, tt3, tt4; - long t, kt; - long c0, c1, c2, c3, c4, bnn; - - /* - * Unrolling four rounds kills performance big time - * on Intel x86 Core2, in both 32-bit and 64-bit modes - * (less than 1 MB/s instead of 55 MB/s on x86-64). - * Unrolling two rounds appears to be fine. - */ - for (int j = 0; j < 24; j += 2) { - - tt0 = A[ 1] ^ A[ 6]; - tt1 = A[11] ^ A[16]; - tt0 ^= A[21] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 4] ^ A[ 9]; - tt3 = A[14] ^ A[19]; - tt0 ^= A[24]; - tt2 ^= tt3; - t0 = tt0 ^ tt2; - - tt0 = A[ 2] ^ A[ 7]; - tt1 = A[12] ^ A[17]; - tt0 ^= A[22] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 0] ^ A[ 5]; - tt3 = A[10] ^ A[15]; - tt0 ^= A[20]; - tt2 ^= tt3; - t1 = tt0 ^ tt2; - - tt0 = A[ 3] ^ A[ 8]; - tt1 = A[13] ^ A[18]; - tt0 ^= A[23] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 1] ^ A[ 6]; - tt3 = A[11] ^ A[16]; - tt0 ^= A[21]; - tt2 ^= tt3; - t2 = tt0 ^ tt2; - - tt0 = A[ 4] ^ A[ 9]; - tt1 = A[14] ^ A[19]; - tt0 ^= A[24] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 2] ^ A[ 7]; - tt3 = A[12] ^ A[17]; - tt0 ^= A[22]; - tt2 ^= tt3; - t3 = tt0 ^ tt2; - - tt0 = A[ 0] ^ A[ 5]; - tt1 = A[10] ^ A[15]; - tt0 ^= A[20] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 3] ^ A[ 8]; - tt3 = A[13] ^ A[18]; - tt0 ^= A[23]; - tt2 ^= tt3; - t4 = tt0 ^ tt2; - - A[ 0] = A[ 0] ^ t0; - A[ 5] = A[ 5] ^ t0; - A[10] = A[10] ^ t0; - A[15] = A[15] ^ t0; - A[20] = A[20] ^ t0; - A[ 1] = A[ 1] ^ t1; - A[ 6] = A[ 6] ^ t1; - A[11] = A[11] ^ t1; - A[16] = A[16] ^ t1; - A[21] = A[21] ^ t1; - A[ 2] = A[ 2] ^ t2; - A[ 7] = A[ 7] ^ t2; - A[12] = A[12] ^ t2; - A[17] = A[17] ^ t2; - A[22] = A[22] ^ t2; - A[ 3] = A[ 3] ^ t3; - A[ 8] = A[ 8] ^ t3; - A[13] = A[13] ^ t3; - A[18] = A[18] ^ t3; - A[23] = A[23] ^ t3; - A[ 4] = A[ 4] ^ t4; - A[ 9] = A[ 9] ^ t4; - A[14] = A[14] ^ t4; - A[19] = A[19] ^ t4; - A[24] = A[24] ^ t4; - A[ 5] = (A[ 5] << 36) | (A[ 5] >>> (64 - 36)); - A[10] = (A[10] << 3) | (A[10] >>> (64 - 3)); - A[15] = (A[15] << 41) | (A[15] >>> (64 - 41)); - A[20] = (A[20] << 18) | (A[20] >>> (64 - 18)); - A[ 1] = (A[ 1] << 1) | (A[ 1] >>> (64 - 1)); - A[ 6] = (A[ 6] << 44) | (A[ 6] >>> (64 - 44)); - A[11] = (A[11] << 10) | (A[11] >>> (64 - 10)); - A[16] = (A[16] << 45) | (A[16] >>> (64 - 45)); - A[21] = (A[21] << 2) | (A[21] >>> (64 - 2)); - A[ 2] = (A[ 2] << 62) | (A[ 2] >>> (64 - 62)); - A[ 7] = (A[ 7] << 6) | (A[ 7] >>> (64 - 6)); - A[12] = (A[12] << 43) | (A[12] >>> (64 - 43)); - A[17] = (A[17] << 15) | (A[17] >>> (64 - 15)); - A[22] = (A[22] << 61) | (A[22] >>> (64 - 61)); - A[ 3] = (A[ 3] << 28) | (A[ 3] >>> (64 - 28)); - A[ 8] = (A[ 8] << 55) | (A[ 8] >>> (64 - 55)); - A[13] = (A[13] << 25) | (A[13] >>> (64 - 25)); - A[18] = (A[18] << 21) | (A[18] >>> (64 - 21)); - A[23] = (A[23] << 56) | (A[23] >>> (64 - 56)); - A[ 4] = (A[ 4] << 27) | (A[ 4] >>> (64 - 27)); - A[ 9] = (A[ 9] << 20) | (A[ 9] >>> (64 - 20)); - A[14] = (A[14] << 39) | (A[14] >>> (64 - 39)); - A[19] = (A[19] << 8) | (A[19] >>> (64 - 8)); - A[24] = (A[24] << 14) | (A[24] >>> (64 - 14)); - bnn = ~A[12]; - kt = A[ 6] | A[12]; - c0 = A[ 0] ^ kt; - kt = bnn | A[18]; - c1 = A[ 6] ^ kt; - kt = A[18] & A[24]; - c2 = A[12] ^ kt; - kt = A[24] | A[ 0]; - c3 = A[18] ^ kt; - kt = A[ 0] & A[ 6]; - c4 = A[24] ^ kt; - A[ 0] = c0; - A[ 6] = c1; - A[12] = c2; - A[18] = c3; - A[24] = c4; - bnn = ~A[22]; - kt = A[ 9] | A[10]; - c0 = A[ 3] ^ kt; - kt = A[10] & A[16]; - c1 = A[ 9] ^ kt; - kt = A[16] | bnn; - c2 = A[10] ^ kt; - kt = A[22] | A[ 3]; - c3 = A[16] ^ kt; - kt = A[ 3] & A[ 9]; - c4 = A[22] ^ kt; - A[ 3] = c0; - A[ 9] = c1; - A[10] = c2; - A[16] = c3; - A[22] = c4; - bnn = ~A[19]; - kt = A[ 7] | A[13]; - c0 = A[ 1] ^ kt; - kt = A[13] & A[19]; - c1 = A[ 7] ^ kt; - kt = bnn & A[20]; - c2 = A[13] ^ kt; - kt = A[20] | A[ 1]; - c3 = bnn ^ kt; - kt = A[ 1] & A[ 7]; - c4 = A[20] ^ kt; - A[ 1] = c0; - A[ 7] = c1; - A[13] = c2; - A[19] = c3; - A[20] = c4; - bnn = ~A[17]; - kt = A[ 5] & A[11]; - c0 = A[ 4] ^ kt; - kt = A[11] | A[17]; - c1 = A[ 5] ^ kt; - kt = bnn | A[23]; - c2 = A[11] ^ kt; - kt = A[23] & A[ 4]; - c3 = bnn ^ kt; - kt = A[ 4] | A[ 5]; - c4 = A[23] ^ kt; - A[ 4] = c0; - A[ 5] = c1; - A[11] = c2; - A[17] = c3; - A[23] = c4; - bnn = ~A[ 8]; - kt = bnn & A[14]; - c0 = A[ 2] ^ kt; - kt = A[14] | A[15]; - c1 = bnn ^ kt; - kt = A[15] & A[21]; - c2 = A[14] ^ kt; - kt = A[21] | A[ 2]; - c3 = A[15] ^ kt; - kt = A[ 2] & A[ 8]; - c4 = A[21] ^ kt; - A[ 2] = c0; - A[ 8] = c1; - A[14] = c2; - A[15] = c3; - A[21] = c4; - A[ 0] = A[ 0] ^ RC[j + 0]; - - tt0 = A[ 6] ^ A[ 9]; - tt1 = A[ 7] ^ A[ 5]; - tt0 ^= A[ 8] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[24] ^ A[22]; - tt3 = A[20] ^ A[23]; - tt0 ^= A[21]; - tt2 ^= tt3; - t0 = tt0 ^ tt2; - - tt0 = A[12] ^ A[10]; - tt1 = A[13] ^ A[11]; - tt0 ^= A[14] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 0] ^ A[ 3]; - tt3 = A[ 1] ^ A[ 4]; - tt0 ^= A[ 2]; - tt2 ^= tt3; - t1 = tt0 ^ tt2; - - tt0 = A[18] ^ A[16]; - tt1 = A[19] ^ A[17]; - tt0 ^= A[15] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[ 6] ^ A[ 9]; - tt3 = A[ 7] ^ A[ 5]; - tt0 ^= A[ 8]; - tt2 ^= tt3; - t2 = tt0 ^ tt2; - - tt0 = A[24] ^ A[22]; - tt1 = A[20] ^ A[23]; - tt0 ^= A[21] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[12] ^ A[10]; - tt3 = A[13] ^ A[11]; - tt0 ^= A[14]; - tt2 ^= tt3; - t3 = tt0 ^ tt2; - - tt0 = A[ 0] ^ A[ 3]; - tt1 = A[ 1] ^ A[ 4]; - tt0 ^= A[ 2] ^ tt1; - tt0 = (tt0 << 1) | (tt0 >>> 63); - tt2 = A[18] ^ A[16]; - tt3 = A[19] ^ A[17]; - tt0 ^= A[15]; - tt2 ^= tt3; - t4 = tt0 ^ tt2; - - A[ 0] = A[ 0] ^ t0; - A[ 3] = A[ 3] ^ t0; - A[ 1] = A[ 1] ^ t0; - A[ 4] = A[ 4] ^ t0; - A[ 2] = A[ 2] ^ t0; - A[ 6] = A[ 6] ^ t1; - A[ 9] = A[ 9] ^ t1; - A[ 7] = A[ 7] ^ t1; - A[ 5] = A[ 5] ^ t1; - A[ 8] = A[ 8] ^ t1; - A[12] = A[12] ^ t2; - A[10] = A[10] ^ t2; - A[13] = A[13] ^ t2; - A[11] = A[11] ^ t2; - A[14] = A[14] ^ t2; - A[18] = A[18] ^ t3; - A[16] = A[16] ^ t3; - A[19] = A[19] ^ t3; - A[17] = A[17] ^ t3; - A[15] = A[15] ^ t3; - A[24] = A[24] ^ t4; - A[22] = A[22] ^ t4; - A[20] = A[20] ^ t4; - A[23] = A[23] ^ t4; - A[21] = A[21] ^ t4; - A[ 3] = (A[ 3] << 36) | (A[ 3] >>> (64 - 36)); - A[ 1] = (A[ 1] << 3) | (A[ 1] >>> (64 - 3)); - A[ 4] = (A[ 4] << 41) | (A[ 4] >>> (64 - 41)); - A[ 2] = (A[ 2] << 18) | (A[ 2] >>> (64 - 18)); - A[ 6] = (A[ 6] << 1) | (A[ 6] >>> (64 - 1)); - A[ 9] = (A[ 9] << 44) | (A[ 9] >>> (64 - 44)); - A[ 7] = (A[ 7] << 10) | (A[ 7] >>> (64 - 10)); - A[ 5] = (A[ 5] << 45) | (A[ 5] >>> (64 - 45)); - A[ 8] = (A[ 8] << 2) | (A[ 8] >>> (64 - 2)); - A[12] = (A[12] << 62) | (A[12] >>> (64 - 62)); - A[10] = (A[10] << 6) | (A[10] >>> (64 - 6)); - A[13] = (A[13] << 43) | (A[13] >>> (64 - 43)); - A[11] = (A[11] << 15) | (A[11] >>> (64 - 15)); - A[14] = (A[14] << 61) | (A[14] >>> (64 - 61)); - A[18] = (A[18] << 28) | (A[18] >>> (64 - 28)); - A[16] = (A[16] << 55) | (A[16] >>> (64 - 55)); - A[19] = (A[19] << 25) | (A[19] >>> (64 - 25)); - A[17] = (A[17] << 21) | (A[17] >>> (64 - 21)); - A[15] = (A[15] << 56) | (A[15] >>> (64 - 56)); - A[24] = (A[24] << 27) | (A[24] >>> (64 - 27)); - A[22] = (A[22] << 20) | (A[22] >>> (64 - 20)); - A[20] = (A[20] << 39) | (A[20] >>> (64 - 39)); - A[23] = (A[23] << 8) | (A[23] >>> (64 - 8)); - A[21] = (A[21] << 14) | (A[21] >>> (64 - 14)); - bnn = ~A[13]; - kt = A[ 9] | A[13]; - c0 = A[ 0] ^ kt; - kt = bnn | A[17]; - c1 = A[ 9] ^ kt; - kt = A[17] & A[21]; - c2 = A[13] ^ kt; - kt = A[21] | A[ 0]; - c3 = A[17] ^ kt; - kt = A[ 0] & A[ 9]; - c4 = A[21] ^ kt; - A[ 0] = c0; - A[ 9] = c1; - A[13] = c2; - A[17] = c3; - A[21] = c4; - bnn = ~A[14]; - kt = A[22] | A[ 1]; - c0 = A[18] ^ kt; - kt = A[ 1] & A[ 5]; - c1 = A[22] ^ kt; - kt = A[ 5] | bnn; - c2 = A[ 1] ^ kt; - kt = A[14] | A[18]; - c3 = A[ 5] ^ kt; - kt = A[18] & A[22]; - c4 = A[14] ^ kt; - A[18] = c0; - A[22] = c1; - A[ 1] = c2; - A[ 5] = c3; - A[14] = c4; - bnn = ~A[23]; - kt = A[10] | A[19]; - c0 = A[ 6] ^ kt; - kt = A[19] & A[23]; - c1 = A[10] ^ kt; - kt = bnn & A[ 2]; - c2 = A[19] ^ kt; - kt = A[ 2] | A[ 6]; - c3 = bnn ^ kt; - kt = A[ 6] & A[10]; - c4 = A[ 2] ^ kt; - A[ 6] = c0; - A[10] = c1; - A[19] = c2; - A[23] = c3; - A[ 2] = c4; - bnn = ~A[11]; - kt = A[ 3] & A[ 7]; - c0 = A[24] ^ kt; - kt = A[ 7] | A[11]; - c1 = A[ 3] ^ kt; - kt = bnn | A[15]; - c2 = A[ 7] ^ kt; - kt = A[15] & A[24]; - c3 = bnn ^ kt; - kt = A[24] | A[ 3]; - c4 = A[15] ^ kt; - A[24] = c0; - A[ 3] = c1; - A[ 7] = c2; - A[11] = c3; - A[15] = c4; - bnn = ~A[16]; - kt = bnn & A[20]; - c0 = A[12] ^ kt; - kt = A[20] | A[ 4]; - c1 = bnn ^ kt; - kt = A[ 4] & A[ 8]; - c2 = A[20] ^ kt; - kt = A[ 8] | A[12]; - c3 = A[ 4] ^ kt; - kt = A[12] & A[16]; - c4 = A[ 8] ^ kt; - A[12] = c0; - A[16] = c1; - A[20] = c2; - A[ 4] = c3; - A[ 8] = c4; - A[ 0] = A[ 0] ^ RC[j + 1]; - t = A[ 5]; - A[ 5] = A[18]; - A[18] = A[11]; - A[11] = A[10]; - A[10] = A[ 6]; - A[ 6] = A[22]; - A[22] = A[20]; - A[20] = A[12]; - A[12] = A[19]; - A[19] = A[15]; - A[15] = A[24]; - A[24] = A[ 8]; - A[ 8] = t; - t = A[ 1]; - A[ 1] = A[ 9]; - A[ 9] = A[14]; - A[14] = A[ 2]; - A[ 2] = A[13]; - A[13] = A[23]; - A[23] = A[ 4]; - A[ 4] = A[21]; - A[21] = A[16]; - A[16] = A[ 3]; - A[ 3] = A[17]; - A[17] = A[ 7]; - A[ 7] = t; - } - } - - protected void doPadding(byte[] out, int off) - { - int ptr = flush(); - byte[] buf = getBlockBuffer(); - if ((ptr + 1) == buf.length) { - buf[ptr] = (byte)0x81; - } else { - buf[ptr] = (byte)0x01; - for (int i = ptr + 1; i < (buf.length - 1); i ++) - buf[i] = 0; - buf[buf.length - 1] = (byte)0x80; - } - processBlock(buf); - A[ 1] = ~A[ 1]; - A[ 2] = ~A[ 2]; - A[ 8] = ~A[ 8]; - A[12] = ~A[12]; - A[17] = ~A[17]; - A[20] = ~A[20]; - int dlen = engineGetDigestLength(); - for (int i = 0; i < dlen; i += 8) - encodeLELong(A[i >>> 3], tmpOut, i); - System.arraycopy(tmpOut, 0, out, off, dlen); - } - - protected void doInit() - { - A = new long[25]; - tmpOut = new byte[(engineGetDigestLength() + 7) & ~7]; - doReset(); - } - - public int getBlockLength() - { - return 200 - 2 * engineGetDigestLength(); - } - - private final void doReset() - { - for (int i = 0; i < 25; i ++) - A[i] = 0; - A[ 1] = 0xFFFFFFFFFFFFFFFFL; - A[ 2] = 0xFFFFFFFFFFFFFFFFL; - A[ 8] = 0xFFFFFFFFFFFFFFFFL; - A[12] = 0xFFFFFFFFFFFFFFFFL; - A[17] = 0xFFFFFFFFFFFFFFFFL; - A[20] = 0xFFFFFFFFFFFFFFFFL; - } - - - protected Digest copyState(KeccakCore dst) - { - System.arraycopy(A, 0, dst.A, 0, 25); - return super.copyState(dst); - } - - public String toString() - { - return "Keccak-" + (engineGetDigestLength() << 3); - } -} +package com.tangem.domain.wallet; + + +/** + * Created by Ilia on 18.12.2017. + */ +abstract class KeccakCore extends DigestEngine { + KeccakCore(String alg) + { + super(alg); + } + + private long[] A; + private byte[] tmpOut; + + private static final long[] RC = { + 0x0000000000000001L, 0x0000000000008082L, + 0x800000000000808AL, 0x8000000080008000L, + 0x000000000000808BL, 0x0000000080000001L, + 0x8000000080008081L, 0x8000000000008009L, + 0x000000000000008AL, 0x0000000000000088L, + 0x0000000080008009L, 0x000000008000000AL, + 0x000000008000808BL, 0x800000000000008BL, + 0x8000000000008089L, 0x8000000000008003L, + 0x8000000000008002L, 0x8000000000000080L, + 0x000000000000800AL, 0x800000008000000AL, + 0x8000000080008081L, 0x8000000000008080L, + 0x0000000080000001L, 0x8000000080008008L + }; + + /** + * Encode the 64-bit word {@code val} into the array + * {@code buf} at offset {@code off}, in little-endian + * convention (least significant byte first). + * + * @param val the value to encode + * @param buf the destination buffer + * @param off the destination offset + */ + private static void encodeLELong(long val, byte[] buf, int off) + { + buf[off + 0] = (byte)val; + buf[off + 1] = (byte)(val >>> 8); + buf[off + 2] = (byte)(val >>> 16); + buf[off + 3] = (byte)(val >>> 24); + buf[off + 4] = (byte)(val >>> 32); + buf[off + 5] = (byte)(val >>> 40); + buf[off + 6] = (byte)(val >>> 48); + buf[off + 7] = (byte)(val >>> 56); + } + + /** + * Decode a 64-bit little-endian word from the array {@code buf} + * at offset {@code off}. + * + * @param buf the source buffer + * @param off the source offset + * @return the decoded value + */ + private static long decodeLELong(byte[] buf, int off) + { + return (buf[off + 0] & 0xFFL) + | ((buf[off + 1] & 0xFFL) << 8) + | ((buf[off + 2] & 0xFFL) << 16) + | ((buf[off + 3] & 0xFFL) << 24) + | ((buf[off + 4] & 0xFFL) << 32) + | ((buf[off + 5] & 0xFFL) << 40) + | ((buf[off + 6] & 0xFFL) << 48) + | ((buf[off + 7] & 0xFFL) << 56); + } + + protected void engineReset() + { + doReset(); + } + + protected void processBlock(byte[] data) + { + /* Input block */ + for (int i = 0; i < data.length; i += 8) + A[i >>> 3] ^= decodeLELong(data, i); + + long t0, t1, t2, t3, t4; + long tt0, tt1, tt2, tt3, tt4; + long t, kt; + long c0, c1, c2, c3, c4, bnn; + + /* + * Unrolling four rounds kills performance big time + * on Intel x86 Core2, in both 32-bit and 64-bit modes + * (less than 1 MB/s instead of 55 MB/s on x86-64). + * Unrolling two rounds appears to be fine. + */ + for (int j = 0; j < 24; j += 2) { + + tt0 = A[ 1] ^ A[ 6]; + tt1 = A[11] ^ A[16]; + tt0 ^= A[21] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 4] ^ A[ 9]; + tt3 = A[14] ^ A[19]; + tt0 ^= A[24]; + tt2 ^= tt3; + t0 = tt0 ^ tt2; + + tt0 = A[ 2] ^ A[ 7]; + tt1 = A[12] ^ A[17]; + tt0 ^= A[22] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 0] ^ A[ 5]; + tt3 = A[10] ^ A[15]; + tt0 ^= A[20]; + tt2 ^= tt3; + t1 = tt0 ^ tt2; + + tt0 = A[ 3] ^ A[ 8]; + tt1 = A[13] ^ A[18]; + tt0 ^= A[23] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 1] ^ A[ 6]; + tt3 = A[11] ^ A[16]; + tt0 ^= A[21]; + tt2 ^= tt3; + t2 = tt0 ^ tt2; + + tt0 = A[ 4] ^ A[ 9]; + tt1 = A[14] ^ A[19]; + tt0 ^= A[24] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 2] ^ A[ 7]; + tt3 = A[12] ^ A[17]; + tt0 ^= A[22]; + tt2 ^= tt3; + t3 = tt0 ^ tt2; + + tt0 = A[ 0] ^ A[ 5]; + tt1 = A[10] ^ A[15]; + tt0 ^= A[20] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 3] ^ A[ 8]; + tt3 = A[13] ^ A[18]; + tt0 ^= A[23]; + tt2 ^= tt3; + t4 = tt0 ^ tt2; + + A[ 0] = A[ 0] ^ t0; + A[ 5] = A[ 5] ^ t0; + A[10] = A[10] ^ t0; + A[15] = A[15] ^ t0; + A[20] = A[20] ^ t0; + A[ 1] = A[ 1] ^ t1; + A[ 6] = A[ 6] ^ t1; + A[11] = A[11] ^ t1; + A[16] = A[16] ^ t1; + A[21] = A[21] ^ t1; + A[ 2] = A[ 2] ^ t2; + A[ 7] = A[ 7] ^ t2; + A[12] = A[12] ^ t2; + A[17] = A[17] ^ t2; + A[22] = A[22] ^ t2; + A[ 3] = A[ 3] ^ t3; + A[ 8] = A[ 8] ^ t3; + A[13] = A[13] ^ t3; + A[18] = A[18] ^ t3; + A[23] = A[23] ^ t3; + A[ 4] = A[ 4] ^ t4; + A[ 9] = A[ 9] ^ t4; + A[14] = A[14] ^ t4; + A[19] = A[19] ^ t4; + A[24] = A[24] ^ t4; + A[ 5] = (A[ 5] << 36) | (A[ 5] >>> (64 - 36)); + A[10] = (A[10] << 3) | (A[10] >>> (64 - 3)); + A[15] = (A[15] << 41) | (A[15] >>> (64 - 41)); + A[20] = (A[20] << 18) | (A[20] >>> (64 - 18)); + A[ 1] = (A[ 1] << 1) | (A[ 1] >>> (64 - 1)); + A[ 6] = (A[ 6] << 44) | (A[ 6] >>> (64 - 44)); + A[11] = (A[11] << 10) | (A[11] >>> (64 - 10)); + A[16] = (A[16] << 45) | (A[16] >>> (64 - 45)); + A[21] = (A[21] << 2) | (A[21] >>> (64 - 2)); + A[ 2] = (A[ 2] << 62) | (A[ 2] >>> (64 - 62)); + A[ 7] = (A[ 7] << 6) | (A[ 7] >>> (64 - 6)); + A[12] = (A[12] << 43) | (A[12] >>> (64 - 43)); + A[17] = (A[17] << 15) | (A[17] >>> (64 - 15)); + A[22] = (A[22] << 61) | (A[22] >>> (64 - 61)); + A[ 3] = (A[ 3] << 28) | (A[ 3] >>> (64 - 28)); + A[ 8] = (A[ 8] << 55) | (A[ 8] >>> (64 - 55)); + A[13] = (A[13] << 25) | (A[13] >>> (64 - 25)); + A[18] = (A[18] << 21) | (A[18] >>> (64 - 21)); + A[23] = (A[23] << 56) | (A[23] >>> (64 - 56)); + A[ 4] = (A[ 4] << 27) | (A[ 4] >>> (64 - 27)); + A[ 9] = (A[ 9] << 20) | (A[ 9] >>> (64 - 20)); + A[14] = (A[14] << 39) | (A[14] >>> (64 - 39)); + A[19] = (A[19] << 8) | (A[19] >>> (64 - 8)); + A[24] = (A[24] << 14) | (A[24] >>> (64 - 14)); + bnn = ~A[12]; + kt = A[ 6] | A[12]; + c0 = A[ 0] ^ kt; + kt = bnn | A[18]; + c1 = A[ 6] ^ kt; + kt = A[18] & A[24]; + c2 = A[12] ^ kt; + kt = A[24] | A[ 0]; + c3 = A[18] ^ kt; + kt = A[ 0] & A[ 6]; + c4 = A[24] ^ kt; + A[ 0] = c0; + A[ 6] = c1; + A[12] = c2; + A[18] = c3; + A[24] = c4; + bnn = ~A[22]; + kt = A[ 9] | A[10]; + c0 = A[ 3] ^ kt; + kt = A[10] & A[16]; + c1 = A[ 9] ^ kt; + kt = A[16] | bnn; + c2 = A[10] ^ kt; + kt = A[22] | A[ 3]; + c3 = A[16] ^ kt; + kt = A[ 3] & A[ 9]; + c4 = A[22] ^ kt; + A[ 3] = c0; + A[ 9] = c1; + A[10] = c2; + A[16] = c3; + A[22] = c4; + bnn = ~A[19]; + kt = A[ 7] | A[13]; + c0 = A[ 1] ^ kt; + kt = A[13] & A[19]; + c1 = A[ 7] ^ kt; + kt = bnn & A[20]; + c2 = A[13] ^ kt; + kt = A[20] | A[ 1]; + c3 = bnn ^ kt; + kt = A[ 1] & A[ 7]; + c4 = A[20] ^ kt; + A[ 1] = c0; + A[ 7] = c1; + A[13] = c2; + A[19] = c3; + A[20] = c4; + bnn = ~A[17]; + kt = A[ 5] & A[11]; + c0 = A[ 4] ^ kt; + kt = A[11] | A[17]; + c1 = A[ 5] ^ kt; + kt = bnn | A[23]; + c2 = A[11] ^ kt; + kt = A[23] & A[ 4]; + c3 = bnn ^ kt; + kt = A[ 4] | A[ 5]; + c4 = A[23] ^ kt; + A[ 4] = c0; + A[ 5] = c1; + A[11] = c2; + A[17] = c3; + A[23] = c4; + bnn = ~A[ 8]; + kt = bnn & A[14]; + c0 = A[ 2] ^ kt; + kt = A[14] | A[15]; + c1 = bnn ^ kt; + kt = A[15] & A[21]; + c2 = A[14] ^ kt; + kt = A[21] | A[ 2]; + c3 = A[15] ^ kt; + kt = A[ 2] & A[ 8]; + c4 = A[21] ^ kt; + A[ 2] = c0; + A[ 8] = c1; + A[14] = c2; + A[15] = c3; + A[21] = c4; + A[ 0] = A[ 0] ^ RC[j + 0]; + + tt0 = A[ 6] ^ A[ 9]; + tt1 = A[ 7] ^ A[ 5]; + tt0 ^= A[ 8] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[24] ^ A[22]; + tt3 = A[20] ^ A[23]; + tt0 ^= A[21]; + tt2 ^= tt3; + t0 = tt0 ^ tt2; + + tt0 = A[12] ^ A[10]; + tt1 = A[13] ^ A[11]; + tt0 ^= A[14] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 0] ^ A[ 3]; + tt3 = A[ 1] ^ A[ 4]; + tt0 ^= A[ 2]; + tt2 ^= tt3; + t1 = tt0 ^ tt2; + + tt0 = A[18] ^ A[16]; + tt1 = A[19] ^ A[17]; + tt0 ^= A[15] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[ 6] ^ A[ 9]; + tt3 = A[ 7] ^ A[ 5]; + tt0 ^= A[ 8]; + tt2 ^= tt3; + t2 = tt0 ^ tt2; + + tt0 = A[24] ^ A[22]; + tt1 = A[20] ^ A[23]; + tt0 ^= A[21] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[12] ^ A[10]; + tt3 = A[13] ^ A[11]; + tt0 ^= A[14]; + tt2 ^= tt3; + t3 = tt0 ^ tt2; + + tt0 = A[ 0] ^ A[ 3]; + tt1 = A[ 1] ^ A[ 4]; + tt0 ^= A[ 2] ^ tt1; + tt0 = (tt0 << 1) | (tt0 >>> 63); + tt2 = A[18] ^ A[16]; + tt3 = A[19] ^ A[17]; + tt0 ^= A[15]; + tt2 ^= tt3; + t4 = tt0 ^ tt2; + + A[ 0] = A[ 0] ^ t0; + A[ 3] = A[ 3] ^ t0; + A[ 1] = A[ 1] ^ t0; + A[ 4] = A[ 4] ^ t0; + A[ 2] = A[ 2] ^ t0; + A[ 6] = A[ 6] ^ t1; + A[ 9] = A[ 9] ^ t1; + A[ 7] = A[ 7] ^ t1; + A[ 5] = A[ 5] ^ t1; + A[ 8] = A[ 8] ^ t1; + A[12] = A[12] ^ t2; + A[10] = A[10] ^ t2; + A[13] = A[13] ^ t2; + A[11] = A[11] ^ t2; + A[14] = A[14] ^ t2; + A[18] = A[18] ^ t3; + A[16] = A[16] ^ t3; + A[19] = A[19] ^ t3; + A[17] = A[17] ^ t3; + A[15] = A[15] ^ t3; + A[24] = A[24] ^ t4; + A[22] = A[22] ^ t4; + A[20] = A[20] ^ t4; + A[23] = A[23] ^ t4; + A[21] = A[21] ^ t4; + A[ 3] = (A[ 3] << 36) | (A[ 3] >>> (64 - 36)); + A[ 1] = (A[ 1] << 3) | (A[ 1] >>> (64 - 3)); + A[ 4] = (A[ 4] << 41) | (A[ 4] >>> (64 - 41)); + A[ 2] = (A[ 2] << 18) | (A[ 2] >>> (64 - 18)); + A[ 6] = (A[ 6] << 1) | (A[ 6] >>> (64 - 1)); + A[ 9] = (A[ 9] << 44) | (A[ 9] >>> (64 - 44)); + A[ 7] = (A[ 7] << 10) | (A[ 7] >>> (64 - 10)); + A[ 5] = (A[ 5] << 45) | (A[ 5] >>> (64 - 45)); + A[ 8] = (A[ 8] << 2) | (A[ 8] >>> (64 - 2)); + A[12] = (A[12] << 62) | (A[12] >>> (64 - 62)); + A[10] = (A[10] << 6) | (A[10] >>> (64 - 6)); + A[13] = (A[13] << 43) | (A[13] >>> (64 - 43)); + A[11] = (A[11] << 15) | (A[11] >>> (64 - 15)); + A[14] = (A[14] << 61) | (A[14] >>> (64 - 61)); + A[18] = (A[18] << 28) | (A[18] >>> (64 - 28)); + A[16] = (A[16] << 55) | (A[16] >>> (64 - 55)); + A[19] = (A[19] << 25) | (A[19] >>> (64 - 25)); + A[17] = (A[17] << 21) | (A[17] >>> (64 - 21)); + A[15] = (A[15] << 56) | (A[15] >>> (64 - 56)); + A[24] = (A[24] << 27) | (A[24] >>> (64 - 27)); + A[22] = (A[22] << 20) | (A[22] >>> (64 - 20)); + A[20] = (A[20] << 39) | (A[20] >>> (64 - 39)); + A[23] = (A[23] << 8) | (A[23] >>> (64 - 8)); + A[21] = (A[21] << 14) | (A[21] >>> (64 - 14)); + bnn = ~A[13]; + kt = A[ 9] | A[13]; + c0 = A[ 0] ^ kt; + kt = bnn | A[17]; + c1 = A[ 9] ^ kt; + kt = A[17] & A[21]; + c2 = A[13] ^ kt; + kt = A[21] | A[ 0]; + c3 = A[17] ^ kt; + kt = A[ 0] & A[ 9]; + c4 = A[21] ^ kt; + A[ 0] = c0; + A[ 9] = c1; + A[13] = c2; + A[17] = c3; + A[21] = c4; + bnn = ~A[14]; + kt = A[22] | A[ 1]; + c0 = A[18] ^ kt; + kt = A[ 1] & A[ 5]; + c1 = A[22] ^ kt; + kt = A[ 5] | bnn; + c2 = A[ 1] ^ kt; + kt = A[14] | A[18]; + c3 = A[ 5] ^ kt; + kt = A[18] & A[22]; + c4 = A[14] ^ kt; + A[18] = c0; + A[22] = c1; + A[ 1] = c2; + A[ 5] = c3; + A[14] = c4; + bnn = ~A[23]; + kt = A[10] | A[19]; + c0 = A[ 6] ^ kt; + kt = A[19] & A[23]; + c1 = A[10] ^ kt; + kt = bnn & A[ 2]; + c2 = A[19] ^ kt; + kt = A[ 2] | A[ 6]; + c3 = bnn ^ kt; + kt = A[ 6] & A[10]; + c4 = A[ 2] ^ kt; + A[ 6] = c0; + A[10] = c1; + A[19] = c2; + A[23] = c3; + A[ 2] = c4; + bnn = ~A[11]; + kt = A[ 3] & A[ 7]; + c0 = A[24] ^ kt; + kt = A[ 7] | A[11]; + c1 = A[ 3] ^ kt; + kt = bnn | A[15]; + c2 = A[ 7] ^ kt; + kt = A[15] & A[24]; + c3 = bnn ^ kt; + kt = A[24] | A[ 3]; + c4 = A[15] ^ kt; + A[24] = c0; + A[ 3] = c1; + A[ 7] = c2; + A[11] = c3; + A[15] = c4; + bnn = ~A[16]; + kt = bnn & A[20]; + c0 = A[12] ^ kt; + kt = A[20] | A[ 4]; + c1 = bnn ^ kt; + kt = A[ 4] & A[ 8]; + c2 = A[20] ^ kt; + kt = A[ 8] | A[12]; + c3 = A[ 4] ^ kt; + kt = A[12] & A[16]; + c4 = A[ 8] ^ kt; + A[12] = c0; + A[16] = c1; + A[20] = c2; + A[ 4] = c3; + A[ 8] = c4; + A[ 0] = A[ 0] ^ RC[j + 1]; + t = A[ 5]; + A[ 5] = A[18]; + A[18] = A[11]; + A[11] = A[10]; + A[10] = A[ 6]; + A[ 6] = A[22]; + A[22] = A[20]; + A[20] = A[12]; + A[12] = A[19]; + A[19] = A[15]; + A[15] = A[24]; + A[24] = A[ 8]; + A[ 8] = t; + t = A[ 1]; + A[ 1] = A[ 9]; + A[ 9] = A[14]; + A[14] = A[ 2]; + A[ 2] = A[13]; + A[13] = A[23]; + A[23] = A[ 4]; + A[ 4] = A[21]; + A[21] = A[16]; + A[16] = A[ 3]; + A[ 3] = A[17]; + A[17] = A[ 7]; + A[ 7] = t; + } + } + + protected void doPadding(byte[] out, int off) + { + int ptr = flush(); + byte[] buf = getBlockBuffer(); + if ((ptr + 1) == buf.length) { + buf[ptr] = (byte)0x81; + } else { + buf[ptr] = (byte)0x01; + for (int i = ptr + 1; i < (buf.length - 1); i ++) + buf[i] = 0; + buf[buf.length - 1] = (byte)0x80; + } + processBlock(buf); + A[ 1] = ~A[ 1]; + A[ 2] = ~A[ 2]; + A[ 8] = ~A[ 8]; + A[12] = ~A[12]; + A[17] = ~A[17]; + A[20] = ~A[20]; + int dlen = engineGetDigestLength(); + for (int i = 0; i < dlen; i += 8) + encodeLELong(A[i >>> 3], tmpOut, i); + System.arraycopy(tmpOut, 0, out, off, dlen); + } + + protected void doInit() + { + A = new long[25]; + tmpOut = new byte[(engineGetDigestLength() + 7) & ~7]; + doReset(); + } + + public int getBlockLength() + { + return 200 - 2 * engineGetDigestLength(); + } + + private final void doReset() + { + for (int i = 0; i < 25; i ++) + A[i] = 0; + A[ 1] = 0xFFFFFFFFFFFFFFFFL; + A[ 2] = 0xFFFFFFFFFFFFFFFFL; + A[ 8] = 0xFFFFFFFFFFFFFFFFL; + A[12] = 0xFFFFFFFFFFFFFFFFL; + A[17] = 0xFFFFFFFFFFFFFFFFL; + A[20] = 0xFFFFFFFFFFFFFFFFL; + } + + + protected Digest copyState(KeccakCore dst) + { + System.arraycopy(A, 0, dst.A, 0, 25); + return super.copyState(dst); + } + + public String toString() + { + return "Keccak-" + (engineGetDigestLength() << 3); + } +} diff --git a/app/src/main/java/com/tangem/wallet/LastSignStorage.java b/app/src/main/java/com/tangem/domain/wallet/LastSignStorage.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/LastSignStorage.java rename to app/src/main/java/com/tangem/domain/wallet/LastSignStorage.java index 66dc1add79..3f134149df 100644 --- a/app/src/main/java/com/tangem/wallet/LastSignStorage.java +++ b/app/src/main/java/com/tangem/domain/wallet/LastSignStorage.java @@ -1,145 +1,145 @@ -package com.tangem.wallet; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.ArrayMap; -import android.util.ArraySet; - -import java.util.Date; -import java.util.Map; -import java.util.Set; - -/** - * Created by dvol on 30.10.2017. - */ - -public class LastSignStorage { - - private static SharedPreferences sharedPreferences=null; - - private static Set cards = new ArraySet<>(); - private static Map dates = new ArrayMap<>(); - private static Map txCol = new ArrayMap<>(); - private static Map txCompleteCol = new ArrayMap<>(); - - public static void Init(Context context) { - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - cards=sharedPreferences.getStringSet("LastSign_Cards", cards); - for (int i = 0; i < cards.size(); i++) { - String wallet = cards.toArray()[i].toString(); - Date dt = new Date(); - dt.setTime(sharedPreferences.getLong("LastSign_" + wallet, 0)); - dates.put(wallet, dt); - } - } - - public static boolean needInit() { - return sharedPreferences==null; - } - - static class CompleteTx - { - public String TX; - public boolean isComplete; - } - public static Map GetTxList() - { - Set wallets=sharedPreferences.getStringSet("LastSign_Cards", cards); - Map txList = new ArrayMap<>(); - - for (int i = 0; i < wallets.size(); i++) { - String wallet = wallets.toArray()[i].toString(); - String tx = sharedPreferences.getString("LastSignTX_" + wallet, ""); - boolean complete = sharedPreferences.getBoolean("LastSignTXComplete_" + wallet, false); - CompleteTx txComplete = new CompleteTx(); - txComplete.isComplete = complete; - txComplete.TX = tx; - txList.put(wallet, txComplete); - } - - return txList; - } - public static Date getLastSignDate(String wallet) { - if (dates.containsKey(wallet)) return dates.get(wallet); - return null; - } - - public static void setLastSignDate(String wallet, Date date) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - if (!cards.contains(wallet)) { - cards.add(wallet); - editor.putStringSet("LastSign_Cards", cards); - } - dates.put(wallet, date); - editor.putLong("LastSign_" + wallet, date.getTime()); - editor.apply(); - } - - public static void setLastTX(String wallet, String tx) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - if (!cards.contains(wallet)) { - cards.add(wallet); - editor.putStringSet("LastSign_Cards", cards); - } - - editor.putString("LastSignTX_" + wallet, tx); - editor.putBoolean("LastSignTXComplete_" + wallet, false); - editor.apply(); - } - - public static void setLastMessage(String wallet, String message) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - if (!cards.contains(wallet)) { - cards.add(wallet); - editor.putStringSet("LastSign_Cards", cards); - } - - editor.putString("LastSignMessage_" + wallet, message); - editor.apply(); - } - - public static String getLastMessage(String wallet) - { - try { - String msg = sharedPreferences.getString("LastSignMessage_" + wallet, ""); - return msg; - } - catch(Exception e) - { - return ""; - } - } - - public static void setTxWasSend(String wallet) - { - - Map txList = GetTxList(); - if(txList.containsKey(wallet)) - { - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putBoolean("LastSignTXComplete_" + wallet, true); - editor.apply(); - } - } - public static boolean getNeedTxSend(String wallet) - { - Map txList = GetTxList(); - if(txList.containsKey(wallet)) - { - boolean complete = txList.get(wallet).isComplete; - return !complete; - } - return false; - } - - public static String getTxForSend(String wallet) - { - Map txList = GetTxList(); - if(txList.containsKey(wallet)) - { - return txList.get(wallet).TX; - } - return ""; - } -} +package com.tangem.domain.wallet; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.ArrayMap; +import android.util.ArraySet; + +import java.util.Date; +import java.util.Map; +import java.util.Set; + +/** + * Created by dvol on 30.10.2017. + */ + +public class LastSignStorage { + + private static SharedPreferences sharedPreferences=null; + + private static Set cards = new ArraySet<>(); + private static Map dates = new ArrayMap<>(); + private static Map txCol = new ArrayMap<>(); + private static Map txCompleteCol = new ArrayMap<>(); + + public static void Init(Context context) { + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + cards=sharedPreferences.getStringSet("LastSign_Cards", cards); + for (int i = 0; i < cards.size(); i++) { + String wallet = cards.toArray()[i].toString(); + Date dt = new Date(); + dt.setTime(sharedPreferences.getLong("LastSign_" + wallet, 0)); + dates.put(wallet, dt); + } + } + + public static boolean needInit() { + return sharedPreferences==null; + } + + static class CompleteTx + { + public String TX; + public boolean isComplete; + } + public static Map GetTxList() + { + Set wallets=sharedPreferences.getStringSet("LastSign_Cards", cards); + Map txList = new ArrayMap<>(); + + for (int i = 0; i < wallets.size(); i++) { + String wallet = wallets.toArray()[i].toString(); + String tx = sharedPreferences.getString("LastSignTX_" + wallet, ""); + boolean complete = sharedPreferences.getBoolean("LastSignTXComplete_" + wallet, false); + CompleteTx txComplete = new CompleteTx(); + txComplete.isComplete = complete; + txComplete.TX = tx; + txList.put(wallet, txComplete); + } + + return txList; + } + public static Date getLastSignDate(String wallet) { + if (dates.containsKey(wallet)) return dates.get(wallet); + return null; + } + + public static void setLastSignDate(String wallet, Date date) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + if (!cards.contains(wallet)) { + cards.add(wallet); + editor.putStringSet("LastSign_Cards", cards); + } + dates.put(wallet, date); + editor.putLong("LastSign_" + wallet, date.getTime()); + editor.apply(); + } + + public static void setLastTX(String wallet, String tx) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + if (!cards.contains(wallet)) { + cards.add(wallet); + editor.putStringSet("LastSign_Cards", cards); + } + + editor.putString("LastSignTX_" + wallet, tx); + editor.putBoolean("LastSignTXComplete_" + wallet, false); + editor.apply(); + } + + public static void setLastMessage(String wallet, String message) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + if (!cards.contains(wallet)) { + cards.add(wallet); + editor.putStringSet("LastSign_Cards", cards); + } + + editor.putString("LastSignMessage_" + wallet, message); + editor.apply(); + } + + public static String getLastMessage(String wallet) + { + try { + String msg = sharedPreferences.getString("LastSignMessage_" + wallet, ""); + return msg; + } + catch(Exception e) + { + return ""; + } + } + + public static void setTxWasSend(String wallet) + { + + Map txList = GetTxList(); + if(txList.containsKey(wallet)) + { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putBoolean("LastSignTXComplete_" + wallet, true); + editor.apply(); + } + } + public static boolean getNeedTxSend(String wallet) + { + Map txList = GetTxList(); + if(txList.containsKey(wallet)) + { + boolean complete = txList.get(wallet).isComplete; + return !complete; + } + return false; + } + + public static String getTxForSend(String wallet) + { + Map txList = GetTxList(); + if(txList.containsKey(wallet)) + { + return txList.get(wallet).TX; + } + return ""; + } +} diff --git a/app/src/main/java/com/tangem/wallet/Logger.java b/app/src/main/java/com/tangem/domain/wallet/Logger.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/Logger.java rename to app/src/main/java/com/tangem/domain/wallet/Logger.java index 559356ebd8..1925c17d52 100644 --- a/app/src/main/java/com/tangem/wallet/Logger.java +++ b/app/src/main/java/com/tangem/domain/wallet/Logger.java @@ -1,285 +1,285 @@ -package com.tangem.wallet; - -import android.content.Context; -import android.util.Log; - -import com.tangem.domain.cardReader.Util; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Date; - -public class Logger { - - public static File collectLogs(Context context) { - File f = new File(context.getCacheDir().getAbsolutePath() + "/Wallet_" + Util.formatDateTimeToFileName(new Date()) + ".log"); - try { - if (f.createNewFile()) { - f.setReadable(true); - FileWriter fileWriter = new FileWriter(f, true); - Process process = Runtime.getRuntime().exec("logcat -d -b main -v time"); - try { - InputStream is = process.getInputStream(); - InputStreamReader isr = new InputStreamReader(is); - BufferedReader bufferedReader = new BufferedReader(isr); - BufferedWriter buf = new BufferedWriter(fileWriter); - buf.append("Tangem Wallet logs"); - buf.newLine(); - - int i = 0; - String line; - while ((line = bufferedReader.readLine()) != null) { - buf.append(line); - buf.newLine(); - i++; - } - Log.e("Logger", String.format("%d log lines collected", i)); - buf.newLine(); - buf.flush(); - buf.close(); - - } finally { - process.destroy(); - } - - return f; - } - } catch (Exception e) { - e.printStackTrace(); - } - - return null; - } - - -} - -//public class Logger { -// -// public static File[] getLastLogFiles() { -// File path = new File(Environment.getExternalStorageDirectory(), "Tangem/logs"); -// if (!path.exists()) { -// return null; -// } -// File[] files = path.listFiles(); -// Arrays.sort(files, new Comparator() { -// @Override -// public int compare(File o1, File o2) { -// if (o1.lastModified() < o2.lastModified()) { -// return -1; -// } else if (o1.lastModified() > o2.lastModified()) { -// return 1; -// } -// return 0; -// } -// }); -// if (files.length < 5) return files; -// return Arrays.copyOfRange(files, files.length - 5, files.length); -// } -// -// private static File logFile = null; -// -// private static void initLogFile(Context context) { -// try { -// File path = new File(Environment.getExternalStorageDirectory(), "Tangem/logs"); -// if (!path.exists()) { -// path.mkdirs(); -// MediaScannerConnection.scanFile(context, new String[]{path.getParentFile().toString()}, null, null); -// } -// logFile = new File(path, String.format("wallet_%s.log", Util.formatDateTimeToFileName(new Date()))); -// logFile.createNewFile(); -// logFile.setReadable(true); -// -// // initiate media scan and put the new things into the path array to -// // make the scanner aware of the location and the files you want to see -// MediaScannerConnection.scanFile(context, new String[]{logFile.getAbsolutePath()}, null, null); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// -// } -// -// public static boolean isCurrent(File f) { -// if (f == null || logFile == null) return false; -// return f.getAbsolutePath().equals(logFile.getAbsolutePath()); -// } -// -// -// private static class LogCatThread extends Thread { -// private boolean Terminated; -// -// private static final Object oSync = new Object(); -// -// public void Terminate() { -// Terminated = true; -// synchronized (oSync) { -// oSync.notifyAll(); -// } -// try { -// join(1000); -// } catch (InterruptedException e) { -// e.printStackTrace(); -// interrupt(); -// } -// } -// -// public void collectLogs(Writer out) { -// try { -// Process process = Runtime.getRuntime().exec("logcat -d -b main -v time"); -// try { -// InputStream is = process.getInputStream(); -// InputStreamReader isr = new InputStreamReader(is); -// BufferedReader bufferedReader = new BufferedReader(isr); -// try { -// -// try { -// //BufferedWriter for performance, true to set append to file flag -// BufferedWriter buf = new BufferedWriter(out); -// -// while (!Terminated && isr.ready()) { -// String line = bufferedReader.readLine(); -// buf.append(line); -// buf.newLine(); -// } -// //Log.i("Logger",String.format("%d lines added",i)); -// buf.newLine(); -// buf.close(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// -// -// } catch (Exception e) { -// e.printStackTrace(); -// } -// -// } finally { -// process.destroy(); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// } -// -// } -// -// @Override -// public void run() { -// Process process = null; -// try { -// if (logFile == null) return; -// process = Runtime.getRuntime().exec("logcat -b main -v time"); -// try { -// InputStream is = process.getInputStream(); -// InputStreamReader isr = new InputStreamReader(is); -// BufferedReader bufferedReader = new BufferedReader(isr); -// while (!Terminated) { -// try { -// synchronized (oSync) { -// oSync.wait(1000); -// } -// if (!logFile.exists()) { -// try { -// logFile.createNewFile(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } -// try { -// //BufferedWriter for performance, true to set append to file flag -// BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); -// -// while (isr.ready()) { -// String line = bufferedReader.readLine(); -// buf.append(line); -// buf.newLine(); -// } -// //Log.i("Logger",String.format("%d lines added",i)); -// buf.newLine(); -// buf.close(); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// -// -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// } finally { -// process.destroy(); -// } -// } catch (IOException e) { -// e.printStackTrace(); -// } -// } -// } -// -// static LogCatThread t = new LogCatThread(); -// -// public static void StartSaveToFile(Activity activity) { -// try { -// if (logFile != null) return; -// -// verifyStoragePermissions(activity); -// initLogFile(activity.getApplicationContext()); -// t.start(); -// } catch (Exception e) { -// e.printStackTrace(); -// } -// } -// -// public static void StopSaveToFile(Context context) { -// final Object oSync = new Object(); -// if (t.isAlive()) { -// t.Terminate(); -// } -// if (logFile != null) { -// MediaScannerConnection.scanFile(context, new String[]{logFile.getAbsolutePath().toString()}, null, new MediaScannerConnection.OnScanCompletedListener() { -// @Override -// public void onScanCompleted(String path, Uri uri) { -//// synchronized (oSync) { -//// oSync.notifyAll(); -//// } -// } -// }); -//// try { -//// synchronized (oSync) { -//// oSync.wait(10000); -// logFile = null; -//// } -//// } catch (InterruptedException e) { -//// e.printStackTrace(); -//// } -// } -// -// } -// -// // Storage Permissions -// private static final int REQUEST_EXTERNAL_STORAGE = 1; -// private static String[] PERMISSIONS_STORAGE = { -// Manifest.permission.READ_EXTERNAL_STORAGE, -// Manifest.permission.WRITE_EXTERNAL_STORAGE -// }; -// -// //Checks if the app has permission to write to device storage -// //If the app does not has permission then the user will be prompted to grant permissions -// public static void verifyStoragePermissions(Activity activity) { -// // Check if we have write permission -// int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); -// -// if (permission != PackageManager.PERMISSION_GRANTED) { -// // We don't have permission so prompt the user -// ActivityCompat.requestPermissions( -// activity, -// PERMISSIONS_STORAGE, -// REQUEST_EXTERNAL_STORAGE -// ); -// } -// } -// -//} - +package com.tangem.domain.wallet; + +import android.content.Context; +import android.util.Log; + +import com.tangem.util.Util; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Date; + +public class Logger { + + public static File collectLogs(Context context) { + File f = new File(context.getCacheDir().getAbsolutePath() + "/Wallet_" + Util.formatDateTimeToFileName(new Date()) + ".log"); + try { + if (f.createNewFile()) { + f.setReadable(true); + FileWriter fileWriter = new FileWriter(f, true); + Process process = Runtime.getRuntime().exec("logcat -d -b main -v time"); + try { + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader bufferedReader = new BufferedReader(isr); + BufferedWriter buf = new BufferedWriter(fileWriter); + buf.append("Tangem Wallet logs"); + buf.newLine(); + + int i = 0; + String line; + while ((line = bufferedReader.readLine()) != null) { + buf.append(line); + buf.newLine(); + i++; + } + Log.e("Logger", String.format("%d log lines collected", i)); + buf.newLine(); + buf.flush(); + buf.close(); + + } finally { + process.destroy(); + } + + return f; + } + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + +} + +//public class Logger { +// +// public static File[] getLastLogFiles() { +// File path = new File(Environment.getExternalStorageDirectory(), "Tangem/logs"); +// if (!path.exists()) { +// return null; +// } +// File[] files = path.listFiles(); +// Arrays.sort(files, new Comparator() { +// @Override +// public int compare(File o1, File o2) { +// if (o1.lastModified() < o2.lastModified()) { +// return -1; +// } else if (o1.lastModified() > o2.lastModified()) { +// return 1; +// } +// return 0; +// } +// }); +// if (files.length < 5) return files; +// return Arrays.copyOfRange(files, files.length - 5, files.length); +// } +// +// private static File logFile = null; +// +// private static void initLogFile(Context context) { +// try { +// File path = new File(Environment.getExternalStorageDirectory(), "Tangem/logs"); +// if (!path.exists()) { +// path.mkdirs(); +// MediaScannerConnection.scanFile(context, new String[]{path.getParentFile().toString()}, null, null); +// } +// logFile = new File(path, String.format("wallet_%s.log", Util.formatDateTimeToFileName(new Date()))); +// logFile.createNewFile(); +// logFile.setReadable(true); +// +// // initiate media scan and put the new things into the path array to +// // make the scanner aware of the location and the files you want to see +// MediaScannerConnection.scanFile(context, new String[]{logFile.getAbsolutePath()}, null, null); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// } +// +// public static boolean isCurrent(File f) { +// if (f == null || logFile == null) return false; +// return f.getAbsolutePath().equals(logFile.getAbsolutePath()); +// } +// +// +// private static class LogCatThread extends Thread { +// private boolean Terminated; +// +// private static final Object oSync = new Object(); +// +// public void Terminate() { +// Terminated = true; +// synchronized (oSync) { +// oSync.notifyAll(); +// } +// try { +// join(1000); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// interrupt(); +// } +// } +// +// public void collectLogs(Writer out) { +// try { +// Process process = Runtime.getRuntime().exec("logcat -d -b main -v time"); +// try { +// InputStream is = process.getInputStream(); +// InputStreamReader isr = new InputStreamReader(is); +// BufferedReader bufferedReader = new BufferedReader(isr); +// try { +// +// try { +// //BufferedWriter for performance, true to set append to file flag +// BufferedWriter buf = new BufferedWriter(out); +// +// while (!Terminated && isr.ready()) { +// String line = bufferedReader.readLine(); +// buf.append(line); +// buf.newLine(); +// } +// //Log.i("Logger",String.format("%d lines added",i)); +// buf.newLine(); +// buf.close(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// +// } finally { +// process.destroy(); +// } +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// } +// +// @Override +// public void run() { +// Process process = null; +// try { +// if (logFile == null) return; +// process = Runtime.getRuntime().exec("logcat -b main -v time"); +// try { +// InputStream is = process.getInputStream(); +// InputStreamReader isr = new InputStreamReader(is); +// BufferedReader bufferedReader = new BufferedReader(isr); +// while (!Terminated) { +// try { +// synchronized (oSync) { +// oSync.wait(1000); +// } +// if (!logFile.exists()) { +// try { +// logFile.createNewFile(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// try { +// //BufferedWriter for performance, true to set append to file flag +// BufferedWriter buf = new BufferedWriter(new FileWriter(logFile, true)); +// +// while (isr.ready()) { +// String line = bufferedReader.readLine(); +// buf.append(line); +// buf.newLine(); +// } +// //Log.i("Logger",String.format("%d lines added",i)); +// buf.newLine(); +// buf.close(); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// +// +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// } finally { +// process.destroy(); +// } +// } catch (IOException e) { +// e.printStackTrace(); +// } +// } +// } +// +// static LogCatThread t = new LogCatThread(); +// +// public static void StartSaveToFile(Activity activity) { +// try { +// if (logFile != null) return; +// +// verifyStoragePermissions(activity); +// initLogFile(activity.getApplicationContext()); +// t.start(); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } +// +// public static void StopSaveToFile(Context context) { +// final Object oSync = new Object(); +// if (t.isAlive()) { +// t.Terminate(); +// } +// if (logFile != null) { +// MediaScannerConnection.scanFile(context, new String[]{logFile.getAbsolutePath().toString()}, null, new MediaScannerConnection.OnScanCompletedListener() { +// @Override +// public void onScanCompleted(String path, Uri uri) { +//// synchronized (oSync) { +//// oSync.notifyAll(); +//// } +// } +// }); +//// try { +//// synchronized (oSync) { +//// oSync.wait(10000); +// logFile = null; +//// } +//// } catch (InterruptedException e) { +//// e.printStackTrace(); +//// } +// } +// +// } +// +// // Storage Permissions +// private static final int REQUEST_EXTERNAL_STORAGE = 1; +// private static String[] PERMISSIONS_STORAGE = { +// Manifest.permission.READ_EXTERNAL_STORAGE, +// Manifest.permission.WRITE_EXTERNAL_STORAGE +// }; +// +// //Checks if the app has permission to write to device storage +// //If the app does not has permission then the user will be prompted to grant permissions +// public static void verifyStoragePermissions(Activity activity) { +// // Check if we have write permission +// int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); +// +// if (permission != PackageManager.PERMISSION_GRANTED) { +// // We don't have permission so prompt the user +// ActivityCompat.requestPermissions( +// activity, +// PERMISSIONS_STORAGE, +// REQUEST_EXTERNAL_STORAGE +// ); +// } +// } +// +//} + diff --git a/app/src/main/java/com/tangem/wallet/Manufacturer.java b/app/src/main/java/com/tangem/domain/wallet/Manufacturer.java similarity index 89% rename from app/src/main/java/com/tangem/wallet/Manufacturer.java rename to app/src/main/java/com/tangem/domain/wallet/Manufacturer.java index c0db7d232c..df8a8a56ac 100644 --- a/app/src/main/java/com/tangem/wallet/Manufacturer.java +++ b/app/src/main/java/com/tangem/domain/wallet/Manufacturer.java @@ -1,126 +1,111 @@ -package com.tangem.wallet; - -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.ECPublicKeySpec; -import org.spongycastle.math.ec.ECPoint; - -import java.math.BigInteger; -import java.security.KeyFactory; -import java.security.PublicKey; -import java.util.Arrays; - -/** - * Created by dvol on 09.08.2017. - */ - -public enum Manufacturer { -// Unknown("", "Unknown", new byte[]{}), -// SMARTCASH_AG("SMART CASH AG","SMART CASH AG", -// new byte[]{0x04, -// (byte) 0x4F, (byte) 0x53, (byte) 0x90, (byte) 0x2D, (byte) 0x50, (byte) 0xE2, (byte) 0xBB, (byte) 0x16, -// (byte) 0xD3, (byte) 0xDD, (byte) 0xC7, (byte) 0xA2, (byte) 0x03, (byte) 0x97, (byte) 0x28, (byte) 0x5E, -// (byte) 0x94, (byte) 0x21, (byte) 0x53, (byte) 0x69, (byte) 0x59, (byte) 0x8C, (byte) 0xE4, (byte) 0xDD, -// (byte) 0x62, (byte) 0x42, (byte) 0xDD, (byte) 0xB4, (byte) 0x5B, (byte) 0x96, (byte) 0xA1, (byte) 0x03, -// (byte) 0x1A, (byte) 0xF5, (byte) 0xC9, (byte) 0x73, (byte) 0x94, (byte) 0xC6, (byte) 0xF9, (byte) 0xC8, -// (byte) 0xD7, (byte) 0x6F, (byte) 0x38, (byte) 0xF9, (byte) 0x65, (byte) 0xCB, (byte) 0xA8, (byte) 0xAE, -// (byte) 0x85, (byte) 0xAF, (byte) 0xF7, (byte) 0x68, (byte) 0x55, (byte) 0xDC, (byte) 0xAA, (byte) 0x08, -// (byte) 0xF3, (byte) 0xCD, (byte) 0x15, (byte) 0x43, (byte) 0x04, (byte) 0x19, (byte) 0xF4, (byte) 0x49}), -// DEVELOPERS_SMARTCASH_AG("DEVELOP CASH AG","SMART CASH AG (DEVELOPERS)", -// new byte[]{0x04, -// (byte) 0xBA, (byte) 0xB8, (byte) 0x6D, (byte) 0x56, (byte) 0x29, (byte) 0x8C, (byte) 0x99, (byte) 0x6F, -// (byte) 0x56, (byte) 0x4A, (byte) 0x84, (byte) 0xFC, (byte) 0x88, (byte) 0xE2, (byte) 0x8A, (byte) 0xED, -// (byte) 0x38, (byte) 0x18, (byte) 0x4B, (byte) 0x12, (byte) 0xF0, (byte) 0x7E, (byte) 0x51, (byte) 0x91, -// (byte) 0x13, (byte) 0xBE, (byte) 0xF4, (byte) 0x8C, (byte) 0x76, (byte) 0xF3, (byte) 0xDF, (byte) 0x3A, -// -// (byte) 0xDC, (byte) 0x30, (byte) 0x35, (byte) 0x99, (byte) 0xB0, (byte) 0x8A, (byte) 0xC0, (byte) 0x5B, -// (byte) 0x55, (byte) 0xEC, (byte) 0x3D, (byte) 0xF9, (byte) 0x8D, (byte) 0x93, (byte) 0x38, (byte) 0x57, -// (byte) 0x3A, (byte) 0x62, (byte) 0x42, (byte) 0xF7, (byte) 0x6F, (byte) 0x5D, (byte) 0x28, (byte) 0xF4, -// (byte) 0xF0, (byte) 0xF3, (byte) 0x64, (byte) 0xE8, (byte) 0x7E, (byte) 0x8F, (byte) 0xCA, (byte) 0x2F}); - - - Unknown("", "Unknown"), - SMARTCASH_AG("SMART CASH AG", "SMART CASH AG"), - DEVELOPERS_SMARTCASH_AG("DEVELOP CASH AG", "SMART CASH AG (DEVELOPERS)"), - SMARTCASH("SMART CASH", "SMART CASH"); - - private String ID; - private String officialName; -// private byte[] publicKey; - - // Manufacturer(String id, String officialName, byte[] publicKey) { - Manufacturer(String id, String officialName) { - this.ID = id; - this.officialName = officialName; -// this.publicKey = publicKey; - } - - public String getOfficialName() { - return officialName; - } - -// public boolean VerifySignature(byte[] Challenge, byte[] Salt, byte[] Signature) { -// -// if (publicKey == null || Challenge == null || Salt == null || Signature == null) { -// Log.e(getOfficialName(), "Not all data read, can't check signature!"); -// return false; -// } -// try { -// java.security.Signature signature = java.security.Signature.getInstance("SHA256withECDSA"); -// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1"); -// KeyFactory factory = KeyFactory.getInstance("EC", "SC"); -// -// ECPoint p1 = spec.getCurve().decodePoint(publicKey); -// -// ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec); -// -// PublicKey publicKey = factory.generatePublic(keySpec); -// signature.initVerify(publicKey); -// signature.update(Challenge); -// signature.update(Salt); -// -// 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(); -// -// if (signature.verify(sigDer)) { -// Log.i(getOfficialName(), "Signature verification OK"); -// return true; -// } else { -// Log.e(getOfficialName(), "Signature verification failed"); -// } -// } -// catch (Exception e) -// { -// e.printStackTrace(); -// } -// return false; -// } -// -// public static Manufacturer FindManufacturer(String ID, byte[] Challenge, byte[] Salt, byte[] Signature) { -// Manufacturer[] manufacturers = Manufacturer.values(); -// for (int i = 1; i < manufacturers.length; i++) { -// if ( manufacturers[i].ID.equals(ID) && manufacturers[i].VerifySignature(Challenge, Salt, Signature)) { -// return manufacturers[i]; -// } -// } -// return Manufacturer.Unknown; -// } - - public static Manufacturer FindManufacturer(String ID) { - Manufacturer[] manufacturers = Manufacturer.values(); - for (int i = 1; i < manufacturers.length; i++) { - if (manufacturers[i].ID.equals(ID)) { - return manufacturers[i]; - } - } - return Manufacturer.Unknown; - } -} +package com.tangem.domain.wallet; + +/** + * Created by dvol on 09.08.2017. + */ + +public enum Manufacturer { +// Unknown("", "Unknown", new byte[]{}), +// SMARTCASH_AG("SMART CASH AG","SMART CASH AG", +// new byte[]{0x04, +// (byte) 0x4F, (byte) 0x53, (byte) 0x90, (byte) 0x2D, (byte) 0x50, (byte) 0xE2, (byte) 0xBB, (byte) 0x16, +// (byte) 0xD3, (byte) 0xDD, (byte) 0xC7, (byte) 0xA2, (byte) 0x03, (byte) 0x97, (byte) 0x28, (byte) 0x5E, +// (byte) 0x94, (byte) 0x21, (byte) 0x53, (byte) 0x69, (byte) 0x59, (byte) 0x8C, (byte) 0xE4, (byte) 0xDD, +// (byte) 0x62, (byte) 0x42, (byte) 0xDD, (byte) 0xB4, (byte) 0x5B, (byte) 0x96, (byte) 0xA1, (byte) 0x03, +// (byte) 0x1A, (byte) 0xF5, (byte) 0xC9, (byte) 0x73, (byte) 0x94, (byte) 0xC6, (byte) 0xF9, (byte) 0xC8, +// (byte) 0xD7, (byte) 0x6F, (byte) 0x38, (byte) 0xF9, (byte) 0x65, (byte) 0xCB, (byte) 0xA8, (byte) 0xAE, +// (byte) 0x85, (byte) 0xAF, (byte) 0xF7, (byte) 0x68, (byte) 0x55, (byte) 0xDC, (byte) 0xAA, (byte) 0x08, +// (byte) 0xF3, (byte) 0xCD, (byte) 0x15, (byte) 0x43, (byte) 0x04, (byte) 0x19, (byte) 0xF4, (byte) 0x49}), +// DEVELOPERS_SMARTCASH_AG("DEVELOP CASH AG","SMART CASH AG (DEVELOPERS)", +// new byte[]{0x04, +// (byte) 0xBA, (byte) 0xB8, (byte) 0x6D, (byte) 0x56, (byte) 0x29, (byte) 0x8C, (byte) 0x99, (byte) 0x6F, +// (byte) 0x56, (byte) 0x4A, (byte) 0x84, (byte) 0xFC, (byte) 0x88, (byte) 0xE2, (byte) 0x8A, (byte) 0xED, +// (byte) 0x38, (byte) 0x18, (byte) 0x4B, (byte) 0x12, (byte) 0xF0, (byte) 0x7E, (byte) 0x51, (byte) 0x91, +// (byte) 0x13, (byte) 0xBE, (byte) 0xF4, (byte) 0x8C, (byte) 0x76, (byte) 0xF3, (byte) 0xDF, (byte) 0x3A, +// +// (byte) 0xDC, (byte) 0x30, (byte) 0x35, (byte) 0x99, (byte) 0xB0, (byte) 0x8A, (byte) 0xC0, (byte) 0x5B, +// (byte) 0x55, (byte) 0xEC, (byte) 0x3D, (byte) 0xF9, (byte) 0x8D, (byte) 0x93, (byte) 0x38, (byte) 0x57, +// (byte) 0x3A, (byte) 0x62, (byte) 0x42, (byte) 0xF7, (byte) 0x6F, (byte) 0x5D, (byte) 0x28, (byte) 0xF4, +// (byte) 0xF0, (byte) 0xF3, (byte) 0x64, (byte) 0xE8, (byte) 0x7E, (byte) 0x8F, (byte) 0xCA, (byte) 0x2F}); + + + Unknown("", "Unknown"), + SMARTCASH_AG("SMART CASH AG", "SMART CASH AG"), + DEVELOPERS_SMARTCASH_AG("DEVELOP CASH AG", "SMART CASH AG (DEVELOPERS)"), + SMARTCASH("SMART CASH", "SMART CASH"); + + private String ID; + private String officialName; +// private byte[] publicKey; + + // Manufacturer(String id, String officialName, byte[] publicKey) { + Manufacturer(String id, String officialName) { + this.ID = id; + this.officialName = officialName; +// this.publicKey = publicKey; + } + + public String getOfficialName() { + return officialName; + } + +// public boolean VerifySignature(byte[] Challenge, byte[] Salt, byte[] Signature) { +// +// if (publicKey == null || Challenge == null || Salt == null || Signature == null) { +// Log.e(getOfficialName(), "Not all data read, can't check signature!"); +// return false; +// } +// try { +// java.security.Signature signature = java.security.Signature.getInstance("SHA256withECDSA"); +// ECNamedCurveParameterSpec spec = ECNamedCurveTable.getParameterSpec("secp256k1"); +// KeyFactory factory = KeyFactory.getInstance("EC", "SC"); +// +// ECPoint p1 = spec.getCurve().decodePoint(publicKey); +// +// ECPublicKeySpec keySpec = new ECPublicKeySpec(p1, spec); +// +// PublicKey publicKey = factory.generatePublic(keySpec); +// signature.initVerify(publicKey); +// signature.update(Challenge); +// signature.update(Salt); +// +// 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(); +// +// if (signature.verify(sigDer)) { +// Log.i(getOfficialName(), "Signature verification OK"); +// return true; +// } else { +// Log.e(getOfficialName(), "Signature verification failed"); +// } +// } +// catch (Exception e) +// { +// e.printStackTrace(); +// } +// return false; +// } +// +// public static Manufacturer FindManufacturer(String ID, byte[] Challenge, byte[] Salt, byte[] Signature) { +// Manufacturer[] manufacturers = Manufacturer.values(); +// for (int i = 1; i < manufacturers.length; i++) { +// if ( manufacturers[i].ID.equals(ID) && manufacturers[i].VerifySignature(Challenge, Salt, Signature)) { +// return manufacturers[i]; +// } +// } +// return Manufacturer.Unknown; +// } + + public static Manufacturer FindManufacturer(String ID) { + Manufacturer[] manufacturers = Manufacturer.values(); + for (int i = 1; i < manufacturers.length; i++) { + if (manufacturers[i].ID.equals(ID)) { + return manufacturers[i]; + } + } + return Manufacturer.Unknown; + } +} diff --git a/app/src/main/java/com/tangem/wallet/PINStorage.java b/app/src/main/java/com/tangem/domain/wallet/PINStorage.java similarity index 96% rename from app/src/main/java/com/tangem/wallet/PINStorage.java rename to app/src/main/java/com/tangem/domain/wallet/PINStorage.java index 04b4878d7c..568addd2cc 100644 --- a/app/src/main/java/com/tangem/wallet/PINStorage.java +++ b/app/src/main/java/com/tangem/domain/wallet/PINStorage.java @@ -1,205 +1,205 @@ -package com.tangem.wallet; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; -import android.util.Base64; - -import com.tangem.domain.cardReader.CardProtocol; - -import java.util.ArrayList; -import java.util.List; - -import javax.crypto.Cipher; - -/** - * Created by dvol on 12.09.2017. - * Global PIN Storage - */ - -public class PINStorage { - private static String mSavedPIN, mUserPIN, mLastUsedPIN, mEncryptedPIN, mPIN2; - private static SharedPreferences sharedPreferences=null; - - public static void Init(Context context) { - sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); - mSavedPIN = sharedPreferences.getString("SavedPIN", null); - mUserPIN = null; - mLastUsedPIN = null; - mEncryptedPIN = null; - mPIN2 = null; - } - - - public static List getPINs() { - ArrayList result = new ArrayList<>(); - if (mLastUsedPIN != null) result.add(mLastUsedPIN); - if (mEncryptedPIN != null && !result.contains(mEncryptedPIN)) result.add(mEncryptedPIN); - if (mUserPIN != null && !result.contains(mUserPIN)) result.add(mUserPIN); - if (mSavedPIN != null && !result.contains(mSavedPIN)) result.add(mSavedPIN); - if (!result.contains(CardProtocol.DefaultPIN)) result.add(CardProtocol.DefaultPIN); - return result; - } - - public static void setLastUsedPIN(String PIN) { - mLastUsedPIN = PIN; - } - - public static void setUserPIN(String PIN) { - mUserPIN = PIN; - } - - public static void setPIN2(String PIN) { - mPIN2 = PIN; - } - - public static void savePIN(String PIN) { - mSavedPIN = PIN; - if (mSavedPIN != null && !mSavedPIN.isEmpty()) { - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putString("SavedPIN", mSavedPIN); - editor.apply(); - } else { - deletePIN(); - } - } - - public static void deletePIN() { - SharedPreferences.Editor editor = sharedPreferences.edit(); - if (mSavedPIN != null && mLastUsedPIN != null && mSavedPIN.equals(mLastUsedPIN)) { - mLastUsedPIN = null; - } - mSavedPIN = null; - editor.remove("SavedPIN"); - editor.apply(); - } - - public static void saveEncryptedPIN(Cipher cipher, String PIN) { - try { - byte[] iv = cipher.getIV(); - byte[] bytes = cipher.doFinal(PIN.getBytes()); - String encryptedPIN = Base64.encodeToString(bytes, Base64.NO_WRAP); - String sIV = Base64.encodeToString(iv, Base64.NO_WRAP); - -// Log.d("PINStorage", String.format("saveEncryptedPIN: %s, encrypted: %s, iv: %s",PIN,encryptedPIN,sIV)); - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putString("EncryptedPIN", encryptedPIN); - editor.putString("EncryptedIV", sIV); - editor.apply(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static byte[] loadEncryptedIV() { - String sIV = sharedPreferences.getString("EncryptedIV", ""); -// Log.d("PINStorage", String.format("loadEncryptedIV: %s",sIV)); - - return Base64.decode(sIV, Base64.NO_WRAP); - } - - public static String loadEncryptedPIN(Cipher cipher) { - String encryptedPIN = sharedPreferences.getString("EncryptedPIN", null); - - try { - byte[] bytes = Base64.decode(encryptedPIN, Base64.NO_WRAP); - mEncryptedPIN = new String(cipher.doFinal(bytes)); -// Log.d("PINStorage", String.format("loadEncryptedPIN: %s (encrypted: %s)",mEncryptedPIN,encryptedPIN)); - } catch (Exception e) { - e.printStackTrace(); - mEncryptedPIN = null; - } - return mEncryptedPIN; - } - - public static boolean haveEncryptedPIN() { - return sharedPreferences.getString("EncryptedPIN", null) != null; - } - - public static void deleteEncryptedPIN() { - if (mEncryptedPIN != null && mLastUsedPIN != null && mEncryptedPIN.equals(mLastUsedPIN)) { - mLastUsedPIN = null; - } - mEncryptedPIN = null; - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.remove("EncryptedPIN"); - editor.remove("EncryptedIV"); - editor.apply(); - } - - public static void saveEncryptedPIN2(Cipher cipher, String PIN) { - try { - byte[] iv = cipher.getIV(); - byte[] bytes = cipher.doFinal(PIN.getBytes()); - String encryptedPIN = Base64.encodeToString(bytes, Base64.NO_WRAP); - String sIV = Base64.encodeToString(iv, Base64.NO_WRAP); - -// Log.d("PINStorage", String.format("saveEncryptedPIN: %s, encrypted: %s, iv: %s",PIN,encryptedPIN,sIV)); - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.putString("EncryptedPIN2", encryptedPIN); - editor.putString("EncryptedIV2", sIV); - editor.apply(); - - } catch (Exception e) { - e.printStackTrace(); - } - } - - public static byte[] loadEncryptedIV2() { - String sIV = sharedPreferences.getString("EncryptedIV2", ""); -// Log.d("PINStorage", String.format("loadEncryptedIV: %s",sIV)); - - return Base64.decode(sIV, Base64.NO_WRAP); - } - - public static String loadEncryptedPIN2(Cipher cipher) { - String encryptedPIN = sharedPreferences.getString("EncryptedPIN2", null); - - try { - byte[] bytes = Base64.decode(encryptedPIN, Base64.NO_WRAP); - mPIN2 = new String(cipher.doFinal(bytes)); -// Log.d("PINStorage", String.format("loadEncryptedPIN: %s (encrypted: %s)",mEncryptedPIN,encryptedPIN)); - } catch (Exception e) { - e.printStackTrace(); - mPIN2 = null; - } - return mPIN2; - } - - public static boolean haveEncryptedPIN2() { - return sharedPreferences.getString("EncryptedPIN2", null) != null; - } - - public static void deleteEncryptedPIN2() { - mPIN2 = null; - SharedPreferences.Editor editor = sharedPreferences.edit(); - editor.remove("EncryptedPIN2"); - editor.remove("EncryptedIV2"); - editor.apply(); - } - - public static String getPIN2() { - return mPIN2; - } - - public static boolean isDefaultPIN(String pin) { - return (pin != null) && (CardProtocol.DefaultPIN.equals(pin)); - } - - public static boolean isDefaultPIN2(String pin2) { - return (pin2 != null) && (CardProtocol.DefaultPIN2.equals(pin2)); - } - - public static String getDefaultPIN() { - return CardProtocol.DefaultPIN; - } - - public static String getDefaultPIN2() { - return CardProtocol.DefaultPIN2; - } - - public static boolean needInit() { - return sharedPreferences==null; - } -} +package com.tangem.domain.wallet; + +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.util.Base64; + +import com.tangem.domain.cardReader.CardProtocol; + +import java.util.ArrayList; +import java.util.List; + +import javax.crypto.Cipher; + +/** + * Created by dvol on 12.09.2017. + * Global PIN Storage + */ + +public class PINStorage { + private static String mSavedPIN, mUserPIN, mLastUsedPIN, mEncryptedPIN, mPIN2; + private static SharedPreferences sharedPreferences=null; + + public static void Init(Context context) { + sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + mSavedPIN = sharedPreferences.getString("SavedPIN", null); + mUserPIN = null; + mLastUsedPIN = null; + mEncryptedPIN = null; + mPIN2 = null; + } + + + public static List getPINs() { + ArrayList result = new ArrayList<>(); + if (mLastUsedPIN != null) result.add(mLastUsedPIN); + if (mEncryptedPIN != null && !result.contains(mEncryptedPIN)) result.add(mEncryptedPIN); + if (mUserPIN != null && !result.contains(mUserPIN)) result.add(mUserPIN); + if (mSavedPIN != null && !result.contains(mSavedPIN)) result.add(mSavedPIN); + if (!result.contains(CardProtocol.DefaultPIN)) result.add(CardProtocol.DefaultPIN); + return result; + } + + public static void setLastUsedPIN(String PIN) { + mLastUsedPIN = PIN; + } + + public static void setUserPIN(String PIN) { + mUserPIN = PIN; + } + + public static void setPIN2(String PIN) { + mPIN2 = PIN; + } + + public static void savePIN(String PIN) { + mSavedPIN = PIN; + if (mSavedPIN != null && !mSavedPIN.isEmpty()) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("SavedPIN", mSavedPIN); + editor.apply(); + } else { + deletePIN(); + } + } + + public static void deletePIN() { + SharedPreferences.Editor editor = sharedPreferences.edit(); + if (mSavedPIN != null && mLastUsedPIN != null && mSavedPIN.equals(mLastUsedPIN)) { + mLastUsedPIN = null; + } + mSavedPIN = null; + editor.remove("SavedPIN"); + editor.apply(); + } + + public static void saveEncryptedPIN(Cipher cipher, String PIN) { + try { + byte[] iv = cipher.getIV(); + byte[] bytes = cipher.doFinal(PIN.getBytes()); + String encryptedPIN = Base64.encodeToString(bytes, Base64.NO_WRAP); + String sIV = Base64.encodeToString(iv, Base64.NO_WRAP); + +// Log.d("PINStorage", String.format("saveEncryptedPIN: %s, encrypted: %s, iv: %s",PIN,encryptedPIN,sIV)); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("EncryptedPIN", encryptedPIN); + editor.putString("EncryptedIV", sIV); + editor.apply(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static byte[] loadEncryptedIV() { + String sIV = sharedPreferences.getString("EncryptedIV", ""); +// Log.d("PINStorage", String.format("loadEncryptedIV: %s",sIV)); + + return Base64.decode(sIV, Base64.NO_WRAP); + } + + public static String loadEncryptedPIN(Cipher cipher) { + String encryptedPIN = sharedPreferences.getString("EncryptedPIN", null); + + try { + byte[] bytes = Base64.decode(encryptedPIN, Base64.NO_WRAP); + mEncryptedPIN = new String(cipher.doFinal(bytes)); +// Log.d("PINStorage", String.format("loadEncryptedPIN: %s (encrypted: %s)",mEncryptedPIN,encryptedPIN)); + } catch (Exception e) { + e.printStackTrace(); + mEncryptedPIN = null; + } + return mEncryptedPIN; + } + + public static boolean haveEncryptedPIN() { + return sharedPreferences.getString("EncryptedPIN", null) != null; + } + + public static void deleteEncryptedPIN() { + if (mEncryptedPIN != null && mLastUsedPIN != null && mEncryptedPIN.equals(mLastUsedPIN)) { + mLastUsedPIN = null; + } + mEncryptedPIN = null; + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove("EncryptedPIN"); + editor.remove("EncryptedIV"); + editor.apply(); + } + + public static void saveEncryptedPIN2(Cipher cipher, String PIN) { + try { + byte[] iv = cipher.getIV(); + byte[] bytes = cipher.doFinal(PIN.getBytes()); + String encryptedPIN = Base64.encodeToString(bytes, Base64.NO_WRAP); + String sIV = Base64.encodeToString(iv, Base64.NO_WRAP); + +// Log.d("PINStorage", String.format("saveEncryptedPIN: %s, encrypted: %s, iv: %s",PIN,encryptedPIN,sIV)); + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString("EncryptedPIN2", encryptedPIN); + editor.putString("EncryptedIV2", sIV); + editor.apply(); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + public static byte[] loadEncryptedIV2() { + String sIV = sharedPreferences.getString("EncryptedIV2", ""); +// Log.d("PINStorage", String.format("loadEncryptedIV: %s",sIV)); + + return Base64.decode(sIV, Base64.NO_WRAP); + } + + public static String loadEncryptedPIN2(Cipher cipher) { + String encryptedPIN = sharedPreferences.getString("EncryptedPIN2", null); + + try { + byte[] bytes = Base64.decode(encryptedPIN, Base64.NO_WRAP); + mPIN2 = new String(cipher.doFinal(bytes)); +// Log.d("PINStorage", String.format("loadEncryptedPIN: %s (encrypted: %s)",mEncryptedPIN,encryptedPIN)); + } catch (Exception e) { + e.printStackTrace(); + mPIN2 = null; + } + return mPIN2; + } + + public static boolean haveEncryptedPIN2() { + return sharedPreferences.getString("EncryptedPIN2", null) != null; + } + + public static void deleteEncryptedPIN2() { + mPIN2 = null; + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.remove("EncryptedPIN2"); + editor.remove("EncryptedIV2"); + editor.apply(); + } + + public static String getPIN2() { + return mPIN2; + } + + public static boolean isDefaultPIN(String pin) { + return (pin != null) && (CardProtocol.DefaultPIN.equals(pin)); + } + + public static boolean isDefaultPIN2(String pin2) { + return (pin2 != null) && (CardProtocol.DefaultPIN2.equals(pin2)); + } + + public static String getDefaultPIN() { + return CardProtocol.DefaultPIN; + } + + public static String getDefaultPIN2() { + return CardProtocol.DefaultPIN2; + } + + public static boolean needInit() { + return sharedPreferences==null; + } +} diff --git a/app/src/main/java/com/tangem/wallet/RLP.java b/app/src/main/java/com/tangem/domain/wallet/RLP.java similarity index 95% rename from app/src/main/java/com/tangem/wallet/RLP.java rename to app/src/main/java/com/tangem/domain/wallet/RLP.java index 17ae006e1a..c4293da0eb 100644 --- a/app/src/main/java/com/tangem/wallet/RLP.java +++ b/app/src/main/java/com/tangem/domain/wallet/RLP.java @@ -1,228 +1,228 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 07.01.2018. - */ - -import java.util.Arrays; - -import static com.tangem.wallet.ByteUtil.isNullOrZeroArray; -import static com.tangem.wallet.ByteUtil.isSingleZero; - -public class RLP { - public static final byte[] EMPTY_ELEMENT_RLP = encodeElement(new byte[0]); - - /** - * Allow for content up to size of 2^64 bytes * - */ - private static final double MAX_ITEM_LENGTH = Math.pow(256, 8); - - /** - * Reason for threshold according to Vitalik Buterin: - * - 56 bytes maximizes the benefit of both options - * - if we went with 60 then we would have only had 4 slots for long strings - * so RLP would not have been able to store objects above 4gb - * - if we went with 48 then RLP would be fine for 2^128 space, but that's way too much - * - so 56 and 2^64 space seems like the right place to put the cutoff - * - also, that's where Bitcoin's varint does the cutof - */ - private static final int SIZE_THRESHOLD = 56; - - /** RLP encoding rules are defined as follows: */ - - /* - * For a single byte whose value is in the [0x00, 0x7f] range, that byte is - * its own RLP encoding. - */ - - /** - * [0x80] - * If a string is 0-55 bytes long, the RLP encoding consists of a single - * byte with value 0x80 plus the length of the string followed by the - * string. The range of the first byte is thus [0x80, 0xb7]. - */ - private static final int OFFSET_SHORT_ITEM = 0x80; - - /** - * [0xb7] - * If a string is more than 55 bytes long, the RLP encoding consists of a - * single byte with value 0xb7 plus the length of the length of the string - * in binary form, followed by the length of the string, followed by the - * string. For example, a length-1024 string would be encoded as - * \xb9\x04\x00 followed by the string. The range of the first byte is thus - * [0xb8, 0xbf]. - */ - private static final int OFFSET_LONG_ITEM = 0xb7; - - /** - * [0xc0] - * If the total payload of a list (i.e. the combined length of all its - * items) is 0-55 bytes long, the RLP encoding consists of a single byte - * with value 0xc0 plus the length of the list followed by the concatenation - * of the RLP encodings of the items. The range of the first byte is thus - * [0xc0, 0xf7]. - */ - private static final int OFFSET_SHORT_LIST = 0xc0; - - public static byte[] encodeByte(byte singleByte) { - if ((singleByte & 0xFF) == 0) { - return new byte[]{(byte) OFFSET_SHORT_ITEM}; - } else if ((singleByte & 0xFF) <= 0x7F) { - return new byte[]{singleByte}; - } else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 1), singleByte}; - } - } - - public static byte[] encodeShort(short singleShort) { - if ((singleShort & 0xFF) == singleShort) - return encodeByte((byte) singleShort); - else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 2), - (byte) (singleShort >> 8 & 0xFF), - (byte) (singleShort >> 0 & 0xFF)}; - } - } - - public static byte[] encodeInt(int singleInt) { - if ((singleInt & 0xFF) == singleInt) - return encodeByte((byte) singleInt); - else if ((singleInt & 0xFFFF) == singleInt) - return encodeShort((short) singleInt); - else if ((singleInt & 0xFFFFFF) == singleInt) - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 3), - (byte) (singleInt >>> 16), - (byte) (singleInt >>> 8), - (byte) singleInt}; - else { - return new byte[]{(byte) (OFFSET_SHORT_ITEM + 4), - (byte) (singleInt >>> 24), - (byte) (singleInt >>> 16), - (byte) (singleInt >>> 8), - (byte) singleInt}; - } - } - - private static final int OFFSET_LONG_LIST = 0xf7; - - public static byte[] encodeElement2(byte[] srcData) { - if (srcData == null) - return new byte[]{(byte) OFFSET_SHORT_ITEM}; - else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { - return srcData; - } else if (srcData.length < SIZE_THRESHOLD) { - // length = 8X - byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length); - byte[] data = Arrays.copyOf(srcData, srcData.length + 1); - System.arraycopy(data, 0, data, 1, srcData.length); - data[0] = length; - - return data; - } else { - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = srcData.length; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - byte[] lenBytes = new byte[byteNum]; - for (int i = 0; i < byteNum; ++i) { - lenBytes[byteNum - 1 - i] = (byte) ((srcData.length >> (8 * i)) & 0xFF); - } - // first byte = F7 + bytes.length - byte[] data = Arrays.copyOf(srcData, srcData.length + 1 + byteNum); - System.arraycopy(data, 0, data, 1 + byteNum, srcData.length); - data[0] = (byte) (OFFSET_LONG_ITEM + byteNum); - System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); - - return data; - } - } - public static byte[] encodeElement(byte[] srcData) { - - if (isNullOrZeroArray(srcData)) - return new byte[]{(byte) OFFSET_SHORT_ITEM}; - else if (isSingleZero(srcData)) - return srcData; - else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { - return srcData; - } else if (srcData.length < SIZE_THRESHOLD) { - // length = 8X - byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length); - byte[] data = Arrays.copyOf(srcData, srcData.length + 1); - System.arraycopy(data, 0, data, 1, srcData.length); - data[0] = length; - - return data; - } else { - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = srcData.length; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - byte[] lenBytes = new byte[byteNum]; - for (int i = 0; i < byteNum; ++i) { - lenBytes[byteNum - 1 - i] = (byte) ((srcData.length >> (8 * i)) & 0xFF); - } - // first byte = F7 + bytes.length - byte[] data = Arrays.copyOf(srcData, srcData.length + 1 + byteNum); - System.arraycopy(data, 0, data, 1 + byteNum, srcData.length); - data[0] = (byte) (OFFSET_LONG_ITEM + byteNum); - System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); - - return data; - } - } - - - public static byte[] encodeList(byte[]... elements) { - - if (elements == null) { - return new byte[]{(byte) OFFSET_SHORT_LIST}; - } - - int totalLength = 0; - for (byte[] element1 : elements) { - totalLength += element1.length; - } - - byte[] data; - int copyPos; - if (totalLength < SIZE_THRESHOLD) { - - data = new byte[1 + totalLength]; - data[0] = (byte) (OFFSET_SHORT_LIST + totalLength); - copyPos = 1; - } else { - // length of length = BX - // prefix = [BX, [length]] - int tmpLength = totalLength; - byte byteNum = 0; - while (tmpLength != 0) { - ++byteNum; - tmpLength = tmpLength >> 8; - } - tmpLength = totalLength; - byte[] lenBytes = new byte[byteNum]; - for (int i = 0; i < byteNum; ++i) { - lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); - } - // first byte = F7 + bytes.length - data = new byte[1 + lenBytes.length + totalLength]; - data[0] = (byte) (OFFSET_LONG_LIST + byteNum); - System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); - - copyPos = lenBytes.length + 1; - } - for (byte[] element : elements) { - System.arraycopy(element, 0, data, copyPos, element.length); - copyPos += element.length; - } - return data; - } +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 07.01.2018. + */ + +import java.util.Arrays; + +import static com.tangem.domain.wallet.ByteUtil.isNullOrZeroArray; +import static com.tangem.domain.wallet.ByteUtil.isSingleZero; + +public class RLP { + public static final byte[] EMPTY_ELEMENT_RLP = encodeElement(new byte[0]); + + /** + * Allow for content up to size of 2^64 bytes * + */ + private static final double MAX_ITEM_LENGTH = Math.pow(256, 8); + + /** + * Reason for threshold according to Vitalik Buterin: + * - 56 bytes maximizes the benefit of both options + * - if we went with 60 then we would have only had 4 slots for long strings + * so RLP would not have been able to store objects above 4gb + * - if we went with 48 then RLP would be fine for 2^128 space, but that's way too much + * - so 56 and 2^64 space seems like the right place to put the cutoff + * - also, that's where Bitcoin's varint does the cutof + */ + private static final int SIZE_THRESHOLD = 56; + + /** RLP encoding rules are defined as follows: */ + + /* + * For a single byte whose value is in the [0x00, 0x7f] range, that byte is + * its own RLP encoding. + */ + + /** + * [0x80] + * If a string is 0-55 bytes long, the RLP encoding consists of a single + * byte with value 0x80 plus the length of the string followed by the + * string. The range of the first byte is thus [0x80, 0xb7]. + */ + private static final int OFFSET_SHORT_ITEM = 0x80; + + /** + * [0xb7] + * If a string is more than 55 bytes long, the RLP encoding consists of a + * single byte with value 0xb7 plus the length of the length of the string + * in binary form, followed by the length of the string, followed by the + * string. For example, a length-1024 string would be encoded as + * \xb9\x04\x00 followed by the string. The range of the first byte is thus + * [0xb8, 0xbf]. + */ + private static final int OFFSET_LONG_ITEM = 0xb7; + + /** + * [0xc0] + * If the total payload of a list (i.e. the combined length of all its + * items) is 0-55 bytes long, the RLP encoding consists of a single byte + * with value 0xc0 plus the length of the list followed by the concatenation + * of the RLP encodings of the items. The range of the first byte is thus + * [0xc0, 0xf7]. + */ + private static final int OFFSET_SHORT_LIST = 0xc0; + + public static byte[] encodeByte(byte singleByte) { + if ((singleByte & 0xFF) == 0) { + return new byte[]{(byte) OFFSET_SHORT_ITEM}; + } else if ((singleByte & 0xFF) <= 0x7F) { + return new byte[]{singleByte}; + } else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 1), singleByte}; + } + } + + public static byte[] encodeShort(short singleShort) { + if ((singleShort & 0xFF) == singleShort) + return encodeByte((byte) singleShort); + else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 2), + (byte) (singleShort >> 8 & 0xFF), + (byte) (singleShort >> 0 & 0xFF)}; + } + } + + public static byte[] encodeInt(int singleInt) { + if ((singleInt & 0xFF) == singleInt) + return encodeByte((byte) singleInt); + else if ((singleInt & 0xFFFF) == singleInt) + return encodeShort((short) singleInt); + else if ((singleInt & 0xFFFFFF) == singleInt) + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 3), + (byte) (singleInt >>> 16), + (byte) (singleInt >>> 8), + (byte) singleInt}; + else { + return new byte[]{(byte) (OFFSET_SHORT_ITEM + 4), + (byte) (singleInt >>> 24), + (byte) (singleInt >>> 16), + (byte) (singleInt >>> 8), + (byte) singleInt}; + } + } + + private static final int OFFSET_LONG_LIST = 0xf7; + + public static byte[] encodeElement2(byte[] srcData) { + if (srcData == null) + return new byte[]{(byte) OFFSET_SHORT_ITEM}; + else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { + return srcData; + } else if (srcData.length < SIZE_THRESHOLD) { + // length = 8X + byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length); + byte[] data = Arrays.copyOf(srcData, srcData.length + 1); + System.arraycopy(data, 0, data, 1, srcData.length); + data[0] = length; + + return data; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = srcData.length; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((srcData.length >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + byte[] data = Arrays.copyOf(srcData, srcData.length + 1 + byteNum); + System.arraycopy(data, 0, data, 1 + byteNum, srcData.length); + data[0] = (byte) (OFFSET_LONG_ITEM + byteNum); + System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); + + return data; + } + } + public static byte[] encodeElement(byte[] srcData) { + + if (isNullOrZeroArray(srcData)) + return new byte[]{(byte) OFFSET_SHORT_ITEM}; + else if (isSingleZero(srcData)) + return srcData; + else if (srcData.length == 1 && (srcData[0] & 0xFF) < 0x80) { + return srcData; + } else if (srcData.length < SIZE_THRESHOLD) { + // length = 8X + byte length = (byte) (OFFSET_SHORT_ITEM + srcData.length); + byte[] data = Arrays.copyOf(srcData, srcData.length + 1); + System.arraycopy(data, 0, data, 1, srcData.length); + data[0] = length; + + return data; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = srcData.length; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((srcData.length >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + byte[] data = Arrays.copyOf(srcData, srcData.length + 1 + byteNum); + System.arraycopy(data, 0, data, 1 + byteNum, srcData.length); + data[0] = (byte) (OFFSET_LONG_ITEM + byteNum); + System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); + + return data; + } + } + + + public static byte[] encodeList(byte[]... elements) { + + if (elements == null) { + return new byte[]{(byte) OFFSET_SHORT_LIST}; + } + + int totalLength = 0; + for (byte[] element1 : elements) { + totalLength += element1.length; + } + + byte[] data; + int copyPos; + if (totalLength < SIZE_THRESHOLD) { + + data = new byte[1 + totalLength]; + data[0] = (byte) (OFFSET_SHORT_LIST + totalLength); + copyPos = 1; + } else { + // length of length = BX + // prefix = [BX, [length]] + int tmpLength = totalLength; + byte byteNum = 0; + while (tmpLength != 0) { + ++byteNum; + tmpLength = tmpLength >> 8; + } + tmpLength = totalLength; + byte[] lenBytes = new byte[byteNum]; + for (int i = 0; i < byteNum; ++i) { + lenBytes[byteNum - 1 - i] = (byte) ((tmpLength >> (8 * i)) & 0xFF); + } + // first byte = F7 + bytes.length + data = new byte[1 + lenBytes.length + totalLength]; + data[0] = (byte) (OFFSET_LONG_LIST + byteNum); + System.arraycopy(lenBytes, 0, data, 1, lenBytes.length); + + copyPos = lenBytes.length + 1; + } + for (byte[] element : elements) { + System.arraycopy(element, 0, data, copyPos, element.length); + copyPos += element.length; + } + return data; + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/RLPElement.java b/app/src/main/java/com/tangem/domain/wallet/RLPElement.java similarity index 79% rename from app/src/main/java/com/tangem/wallet/RLPElement.java rename to app/src/main/java/com/tangem/domain/wallet/RLPElement.java index 3706e0be22..a94de8a740 100644 --- a/app/src/main/java/com/tangem/wallet/RLPElement.java +++ b/app/src/main/java/com/tangem/domain/wallet/RLPElement.java @@ -1,12 +1,12 @@ -package com.tangem.wallet; - -import java.io.Serializable; - -/** - * Created by Ilia on 07.01.2018. - */ - -public interface RLPElement extends Serializable { - - byte[] getRLPData(); -} +package com.tangem.domain.wallet; + +import java.io.Serializable; + +/** + * Created by Ilia on 07.01.2018. + */ + +public interface RLPElement extends Serializable { + + byte[] getRLPData(); +} diff --git a/app/src/main/java/com/tangem/wallet/RLPList.java b/app/src/main/java/com/tangem/domain/wallet/RLPList.java similarity index 93% rename from app/src/main/java/com/tangem/wallet/RLPList.java rename to app/src/main/java/com/tangem/domain/wallet/RLPList.java index 94dad1521f..90915c9f27 100644 --- a/app/src/main/java/com/tangem/wallet/RLPList.java +++ b/app/src/main/java/com/tangem/domain/wallet/RLPList.java @@ -1,37 +1,37 @@ -package com.tangem.wallet; - -import java.util.ArrayList; - -/** - * Created by Ilia on 07.01.2018. - */ - -public class RLPList extends ArrayList implements RLPElement { - - byte[] rlpData; - - public void setRLPData(byte[] rlpData) { - this.rlpData = rlpData; - } - - public byte[] getRLPData() { - return rlpData; - } - - public static void recursivePrint(RLPElement element) { - - if (element == null) - throw new RuntimeException("RLPElement object can't be null"); - if (element instanceof RLPList) { - - RLPList rlpList = (RLPList) element; - System.out.print("["); - for (RLPElement singleElement : rlpList) - recursivePrint(singleElement); - System.out.print("]"); - } else { - String hex = BTCUtils.toHex(element.getRLPData()); - System.out.print(hex + ", "); - } - } -} +package com.tangem.domain.wallet; + +import java.util.ArrayList; + +/** + * Created by Ilia on 07.01.2018. + */ + +public class RLPList extends ArrayList implements RLPElement { + + byte[] rlpData; + + public void setRLPData(byte[] rlpData) { + this.rlpData = rlpData; + } + + public byte[] getRLPData() { + return rlpData; + } + + public static void recursivePrint(RLPElement element) { + + if (element == null) + throw new RuntimeException("RLPElement object can't be null"); + if (element instanceof RLPList) { + + RLPList rlpList = (RLPList) element; + System.out.print("["); + for (RLPElement singleElement : rlpList) + recursivePrint(singleElement); + System.out.print("]"); + } else { + String hex = BTCUtils.toHex(element.getRLPData()); + System.out.print(hex + ", "); + } + } +} diff --git a/app/src/main/java/com/tangem/wallet/SharedData.java b/app/src/main/java/com/tangem/domain/wallet/SharedData.java similarity index 90% rename from app/src/main/java/com/tangem/wallet/SharedData.java rename to app/src/main/java/com/tangem/domain/wallet/SharedData.java index 20bbf5942d..f9557360fe 100644 --- a/app/src/main/java/com/tangem/wallet/SharedData.java +++ b/app/src/main/java/com/tangem/domain/wallet/SharedData.java @@ -1,23 +1,23 @@ -package com.tangem.wallet; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Created by Ilia on 12.04.2018. - */ - - -public class SharedData -{ - public static int COUNT_REQUEST = 3; - public AtomicInteger requestCounter; - public int allRequest; - public AtomicInteger errorRequest; - - public SharedData(int requstCount) - { - allRequest = requstCount; - errorRequest = new AtomicInteger(0); - requestCounter = new AtomicInteger(0); - } +package com.tangem.domain.wallet; + +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Created by Ilia on 12.04.2018. + */ + + +public class SharedData +{ + public static int COUNT_REQUEST = 3; + public AtomicInteger requestCounter; + public int allRequest; + public AtomicInteger errorRequest; + + public SharedData(int requstCount) + { + allRequest = requstCount; + errorRequest = new AtomicInteger(0); + requestCounter = new AtomicInteger(0); + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/wallet/Tangem_Card.java b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java similarity index 99% rename from app/src/main/java/com/tangem/wallet/Tangem_Card.java rename to app/src/main/java/com/tangem/domain/wallet/TangemCard.java index b18187d8a2..aebeb5fca7 100644 --- a/app/src/main/java/com/tangem/wallet/Tangem_Card.java +++ b/app/src/main/java/com/tangem/domain/wallet/TangemCard.java @@ -1,10 +1,10 @@ -package com.tangem.wallet; +package com.tangem.domain.wallet; import android.os.Bundle; import com.google.common.base.Strings; import com.tangem.domain.cardReader.SettingsMask; -import com.tangem.domain.cardReader.Util; +import com.tangem.util.Util; import java.math.BigInteger; import java.util.ArrayList; @@ -16,7 +16,7 @@ import java.util.List; * Created by dvol on 16.07.2017. */ -public class Tangem_Card { +public class TangemCard { private byte[] CID; private Status status; private String wallet; @@ -1017,7 +1017,7 @@ public class Tangem_Card { return mHeaders != null; } - public Tangem_Card(String UID) { + public TangemCard(String UID) { this.UID = UID; } diff --git a/app/src/main/java/com/tangem/wallet/TokenEngine.java b/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java similarity index 79% rename from app/src/main/java/com/tangem/wallet/TokenEngine.java rename to app/src/main/java/com/tangem/domain/wallet/TokenEngine.java index 79c92b1d6e..1da5574f35 100644 --- a/app/src/main/java/com/tangem/wallet/TokenEngine.java +++ b/app/src/main/java/com/tangem/domain/wallet/TokenEngine.java @@ -1,405 +1,405 @@ -package com.tangem.wallet; - -import android.net.Uri; -import android.util.Log; - -import com.google.common.base.Strings; -import com.tangem.domain.cardReader.CardProtocol; -import com.tangem.domain.cardReader.TLV; - -import org.bitcoinj.core.ECKey; - -import java.math.BigDecimal; -import java.math.BigInteger; -import java.math.RoundingMode; -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; -import java.text.DecimalFormat; -import java.util.Arrays; -import java.util.Date; - -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) { - return "abc1.hsmiths.com"; - } - - public int GetNextNodePort(Tangem_Card mCard) { - return 60001; - } - - public String GetNode(Tangem_Card mCard) { - return "abc1.hsmiths.com"; - } - - public int GetNodePort(Tangem_Card mCard) { - return 60001; - } - - public void SwitchNode(Tangem_Card mCard) { - } - - public boolean AwaitingConfirmation(Tangem_Card card) { - return false; - } - - public boolean InOutPutVisible() { - return false; - } - - public String GetBalanceCurrency(Tangem_Card card) { - String currency = card.getTokenSymbol(); - if (Strings.isNullOrEmpty(currency)) - return "NoN"; - return currency; - } - - public String GetFeeCurrency() { - return "Gwei"; - } - - BigDecimal convertToEth(String value) { - BigInteger m = new BigInteger(value, 10); - BigDecimal n = new BigDecimal(m); - BigDecimal d = n.divide(new BigDecimal("1000000000000000000")); - d = d.setScale(8, RoundingMode.DOWN); - return d; - } - - - public int GetTokenDecimals(Tangem_Card card) { - return card.getTokensDecimal(); - } - - public String GetContractAddress(Tangem_Card card) { - return card.getContractAddress(); - } - - public boolean IsNeedCheckNode() { - return false; - } - - public boolean ValdateAddress(String address, Tangem_Card card) { - if (address == null || address.isEmpty()) { - return false; - } - - if (!address.startsWith("0x") && !address.startsWith("0X")) { - return false; - } - - if (address.length() != 42) { - return false; - } - - return true; - } - - public String GetBalanceAlterValue(Tangem_Card mCard) { - String dec = mCard.getDecimalBalanceAlter(); - BigDecimal d = convertToEth(dec); - String s = d.toString(); - - String pattern = "#0.000"; // If you like 4 zeros - DecimalFormat myFormatter = new DecimalFormat(pattern); - String output = myFormatter.format(d); - return output; - } - - public String GetBalanceValue(Tangem_Card mCard) { - if (!HasBalanceInfo(mCard)) - return "-- -- -- " + GetBalanceCurrency(mCard); - - String dec = mCard.getDecimalBalance(); - BigDecimal d = new BigDecimal(dec); - BigDecimal p = new BigDecimal(10); - p = p.pow(GetTokenDecimals(mCard)); - BigDecimal l = d.divide(p); - - String pattern = "#0.000"; // If you like 4 zeros - DecimalFormat myFormatter = new DecimalFormat(pattern); - String output = myFormatter.format(l); - return output; - } - - 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) { - return false; - } - - return true; - } - - public Long GetBalanceLong(Tangem_Card mCard) { - return mCard.getBalance(); - } - - public boolean IsBalanceAlterNotZero(Tangem_Card card) { - String balance = card.getDecimalBalanceAlter(); - if (balance == null || balance == "") - return false; - - BigDecimal bi = new BigDecimal(balance); - - if (BigDecimal.ZERO.compareTo(bi) == 0) - return false; - - return true; - } - - public boolean IsBalanceNotZero(Tangem_Card card) { - String balance = card.getDecimalBalance(); - if (balance == null || balance == "") - return false; - - BigDecimal bi = new BigDecimal(balance); - - if (BigDecimal.ZERO.compareTo(bi) == 0) - return false; - - return true; - } - - public boolean HasBalanceInfo(Tangem_Card card) { - String balance = card.getDecimalBalance(); - if (balance == null || balance == "") - return false; - - String balanceEx = card.getDecimalBalanceAlter(); - if (balanceEx == null || balanceEx == "") - return false; - return true; - } - - @Override - public String GetBalanceEquivalent(Tangem_Card mCard) { - if (!HasBalanceInfo(mCard)) { - return "-- -- -- "; - } - String dec = mCard.getDecimalBalance(); - BigDecimal d = convertToEth(dec); - return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRate()); - } - - @Override - public String GetBalance(Tangem_Card mCard) { - if (!HasBalanceInfo(mCard)) { - return "-- -- -- " + GetBalanceCurrency(mCard); - } - - String output = GetBalanceValue(mCard); - String s = output + " " + GetBalanceCurrency(mCard); - return s; - } - - - public String GetBalanceWithAlter(Tangem_Card mCard) { - //return GetBalance(mCard) + "\n(" + GetBalanceAlterValue(mCard) + " ETH)"; - return " " + GetBalance(mCard) + "
+ " + GetBalanceAlterValue(mCard) + " ETH for gas"; - } - - public String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { - Keccak256 kec = new Keccak256(); - int lenPk = pkUncompressed.length; - if (lenPk < 2) { - throw new IllegalArgumentException("Uncompress public key length is invald"); - } - byte[] cleanKey = new byte[lenPk - 1]; - for (int i = 0; i < cleanKey.length; ++i) { - cleanKey[i] = pkUncompressed[i + 1]; - } - byte[] r = kec.digest(cleanKey); - - byte[] address = new byte[20]; - for (int i = 0; i < 20; ++i) { - address[i] = r[i + 12]; - } - - return String.format("0x%s", BTCUtils.toHex(address)); - } - - @Override - public String ConvertByteArrayToAmount(Tangem_Card mCard, byte[] bytes) throws Exception { - throw new Exception("Not implemented"); - } - - @Override - public byte[] ConvertAmountToByteArray(Tangem_Card mCard, String amount) throws Exception { - throw new Exception("Not implemented"); - } - - @Override - public String GetAmountDescription(Tangem_Card mCard, String amount) throws Exception { - throw new Exception("Not implemented"); - } - - - 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) { - 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 getShareWalletURI(Tangem_Card mCard) { - return Uri.parse("" + mCard.getWallet()); - } - - public boolean CheckUnspentTransaction(Tangem_Card mCard) { - return true; - } - - public boolean CheckAmountValie(Tangem_Card mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) { - Long fee = null; - BigDecimal amount = null; - try { - amount = new BigDecimal(GetBalanceAlterValue(mCard));//mCard.InternalUnitsFromString(amountValue); - fee = mCard.InternalUnitsFromString(feeValue); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - - if (fee == null || amount == null) - return false; - - if (fee == 0 || amount.compareTo(BigDecimal.ZERO) == 0) - return false; - - - if (fee < minFeeInInternalUnits) - return false; - - - BigDecimal tmpFee = new BigDecimal(feeValue); - BigDecimal tmpAmount = amount; - tmpAmount = tmpAmount.multiply(new BigDecimal("1000000000")); - - if (tmpFee.compareTo(tmpAmount) > 0) - return false; - - return true; - } - - 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); - return GetFeeEqualentDescriptor(mCard, gweFee.toString()); - } - - public byte[] Sign(String feeValue, String amountValue, String toValue, Tangem_Card mCard, CardProtocol protocol) throws Exception { - - BigInteger nonceValue = mCard.GetConfirmTXCount(); - byte[] pbKey = mCard.getWalletPublicKey(); - boolean flag = (mCard.getSigningMethod() == Tangem_Card.SigningMethod.Sign_Hash_Validated_By_Issuer); - Issuer issuer = mCard.getIssuer(); - - - BigInteger fee = new BigInteger(feeValue, 10); - - BigDecimal amountDecValue = new BigDecimal(amountValue); - - int d = GetTokenDecimals(mCard); - BigDecimal amountDec = new BigDecimal("10"); - amountDec = amountDec.pow(d); - amountDec = amountDecValue.multiply(amountDec); - - //amountDec = amountDec.multiply(new BigDecimal("1000000000")); - - - BigInteger amount = amountDec.toBigInteger(); //new BigInteger(amountValue, 10); - - - //amount = amount.subtract(fee); - - BigInteger nonce = nonceValue; - BigInteger gasPrice = fee.divide(BigInteger.valueOf(21000)); - BigInteger gasLimit = BigInteger.valueOf(60000); - Integer chainId = ETH_Transaction.ChainEnum.Mainnet.getValue(); - BigInteger amountZero = BigInteger.ZERO; - - Long multiplicator = 1000000000L; - - gasPrice = gasPrice.multiply(BigInteger.valueOf(multiplicator)); - - String to = toValue; - - if (to.startsWith("0x") || to.startsWith("0X")) { - to = to.substring(2); - } - - String contractAddress = GetContractAddress(mCard); - - if (contractAddress.startsWith("0x") || contractAddress.startsWith("0X")) { - contractAddress = contractAddress.substring(2); - } - - String amountLeadZero = amount.toString(16); - if (amountLeadZero.startsWith("0x") || amountLeadZero.startsWith("0X")) { - amountLeadZero = amountLeadZero.substring(2); - } - - while (amountLeadZero.length() < 64) { - amountLeadZero = "0" + amountLeadZero; - } - - String cmd = "a9059cbb000000000000000000000000" + to + amountLeadZero; //TODO only for BAT - - - byte[] data = BTCUtils.fromHex(cmd); - ETH_Transaction tx = ETH_Transaction.create(contractAddress, amountZero, nonce, gasPrice, gasLimit, chainId, data); - - byte[][] hashesForSign = new byte[1][]; - byte[] for_hash = tx.getRawHash(); - hashesForSign[0] = for_hash; - - byte[] signFromCard = null; - try { - signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value; - // TODO slice signFromCard to hashes.length parts - } catch (Exception ex) { - Log.e("ETH", ex.getMessage()); - return null; - } - - LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); - - BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, 32)); - BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32, 64)); - s = CryptoUtil.toCanonicalised(s); - - boolean f = ECKey.verify(for_hash, new ECKey.ECDSASignature(r, s), pbKey); - - if (!f) { - Log.e("ETH-CHECK", "Sign Failed."); - } - - tx.signature = new ECDSASignature_ETH(r, s); - int v = tx.BruteRecoveryID2(tx.signature, for_hash, pbKey); - if (v != 27 && v != 28) { - Log.e("ETH", "invalid v"); - return null; - } - tx.signature.v = (byte) v; - Log.e("ETH_v", String.valueOf(v)); - - byte[] realTX = tx.getEncoded(); - return realTX; - } -} +package com.tangem.domain.wallet; + +import android.net.Uri; +import android.util.Log; + +import com.google.common.base.Strings; +import com.tangem.domain.cardReader.CardProtocol; +import com.tangem.domain.cardReader.TLV; + +import org.bitcoinj.core.ECKey; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.math.RoundingMode; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.Date; + +import static com.tangem.domain.wallet.FormatUtil.GetDecimalFormat; + +/** + * Created by Ilia on 20.03.2018. + */ + +public class TokenEngine extends CoinEngine { + public String GetNextNode(TangemCard mCard) { + return "abc1.hsmiths.com"; + } + + public int GetNextNodePort(TangemCard mCard) { + return 60001; + } + + public String GetNode(TangemCard mCard) { + return "abc1.hsmiths.com"; + } + + public int GetNodePort(TangemCard mCard) { + return 60001; + } + + public void SwitchNode(TangemCard mCard) { + } + + public boolean AwaitingConfirmation(TangemCard card) { + return false; + } + + public boolean InOutPutVisible() { + return false; + } + + public String GetBalanceCurrency(TangemCard card) { + String currency = card.getTokenSymbol(); + if (Strings.isNullOrEmpty(currency)) + return "NoN"; + return currency; + } + + public String GetFeeCurrency() { + return "Gwei"; + } + + BigDecimal convertToEth(String value) { + BigInteger m = new BigInteger(value, 10); + BigDecimal n = new BigDecimal(m); + BigDecimal d = n.divide(new BigDecimal("1000000000000000000")); + d = d.setScale(8, RoundingMode.DOWN); + return d; + } + + + public int GetTokenDecimals(TangemCard card) { + return card.getTokensDecimal(); + } + + public String GetContractAddress(TangemCard card) { + return card.getContractAddress(); + } + + public boolean IsNeedCheckNode() { + return false; + } + + public boolean ValdateAddress(String address, TangemCard card) { + if (address == null || address.isEmpty()) { + return false; + } + + if (!address.startsWith("0x") && !address.startsWith("0X")) { + return false; + } + + if (address.length() != 42) { + return false; + } + + return true; + } + + public String GetBalanceAlterValue(TangemCard mCard) { + String dec = mCard.getDecimalBalanceAlter(); + BigDecimal d = convertToEth(dec); + String s = d.toString(); + + String pattern = "#0.000"; // If you like 4 zeros + DecimalFormat myFormatter = new DecimalFormat(pattern); + String output = myFormatter.format(d); + return output; + } + + public String GetBalanceValue(TangemCard mCard) { + if (!HasBalanceInfo(mCard)) + return "-- -- -- " + GetBalanceCurrency(mCard); + + String dec = mCard.getDecimalBalance(); + BigDecimal d = new BigDecimal(dec); + BigDecimal p = new BigDecimal(10); + p = p.pow(GetTokenDecimals(mCard)); + BigDecimal l = d.divide(p); + + String pattern = "#0.000"; // If you like 4 zeros + DecimalFormat myFormatter = new DecimalFormat(pattern); + String output = myFormatter.format(l); + return output; + } + + public boolean CheckAmount(TangemCard 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) { + return false; + } + + return true; + } + + public Long GetBalanceLong(TangemCard mCard) { + return mCard.getBalance(); + } + + public boolean IsBalanceAlterNotZero(TangemCard card) { + String balance = card.getDecimalBalanceAlter(); + if (balance == null || balance == "") + return false; + + BigDecimal bi = new BigDecimal(balance); + + if (BigDecimal.ZERO.compareTo(bi) == 0) + return false; + + return true; + } + + public boolean IsBalanceNotZero(TangemCard card) { + String balance = card.getDecimalBalance(); + if (balance == null || balance == "") + return false; + + BigDecimal bi = new BigDecimal(balance); + + if (BigDecimal.ZERO.compareTo(bi) == 0) + return false; + + return true; + } + + public boolean HasBalanceInfo(TangemCard card) { + String balance = card.getDecimalBalance(); + if (balance == null || balance == "") + return false; + + String balanceEx = card.getDecimalBalanceAlter(); + if (balanceEx == null || balanceEx == "") + return false; + return true; + } + + @Override + public String GetBalanceEquivalent(TangemCard mCard) { + if (!HasBalanceInfo(mCard)) { + return "-- -- -- "; + } + String dec = mCard.getDecimalBalance(); + BigDecimal d = convertToEth(dec); + return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRate()); + } + + @Override + public String GetBalance(TangemCard mCard) { + if (!HasBalanceInfo(mCard)) { + return "-- -- -- " + GetBalanceCurrency(mCard); + } + + String output = GetBalanceValue(mCard); + String s = output + " " + GetBalanceCurrency(mCard); + return s; + } + + + public String GetBalanceWithAlter(TangemCard mCard) { + //return GetBalance(mCard) + "\n(" + GetBalanceAlterValue(mCard) + " ETH)"; + return " " + GetBalance(mCard) + "
+ " + GetBalanceAlterValue(mCard) + " ETH for gas"; + } + + public String calculateAddress(TangemCard mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException { + Keccak256 kec = new Keccak256(); + int lenPk = pkUncompressed.length; + if (lenPk < 2) { + throw new IllegalArgumentException("Uncompress public key length is invald"); + } + byte[] cleanKey = new byte[lenPk - 1]; + for (int i = 0; i < cleanKey.length; ++i) { + cleanKey[i] = pkUncompressed[i + 1]; + } + byte[] r = kec.digest(cleanKey); + + byte[] address = new byte[20]; + for (int i = 0; i < 20; ++i) { + address[i] = r[i + 12]; + } + + return String.format("0x%s", BTCUtils.toHex(address)); + } + + @Override + public String ConvertByteArrayToAmount(TangemCard mCard, byte[] bytes) throws Exception { + throw new Exception("Not implemented"); + } + + @Override + public byte[] ConvertAmountToByteArray(TangemCard mCard, String amount) throws Exception { + throw new Exception("Not implemented"); + } + + @Override + public String GetAmountDescription(TangemCard mCard, String amount) throws Exception { + throw new Exception("Not implemented"); + } + + + public String GetAmountEqualentDescriptor(TangemCard mCard, String value) { + BigDecimal d = new BigDecimal(value); + return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRate()); + } + + public String GetFeeEqualentDescriptor(TangemCard mCard, String value) { + BigDecimal d = new BigDecimal(value); + return EthEngine.getAmountEquivalentDescriptionETH(d, mCard.getRateAlter()); + } + + public Uri getShareWalletURIExplorer(TangemCard mCard) { + return Uri.parse("https://etherscan.io/token/" + GetContractAddress(mCard) + "?a=" + mCard.getWallet()); + } + + public Uri getShareWalletURI(TangemCard mCard) { + return Uri.parse("" + mCard.getWallet()); + } + + public boolean CheckUnspentTransaction(TangemCard mCard) { + return true; + } + + public boolean CheckAmountValie(TangemCard mCard, String amountValue, String feeValue, Long minFeeInInternalUnits) { + Long fee = null; + BigDecimal amount = null; + try { + amount = new BigDecimal(GetBalanceAlterValue(mCard));//mCard.InternalUnitsFromString(amountValue); + fee = mCard.InternalUnitsFromString(feeValue); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + if (fee == null || amount == null) + return false; + + if (fee == 0 || amount.compareTo(BigDecimal.ZERO) == 0) + return false; + + + if (fee < minFeeInInternalUnits) + return false; + + + BigDecimal tmpFee = new BigDecimal(feeValue); + BigDecimal tmpAmount = amount; + tmpAmount = tmpAmount.multiply(new BigDecimal("1000000000")); + + if (tmpFee.compareTo(tmpAmount) > 0) + return false; + + return true; + } + + public String EvaluteFeeEquivalent(TangemCard mCard, String fee) { + BigDecimal gweFee = new BigDecimal(fee); + gweFee = gweFee.divide(new BigDecimal("1000000000")); + gweFee = gweFee.setScale(18, RoundingMode.DOWN); + return GetFeeEqualentDescriptor(mCard, gweFee.toString()); + } + + public byte[] Sign(String feeValue, String amountValue, String toValue, TangemCard mCard, CardProtocol protocol) throws Exception { + + BigInteger nonceValue = mCard.GetConfirmTXCount(); + byte[] pbKey = mCard.getWalletPublicKey(); + boolean flag = (mCard.getSigningMethod() == TangemCard.SigningMethod.Sign_Hash_Validated_By_Issuer); + Issuer issuer = mCard.getIssuer(); + + + BigInteger fee = new BigInteger(feeValue, 10); + + BigDecimal amountDecValue = new BigDecimal(amountValue); + + int d = GetTokenDecimals(mCard); + BigDecimal amountDec = new BigDecimal("10"); + amountDec = amountDec.pow(d); + amountDec = amountDecValue.multiply(amountDec); + + //amountDec = amountDec.multiply(new BigDecimal("1000000000")); + + + BigInteger amount = amountDec.toBigInteger(); //new BigInteger(amountValue, 10); + + + //amount = amount.subtract(fee); + + BigInteger nonce = nonceValue; + BigInteger gasPrice = fee.divide(BigInteger.valueOf(21000)); + BigInteger gasLimit = BigInteger.valueOf(60000); + Integer chainId = ETH_Transaction.ChainEnum.Mainnet.getValue(); + BigInteger amountZero = BigInteger.ZERO; + + Long multiplicator = 1000000000L; + + gasPrice = gasPrice.multiply(BigInteger.valueOf(multiplicator)); + + String to = toValue; + + if (to.startsWith("0x") || to.startsWith("0X")) { + to = to.substring(2); + } + + String contractAddress = GetContractAddress(mCard); + + if (contractAddress.startsWith("0x") || contractAddress.startsWith("0X")) { + contractAddress = contractAddress.substring(2); + } + + String amountLeadZero = amount.toString(16); + if (amountLeadZero.startsWith("0x") || amountLeadZero.startsWith("0X")) { + amountLeadZero = amountLeadZero.substring(2); + } + + while (amountLeadZero.length() < 64) { + amountLeadZero = "0" + amountLeadZero; + } + + String cmd = "a9059cbb000000000000000000000000" + to + amountLeadZero; //TODO only for BAT + + + byte[] data = BTCUtils.fromHex(cmd); + ETH_Transaction tx = ETH_Transaction.create(contractAddress, amountZero, nonce, gasPrice, gasLimit, chainId, data); + + byte[][] hashesForSign = new byte[1][]; + byte[] for_hash = tx.getRawHash(); + hashesForSign[0] = for_hash; + + byte[] signFromCard = null; + try { + signFromCard = protocol.run_SignHashes(PINStorage.getPIN2(), hashesForSign, flag, null, issuer).getTLV(TLV.Tag.TAG_Signature).Value; + // TODO slice signFromCard to hashes.length parts + } catch (Exception ex) { + Log.e("ETH", ex.getMessage()); + return null; + } + + LastSignStorage.setLastSignDate(mCard.getWallet(), new Date()); + + BigInteger r = new BigInteger(1, Arrays.copyOfRange(signFromCard, 0, 32)); + BigInteger s = new BigInteger(1, Arrays.copyOfRange(signFromCard, 32, 64)); + s = CryptoUtil.toCanonicalised(s); + + boolean f = ECKey.verify(for_hash, new ECKey.ECDSASignature(r, s), pbKey); + + if (!f) { + Log.e("ETH-CHECK", "Sign Failed."); + } + + tx.signature = new ECDSASignature_ETH(r, s); + int v = tx.BruteRecoveryID2(tx.signature, for_hash, pbKey); + if (v != 27 && v != 28) { + Log.e("ETH", "invalid v"); + return null; + } + tx.signature.v = (byte) v; + Log.e("ETH_v", String.valueOf(v)); + + byte[] realTX = tx.getEncoded(); + return realTX; + } +} diff --git a/app/src/main/java/com/tangem/wallet/Transaction.java b/app/src/main/java/com/tangem/domain/wallet/Transaction.java similarity index 97% rename from app/src/main/java/com/tangem/wallet/Transaction.java rename to app/src/main/java/com/tangem/domain/wallet/Transaction.java index 9cab3f0182..993e54f717 100644 --- a/app/src/main/java/com/tangem/wallet/Transaction.java +++ b/app/src/main/java/com/tangem/domain/wallet/Transaction.java @@ -1,632 +1,630 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ - -import org.spongycastle.jcajce.provider.symmetric.ARC4; - -import java.io.ByteArrayOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Stack; - -@SuppressWarnings("WeakerAccess") -public final class Transaction { - public final int version; - public final Input[] inputs; - public final Output[] outputs; - public final int lockTime; - - public Transaction(byte[] rawBytes) throws BitcoinException { - if (rawBytes == null) { - throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "empty input"); - } - BitcoinInputStream bais = null; - try { - bais = new BitcoinInputStream(rawBytes); - version = bais.readInt32(); - if (version != 1 && version != 2 && version != 3) { - throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unsupported TX version", version); - } - - - int inputsCount = 0; - int first = bais.readByte(); - if(first == 0) - { - int skip = bais.readByte(); - inputsCount = bais.readByte(); - } - else - { - inputsCount = first; - } - //int inputsCount = (int) bais.readVarInt(); TODO: - inputs = new Input[inputsCount]; - for (int i = 0; i < inputsCount; i++) { - OutPoint outPoint = new OutPoint(BTCUtils.reverse(bais.readChars(32)), bais.readInt32()); - byte[] script = bais.readChars((int) bais.readVarInt()); - int sequence = bais.readInt32(); - inputs[i] = new Input(outPoint, new Script(script), sequence); - } - int outputsCount = (int) bais.readVarInt(); - outputs = new Output[outputsCount]; - for (int i = 0; i < outputsCount; i++) { - long value = bais.readInt64(); - long scriptSize = bais.readVarInt(); - if (scriptSize < 0 || scriptSize > 10_000_000) { - throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "Script size for output " + i + - " is strange (" + scriptSize + " bytes)."); - } - byte[] script = bais.readChars((int) scriptSize); - outputs[i] = new Output(value, new Script(script)); - } - lockTime = bais.readInt32(); - } catch (EOFException e) { - throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "TX incomplete"); - } catch (IOException e) { - throw new IllegalArgumentException("Unable to read TX"); - } catch (Error e) { - throw new IllegalArgumentException("Unable to read TX: " + e); - } finally { - if (bais != null) { - try { - bais.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - } - - public Transaction(Input[] inputs, Output[] outputs, int lockTime) { - this.version = 1; - this.inputs = inputs; - this.outputs = outputs; - this.lockTime = lockTime; - } - - public byte[] getBytes() { - BitcoinOutputStream baos = new BitcoinOutputStream(); - try { - baos.writeInt32(version); - baos.writeVarInt(inputs.length); - for (Input input : inputs) { - baos.write(BTCUtils.reverse(input.outPoint.hash)); - baos.writeInt32(input.outPoint.index); - int scriptLen = input.script == null ? 0 : input.script.bytes.length; - baos.writeVarInt(scriptLen); - if (scriptLen > 0) { - baos.write(input.script.bytes); - } - baos.writeInt32(input.sequence); - } - baos.writeVarInt(outputs.length); - for (Output output : outputs) { - baos.writeInt64(output.value); - int scriptLen = output.script == null ? 0 : output.script.bytes.length; - baos.writeVarInt(scriptLen); - if (scriptLen > 0) { - baos.write(output.script.bytes); - } - } - baos.writeInt32(lockTime); - } catch (IOException e) { - e.printStackTrace(); - } finally { - try { - baos.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - return baos.toByteArray(); - - } - - @Override - public String toString() { - return "{" + - "\n\"inputs\":\n" + printAsJsonArray(inputs) + - ",\n\"outputs\":\n" + printAsJsonArray(outputs) + - ",\n\"lockTime\":\"" + lockTime + "\"}\n"; - } - - private String printAsJsonArray(Object[] a) { - if (a == null) { - return "null"; - } - if (a.length == 0) { - return "[]"; - } - int iMax = a.length - 1; - StringBuilder sb = new StringBuilder(); - sb.append('['); - for (int i = 0; ; i++) { - sb.append(String.valueOf(a[i])); - if (i == iMax) - return sb.append(']').toString(); - sb.append(",\n"); - } - } - - public static class Input { - public final OutPoint outPoint; - public final Script script; - public final int sequence; - - public Input(OutPoint outPoint, Script script, int sequence) { - this.outPoint = outPoint; - this.script = script; - this.sequence = sequence; - } - - @Override - public String toString() { - return "{\n\"outPoint\":" + outPoint + ",\n\"script\":\"" + script + "\",\n\"sequence\":\"" + Integer.toHexString(sequence) + "\"\n}\n"; - } - } - - public static class OutPoint { - public final byte[] hash;//32-byte hash of the transaction from which we want to redeem an output - public final int index;//Four-byte field denoting the output index we want to redeem from the transaction with the above hash (output number 2 = output index 1) - - public OutPoint(byte[] hash, int index) { - this.hash = hash; - this.index = index; - } - - @Override - public String toString() { - return "{" + "\"hash\":\"" + BTCUtils.toHex(hash) + "\", \"index\":\"" + index + "\"}"; - } - } - - public static class Output { - public final long value; - public final Script script; - - public Output(long value, Script script) { - this.value = value; - this.script = script; - } - - @Override - public String toString() { - return "{\n\"value\":\"" + value * 1e-8 + "\",\"script\":\"" + script + "\"\n}"; - } - } - - public static final class Script { - - public static class ScriptInvalidException extends Exception { - public ScriptInvalidException() { - } - - public ScriptInvalidException(String s) { - super(s); - } - } - - public static final byte OP_FALSE = 0; - public static final byte OP_TRUE = 0x51; - public static final byte OP_PUSHDATA1 = 0x4c; - public static final byte OP_PUSHDATA2 = 0x4d; - public static final byte OP_PUSHDATA4 = 0x4e; - public static final byte OP_DUP = 0x76;//Duplicates the top stack item. - public static final byte OP_DROP = 0x75; - public static final byte OP_HASH160 = (byte) 0xA9;//The input is hashed twice: first with SHA-256 and then with RIPEMD-160. - public static final byte OP_VERIFY = 0x69;//Marks transaction as invalid if top stack value is not true. True is removed, but false is not. - public static final byte OP_EQUAL = (byte) 0x87;//Returns 1 if the inputs are exactly equal, 0 otherwise. - public static final byte OP_EQUALVERIFY = (byte) 0x88;//Same as OP_EQUAL, but runs OP_VERIFY afterward. - public static final byte OP_CHECKSIG = (byte) 0xAC;//The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. - public static final byte OP_CHECKSIGVERIFY = (byte) 0xAD; - public static final byte OP_NOP = 0x61; - - public static final byte SIGHASH_ALL = 1; - - public final byte[] bytes; - - public Script(byte[] rawBytes) { - bytes = rawBytes; - } - - public Script(byte[] data1, byte[] data2) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(data1.length + data2.length + 2); - try { - writeBytes(data1, baos); - writeBytes(data2, baos); - baos.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } - bytes = baos.toByteArray(); - } - - private static void writeBytes(byte[] data, ByteArrayOutputStream baos) throws IOException { - if (data.length < OP_PUSHDATA1) { - baos.write(data.length); - } else if (data.length < 0xff) { - baos.write(OP_PUSHDATA1); - baos.write(data.length); - } else if (data.length < 0xffff) { - baos.write(OP_PUSHDATA2); - baos.write(data.length & 0xff); - baos.write((data.length >> 8) & 0xff); - } else { - baos.write(OP_PUSHDATA4); - baos.write(data.length & 0xff); - baos.write((data.length >> 8) & 0xff); - baos.write((data.length >> 16) & 0xff); - baos.write((data.length >>> 24) & 0xff); - } - baos.write(data); - } - - public void run(Stack stack) throws ScriptInvalidException { - run(0, null, stack); - } - - public void run(int inputIndex, Transaction tx, Stack stack) throws ScriptInvalidException { - for (int pos = 0; pos < bytes.length; pos++) { - switch (bytes[pos]) { - case OP_NOP: - break; - case OP_DROP: - if (stack.isEmpty()) { - throw new IllegalArgumentException("stack empty on OP_DROP"); - } - stack.pop(); - break; - case OP_DUP: - if (stack.isEmpty()) { - throw new IllegalArgumentException("stack empty on OP_DUP"); - } - stack.push(stack.peek()); - break; - case OP_HASH160: - if (stack.isEmpty()) { - throw new IllegalArgumentException("stack empty on OP_HASH160"); - } - stack.push(CryptoUtil.sha256ripemd160(stack.pop())); - break; - case OP_EQUAL: - case OP_EQUALVERIFY: - if (stack.size() < 2) { - throw new IllegalArgumentException("not enough elements to perform OP_EQUAL"); - } - stack.push(new byte[]{(byte) (Arrays.equals(stack.pop(), stack.pop()) ? 1 : 0)}); - if (bytes[pos] == OP_EQUALVERIFY) { - if (verifyFails(stack)) { - throw new ScriptInvalidException("wrong address"); - } - } - break; - case OP_VERIFY: - if (verifyFails(stack)) { - throw new ScriptInvalidException(); - } - break; - case OP_CHECKSIG: - case OP_CHECKSIGVERIFY: - byte[] publicKey = stack.pop(); - byte[] signatureAndHashType = stack.pop(); - if (signatureAndHashType[signatureAndHashType.length - 1] != SIGHASH_ALL) { - throw new IllegalArgumentException("I cannot check this sig type: " + signatureAndHashType[signatureAndHashType.length - 1]); - } - byte[] signature = new byte[signatureAndHashType.length - 1]; - System.arraycopy(signatureAndHashType, 0, signature, 0, signature.length); - byte[] hash = hashTransaction(inputIndex, bytes, tx); - //boolean valid = BTCUtils.verify(publicKey, signature, hash); - if (bytes[pos] == OP_CHECKSIG) { - stack.push(new byte[]{(byte) (1)}); - } else { - if (verifyFails(stack)) { - throw new ScriptInvalidException("Bad signature"); - } - if (!stack.empty()) { - throw new ScriptInvalidException("Bad signature - superfluous scriptSig operations"); - } - } - break; - case OP_FALSE: - stack.push(new byte[]{0}); - break; - case OP_TRUE: - stack.push(new byte[]{1}); - break; - default: - int op = bytes[pos] & 0xff; - int len; - if (op < OP_PUSHDATA1) { - len = op; - byte[] data = new byte[len]; - System.arraycopy(bytes, pos + 1, data, 0, len); - stack.push(data); - pos += data.length; - } else if (op == OP_PUSHDATA1) { - len = bytes[pos + 1] & 0xff; - byte[] data = new byte[len]; - System.arraycopy(bytes, pos + 1, data, 0, len); - stack.push(data); - pos += 1 + data.length; - } else { - throw new IllegalArgumentException("I cannot read this data: " + Integer.toHexString(bytes[pos])); - } - break; - } - } - } - - public static byte[] hashTransaction(int inputIndex, byte[] subscript, Transaction tx) { - Input[] unsignedInputs = new Input[tx.inputs.length]; - for (int i = 0; i < tx.inputs.length; i++) { - Input txInput = tx.inputs[i]; - if (i == inputIndex) { - unsignedInputs[i] = new Input(txInput.outPoint, new Script(subscript), txInput.sequence); - } else { - unsignedInputs[i] = new Input(txInput.outPoint, new Script(new byte[0]), txInput.sequence); - } - } - Transaction unsignedTransaction = new Transaction(unsignedInputs, tx.outputs, tx.lockTime); - return hashTransactionForSigning(unsignedTransaction); - } - - public static byte[] hashTransactionForSigning(Transaction unsignedTransaction) { - byte[] txUnsignedBytes = unsignedTransaction.getBytes(); - BitcoinOutputStream baos = new BitcoinOutputStream(); - try { - baos.write(txUnsignedBytes); - baos.writeInt32(Script.SIGHASH_ALL); - baos.close(); - } catch (Exception e) { - throw new RuntimeException(e); - } - return CryptoUtil.doubleSha256(baos.toByteArray()); - } - - public static boolean verifyFails(Stack stack) { - byte[] input; - boolean valid; - input = stack.pop(); - if (input.length == 0 || (input.length == 1 && input[0] == OP_FALSE)) { - //false - stack.push(new byte[]{OP_FALSE}); - valid = false; - } else { - //true - valid = true; - } - return !valid; - } - - - @Override - public String toString() { - return convertBytesToReadableString(bytes); - } - - //converts something like "OP_DUP OP_HASH160 ba507bae8f1643d2556000ca26b9301b9069dc6b OP_EQUALVERIFY OP_CHECKSIG" into bytes - public static byte[] convertReadableStringToBytes(String readableString) { - String[] tokens = readableString.trim().split("\\s+"); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - for (String token : tokens) { - switch (token) { - case "OP_NOP": - os.write(OP_NOP); - break; - case "OP_DROP": - os.write(OP_DROP); - break; - case "OP_DUP": - os.write(OP_DUP); - break; - case "OP_HASH160": - os.write(OP_HASH160); - break; - case "OP_EQUAL": - os.write(OP_EQUAL); - break; - case "OP_EQUALVERIFY": - os.write(OP_EQUALVERIFY); - break; - case "OP_VERIFY": - os.write(OP_VERIFY); - break; - case "OP_CHECKSIG": - os.write(OP_CHECKSIG); - break; - case "OP_CHECKSIGVERIFY": - os.write(OP_CHECKSIGVERIFY); - break; - case "OP_FALSE": - os.write(OP_FALSE); - break; - case "OP_TRUE": - os.write(OP_TRUE); - break; - default: - if (token.startsWith("OP_")) { - throw new IllegalArgumentException("I don't know this operation: " + token); - } - byte[] data = BTCUtils.fromHex(token); - if (data == null) { - throw new IllegalArgumentException("I don't know what's this: " + token); - } - if (data.length < OP_PUSHDATA1) { - os.write(data.length); - try { - os.write(data); - } catch (IOException e) { - throw new RuntimeException("ByteArrayOutputStream behaves weird: " + e); - } - } else if (data.length <= 255) { - os.write(OP_PUSHDATA1); - os.write(data.length); - try { - os.write(data); - } catch (IOException e) { - throw new RuntimeException("ByteArrayOutputStream behaves weird: " + e); - } - } else { - throw new IllegalArgumentException("OP_PUSHDATA2 & OP_PUSHDATA4 are not supported"); - } - break; - } - } - try { - os.close(); - } catch (IOException e) { - e.printStackTrace(); - } - return os.toByteArray(); - } - - public static String convertBytesToReadableString(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (int pos = 0; pos < bytes.length; pos++) { - if (sb.length() > 0) { - sb.append(' '); - } - switch (bytes[pos]) { - case OP_NOP: - sb.append("OP_NOP"); - break; - case OP_DROP: - sb.append("OP_DROP"); - break; - case OP_DUP: - sb.append("OP_DUP"); - break; - case OP_HASH160: - sb.append("OP_HASH160"); - break; - case OP_EQUAL: - sb.append("OP_EQUAL"); - break; - case OP_EQUALVERIFY: - sb.append("OP_EQUALVERIFY"); - break; - case OP_VERIFY: - sb.append("OP_VERIFY"); - break; - case OP_CHECKSIG: - sb.append("OP_CHECKSIG"); - break; - case OP_CHECKSIGVERIFY: - sb.append("OP_CHECKSIGVERIFY"); - break; - case OP_FALSE: - sb.append("OP_FALSE"); - break; - case OP_TRUE: - sb.append("OP_TRUE"); - break; - default: - int op = bytes[pos] & 0xff; - int len; - if (op < OP_PUSHDATA1) { - len = op; - byte[] data = new byte[len]; - System.arraycopy(bytes, pos + 1, data, 0, len); - sb.append(BTCUtils.toHex(data)); - pos += data.length; - } else if (op == OP_PUSHDATA1) { - len = bytes[pos + 1] & 0xff; - byte[] data = new byte[len]; - System.arraycopy(bytes, pos + 1, data, 0, len);//FIXME I suspect there is off by one error... - sb.append(BTCUtils.toHex(data)); - pos += 1 + data.length; - } else { - throw new IllegalArgumentException("I cannot read this data: " + Integer.toHexString(bytes[pos]) + " at " + pos); - } - break; - } - } - return sb.toString(); - } - - @Override - public boolean equals(Object o) { - return this == o || !(o == null || getClass() != o.getClass()) && Arrays.equals(bytes, ((Script) o).bytes); - } - - @Override - public int hashCode() { - return Arrays.hashCode(bytes); - } - - public static Script buildOutput(String address) throws BitcoinException { - //noinspection TryWithIdenticalCatches - byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); - if (addressWithCheckSumAndNetworkCode[0] == 0 || addressWithCheckSumAndNetworkCode[0] == 111) { - return buildOutputP2H(address); - } - - if(addressWithCheckSumAndNetworkCode[0] == 5 || addressWithCheckSumAndNetworkCode[0] == (byte)0xc4) { - return buildOutputP2SH(address); - } - - throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); - } - public static Script buildOutputP2SH(String address) throws BitcoinException { - try { - byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); - if (addressWithCheckSumAndNetworkCode[0] != 5 && addressWithCheckSumAndNetworkCode[0] != (byte)0xc4) { - throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); - } - - byte[] bareAddress = new byte[20]; - System.arraycopy(addressWithCheckSumAndNetworkCode, 1, bareAddress, 0, bareAddress.length); - - ByteArrayOutputStream buf = new ByteArrayOutputStream(23); - buf.write(OP_HASH160); - writeBytes(bareAddress, buf); - buf.write(OP_EQUAL); - return new Script(buf.toByteArray()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - - public static Script buildOutputP2H(String address) throws BitcoinException { - //noinspection TryWithIdenticalCatches - try { - byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); - if (addressWithCheckSumAndNetworkCode[0] != 0 && addressWithCheckSumAndNetworkCode[0] != 111) { - throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); - } - - byte[] bareAddress = new byte[20]; - System.arraycopy(addressWithCheckSumAndNetworkCode, 1, bareAddress, 0, bareAddress.length); - - MessageDigest digestSha = MessageDigest.getInstance("SHA-256"); - digestSha.update(addressWithCheckSumAndNetworkCode, 0, addressWithCheckSumAndNetworkCode.length - 4); - - byte[] calculatedDigest = digestSha.digest(digestSha.digest()); - for (int i = 0; i < 4; i++) { - if (calculatedDigest[i] != addressWithCheckSumAndNetworkCode[addressWithCheckSumAndNetworkCode.length - 4 + i]) { - throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "Bad address", address); - } - } - - ByteArrayOutputStream buf = new ByteArrayOutputStream(25); - buf.write(OP_DUP); - buf.write(OP_HASH160); - writeBytes(bareAddress, buf); - buf.write(OP_EQUALVERIFY); - buf.write(OP_CHECKSIG); - return new Script(buf.toByteArray()); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } -} +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +import java.io.ByteArrayOutputStream; +import java.io.EOFException; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; +import java.util.Stack; + +@SuppressWarnings("WeakerAccess") +public final class Transaction { + public final int version; + public final Input[] inputs; + public final Output[] outputs; + public final int lockTime; + + public Transaction(byte[] rawBytes) throws BitcoinException { + if (rawBytes == null) { + throw new BitcoinException(BitcoinException.ERR_NO_INPUT, "empty input"); + } + BitcoinInputStream bais = null; + try { + bais = new BitcoinInputStream(rawBytes); + version = bais.readInt32(); + if (version != 1 && version != 2 && version != 3) { + throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unsupported TX version", version); + } + + + int inputsCount = 0; + int first = bais.readByte(); + if(first == 0) + { + int skip = bais.readByte(); + inputsCount = bais.readByte(); + } + else + { + inputsCount = first; + } + //int inputsCount = (int) bais.readVarInt(); TODO: + inputs = new Input[inputsCount]; + for (int i = 0; i < inputsCount; i++) { + OutPoint outPoint = new OutPoint(BTCUtils.reverse(bais.readChars(32)), bais.readInt32()); + byte[] script = bais.readChars((int) bais.readVarInt()); + int sequence = bais.readInt32(); + inputs[i] = new Input(outPoint, new Script(script), sequence); + } + int outputsCount = (int) bais.readVarInt(); + outputs = new Output[outputsCount]; + for (int i = 0; i < outputsCount; i++) { + long value = bais.readInt64(); + long scriptSize = bais.readVarInt(); + if (scriptSize < 0 || scriptSize > 10_000_000) { + throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "Script size for output " + i + + " is strange (" + scriptSize + " bytes)."); + } + byte[] script = bais.readChars((int) scriptSize); + outputs[i] = new Output(value, new Script(script)); + } + lockTime = bais.readInt32(); + } catch (EOFException e) { + throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "TX incomplete"); + } catch (IOException e) { + throw new IllegalArgumentException("Unable to read TX"); + } catch (Error e) { + throw new IllegalArgumentException("Unable to read TX: " + e); + } finally { + if (bais != null) { + try { + bais.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + } + + public Transaction(Input[] inputs, Output[] outputs, int lockTime) { + this.version = 1; + this.inputs = inputs; + this.outputs = outputs; + this.lockTime = lockTime; + } + + public byte[] getBytes() { + BitcoinOutputStream baos = new BitcoinOutputStream(); + try { + baos.writeInt32(version); + baos.writeVarInt(inputs.length); + for (Input input : inputs) { + baos.write(BTCUtils.reverse(input.outPoint.hash)); + baos.writeInt32(input.outPoint.index); + int scriptLen = input.script == null ? 0 : input.script.bytes.length; + baos.writeVarInt(scriptLen); + if (scriptLen > 0) { + baos.write(input.script.bytes); + } + baos.writeInt32(input.sequence); + } + baos.writeVarInt(outputs.length); + for (Output output : outputs) { + baos.writeInt64(output.value); + int scriptLen = output.script == null ? 0 : output.script.bytes.length; + baos.writeVarInt(scriptLen); + if (scriptLen > 0) { + baos.write(output.script.bytes); + } + } + baos.writeInt32(lockTime); + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + baos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + return baos.toByteArray(); + + } + + @Override + public String toString() { + return "{" + + "\n\"inputs\":\n" + printAsJsonArray(inputs) + + ",\n\"outputs\":\n" + printAsJsonArray(outputs) + + ",\n\"lockTime\":\"" + lockTime + "\"}\n"; + } + + private String printAsJsonArray(Object[] a) { + if (a == null) { + return "null"; + } + if (a.length == 0) { + return "[]"; + } + int iMax = a.length - 1; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; ; i++) { + sb.append(String.valueOf(a[i])); + if (i == iMax) + return sb.append(']').toString(); + sb.append(",\n"); + } + } + + public static class Input { + public final OutPoint outPoint; + public final Script script; + public final int sequence; + + public Input(OutPoint outPoint, Script script, int sequence) { + this.outPoint = outPoint; + this.script = script; + this.sequence = sequence; + } + + @Override + public String toString() { + return "{\n\"outPoint\":" + outPoint + ",\n\"script\":\"" + script + "\",\n\"sequence\":\"" + Integer.toHexString(sequence) + "\"\n}\n"; + } + } + + public static class OutPoint { + public final byte[] hash;//32-byte hash of the transaction from which we want to redeem an output + public final int index;//Four-byte field denoting the output index we want to redeem from the transaction with the above hash (output number 2 = output index 1) + + public OutPoint(byte[] hash, int index) { + this.hash = hash; + this.index = index; + } + + @Override + public String toString() { + return "{" + "\"hash\":\"" + BTCUtils.toHex(hash) + "\", \"index\":\"" + index + "\"}"; + } + } + + public static class Output { + public final long value; + public final Script script; + + public Output(long value, Script script) { + this.value = value; + this.script = script; + } + + @Override + public String toString() { + return "{\n\"value\":\"" + value * 1e-8 + "\",\"script\":\"" + script + "\"\n}"; + } + } + + public static final class Script { + + public static class ScriptInvalidException extends Exception { + public ScriptInvalidException() { + } + + public ScriptInvalidException(String s) { + super(s); + } + } + + public static final byte OP_FALSE = 0; + public static final byte OP_TRUE = 0x51; + public static final byte OP_PUSHDATA1 = 0x4c; + public static final byte OP_PUSHDATA2 = 0x4d; + public static final byte OP_PUSHDATA4 = 0x4e; + public static final byte OP_DUP = 0x76;//Duplicates the top stack item. + public static final byte OP_DROP = 0x75; + public static final byte OP_HASH160 = (byte) 0xA9;//The input is hashed twice: first with SHA-256 and then with RIPEMD-160. + public static final byte OP_VERIFY = 0x69;//Marks transaction as invalid if top stack value is not true. True is removed, but false is not. + public static final byte OP_EQUAL = (byte) 0x87;//Returns 1 if the inputs are exactly equal, 0 otherwise. + public static final byte OP_EQUALVERIFY = (byte) 0x88;//Same as OP_EQUAL, but runs OP_VERIFY afterward. + public static final byte OP_CHECKSIG = (byte) 0xAC;//The entire transaction's outputs, inputs, and script (from the most recently-executed OP_CODESEPARATOR to the end) are hashed. The signature used by OP_CHECKSIG must be a valid signature for this hash and public key. If it is, 1 is returned, 0 otherwise. + public static final byte OP_CHECKSIGVERIFY = (byte) 0xAD; + public static final byte OP_NOP = 0x61; + + public static final byte SIGHASH_ALL = 1; + + public final byte[] bytes; + + public Script(byte[] rawBytes) { + bytes = rawBytes; + } + + public Script(byte[] data1, byte[] data2) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(data1.length + data2.length + 2); + try { + writeBytes(data1, baos); + writeBytes(data2, baos); + baos.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + bytes = baos.toByteArray(); + } + + private static void writeBytes(byte[] data, ByteArrayOutputStream baos) throws IOException { + if (data.length < OP_PUSHDATA1) { + baos.write(data.length); + } else if (data.length < 0xff) { + baos.write(OP_PUSHDATA1); + baos.write(data.length); + } else if (data.length < 0xffff) { + baos.write(OP_PUSHDATA2); + baos.write(data.length & 0xff); + baos.write((data.length >> 8) & 0xff); + } else { + baos.write(OP_PUSHDATA4); + baos.write(data.length & 0xff); + baos.write((data.length >> 8) & 0xff); + baos.write((data.length >> 16) & 0xff); + baos.write((data.length >>> 24) & 0xff); + } + baos.write(data); + } + + public void run(Stack stack) throws ScriptInvalidException { + run(0, null, stack); + } + + public void run(int inputIndex, Transaction tx, Stack stack) throws ScriptInvalidException { + for (int pos = 0; pos < bytes.length; pos++) { + switch (bytes[pos]) { + case OP_NOP: + break; + case OP_DROP: + if (stack.isEmpty()) { + throw new IllegalArgumentException("stack empty on OP_DROP"); + } + stack.pop(); + break; + case OP_DUP: + if (stack.isEmpty()) { + throw new IllegalArgumentException("stack empty on OP_DUP"); + } + stack.push(stack.peek()); + break; + case OP_HASH160: + if (stack.isEmpty()) { + throw new IllegalArgumentException("stack empty on OP_HASH160"); + } + stack.push(CryptoUtil.sha256ripemd160(stack.pop())); + break; + case OP_EQUAL: + case OP_EQUALVERIFY: + if (stack.size() < 2) { + throw new IllegalArgumentException("not enough elements to perform OP_EQUAL"); + } + stack.push(new byte[]{(byte) (Arrays.equals(stack.pop(), stack.pop()) ? 1 : 0)}); + if (bytes[pos] == OP_EQUALVERIFY) { + if (verifyFails(stack)) { + throw new ScriptInvalidException("wrong address"); + } + } + break; + case OP_VERIFY: + if (verifyFails(stack)) { + throw new ScriptInvalidException(); + } + break; + case OP_CHECKSIG: + case OP_CHECKSIGVERIFY: + byte[] publicKey = stack.pop(); + byte[] signatureAndHashType = stack.pop(); + if (signatureAndHashType[signatureAndHashType.length - 1] != SIGHASH_ALL) { + throw new IllegalArgumentException("I cannot check this sig type: " + signatureAndHashType[signatureAndHashType.length - 1]); + } + byte[] signature = new byte[signatureAndHashType.length - 1]; + System.arraycopy(signatureAndHashType, 0, signature, 0, signature.length); + byte[] hash = hashTransaction(inputIndex, bytes, tx); + //boolean valid = BTCUtils.verify(publicKey, signature, hash); + if (bytes[pos] == OP_CHECKSIG) { + stack.push(new byte[]{(byte) (1)}); + } else { + if (verifyFails(stack)) { + throw new ScriptInvalidException("Bad signature"); + } + if (!stack.empty()) { + throw new ScriptInvalidException("Bad signature - superfluous scriptSig operations"); + } + } + break; + case OP_FALSE: + stack.push(new byte[]{0}); + break; + case OP_TRUE: + stack.push(new byte[]{1}); + break; + default: + int op = bytes[pos] & 0xff; + int len; + if (op < OP_PUSHDATA1) { + len = op; + byte[] data = new byte[len]; + System.arraycopy(bytes, pos + 1, data, 0, len); + stack.push(data); + pos += data.length; + } else if (op == OP_PUSHDATA1) { + len = bytes[pos + 1] & 0xff; + byte[] data = new byte[len]; + System.arraycopy(bytes, pos + 1, data, 0, len); + stack.push(data); + pos += 1 + data.length; + } else { + throw new IllegalArgumentException("I cannot read this data: " + Integer.toHexString(bytes[pos])); + } + break; + } + } + } + + public static byte[] hashTransaction(int inputIndex, byte[] subscript, Transaction tx) { + Input[] unsignedInputs = new Input[tx.inputs.length]; + for (int i = 0; i < tx.inputs.length; i++) { + Input txInput = tx.inputs[i]; + if (i == inputIndex) { + unsignedInputs[i] = new Input(txInput.outPoint, new Script(subscript), txInput.sequence); + } else { + unsignedInputs[i] = new Input(txInput.outPoint, new Script(new byte[0]), txInput.sequence); + } + } + Transaction unsignedTransaction = new Transaction(unsignedInputs, tx.outputs, tx.lockTime); + return hashTransactionForSigning(unsignedTransaction); + } + + public static byte[] hashTransactionForSigning(Transaction unsignedTransaction) { + byte[] txUnsignedBytes = unsignedTransaction.getBytes(); + BitcoinOutputStream baos = new BitcoinOutputStream(); + try { + baos.write(txUnsignedBytes); + baos.writeInt32(Script.SIGHASH_ALL); + baos.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + return CryptoUtil.doubleSha256(baos.toByteArray()); + } + + public static boolean verifyFails(Stack stack) { + byte[] input; + boolean valid; + input = stack.pop(); + if (input.length == 0 || (input.length == 1 && input[0] == OP_FALSE)) { + //false + stack.push(new byte[]{OP_FALSE}); + valid = false; + } else { + //true + valid = true; + } + return !valid; + } + + + @Override + public String toString() { + return convertBytesToReadableString(bytes); + } + + //converts something like "OP_DUP OP_HASH160 ba507bae8f1643d2556000ca26b9301b9069dc6b OP_EQUALVERIFY OP_CHECKSIG" into bytes + public static byte[] convertReadableStringToBytes(String readableString) { + String[] tokens = readableString.trim().split("\\s+"); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + for (String token : tokens) { + switch (token) { + case "OP_NOP": + os.write(OP_NOP); + break; + case "OP_DROP": + os.write(OP_DROP); + break; + case "OP_DUP": + os.write(OP_DUP); + break; + case "OP_HASH160": + os.write(OP_HASH160); + break; + case "OP_EQUAL": + os.write(OP_EQUAL); + break; + case "OP_EQUALVERIFY": + os.write(OP_EQUALVERIFY); + break; + case "OP_VERIFY": + os.write(OP_VERIFY); + break; + case "OP_CHECKSIG": + os.write(OP_CHECKSIG); + break; + case "OP_CHECKSIGVERIFY": + os.write(OP_CHECKSIGVERIFY); + break; + case "OP_FALSE": + os.write(OP_FALSE); + break; + case "OP_TRUE": + os.write(OP_TRUE); + break; + default: + if (token.startsWith("OP_")) { + throw new IllegalArgumentException("I don't know this operation: " + token); + } + byte[] data = BTCUtils.fromHex(token); + if (data == null) { + throw new IllegalArgumentException("I don't know what's this: " + token); + } + if (data.length < OP_PUSHDATA1) { + os.write(data.length); + try { + os.write(data); + } catch (IOException e) { + throw new RuntimeException("ByteArrayOutputStream behaves weird: " + e); + } + } else if (data.length <= 255) { + os.write(OP_PUSHDATA1); + os.write(data.length); + try { + os.write(data); + } catch (IOException e) { + throw new RuntimeException("ByteArrayOutputStream behaves weird: " + e); + } + } else { + throw new IllegalArgumentException("OP_PUSHDATA2 & OP_PUSHDATA4 are not supported"); + } + break; + } + } + try { + os.close(); + } catch (IOException e) { + e.printStackTrace(); + } + return os.toByteArray(); + } + + public static String convertBytesToReadableString(byte[] bytes) { + StringBuilder sb = new StringBuilder(); + for (int pos = 0; pos < bytes.length; pos++) { + if (sb.length() > 0) { + sb.append(' '); + } + switch (bytes[pos]) { + case OP_NOP: + sb.append("OP_NOP"); + break; + case OP_DROP: + sb.append("OP_DROP"); + break; + case OP_DUP: + sb.append("OP_DUP"); + break; + case OP_HASH160: + sb.append("OP_HASH160"); + break; + case OP_EQUAL: + sb.append("OP_EQUAL"); + break; + case OP_EQUALVERIFY: + sb.append("OP_EQUALVERIFY"); + break; + case OP_VERIFY: + sb.append("OP_VERIFY"); + break; + case OP_CHECKSIG: + sb.append("OP_CHECKSIG"); + break; + case OP_CHECKSIGVERIFY: + sb.append("OP_CHECKSIGVERIFY"); + break; + case OP_FALSE: + sb.append("OP_FALSE"); + break; + case OP_TRUE: + sb.append("OP_TRUE"); + break; + default: + int op = bytes[pos] & 0xff; + int len; + if (op < OP_PUSHDATA1) { + len = op; + byte[] data = new byte[len]; + System.arraycopy(bytes, pos + 1, data, 0, len); + sb.append(BTCUtils.toHex(data)); + pos += data.length; + } else if (op == OP_PUSHDATA1) { + len = bytes[pos + 1] & 0xff; + byte[] data = new byte[len]; + System.arraycopy(bytes, pos + 1, data, 0, len);//FIXME I suspect there is off by one error... + sb.append(BTCUtils.toHex(data)); + pos += 1 + data.length; + } else { + throw new IllegalArgumentException("I cannot read this data: " + Integer.toHexString(bytes[pos]) + " at " + pos); + } + break; + } + } + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + return this == o || !(o == null || getClass() != o.getClass()) && Arrays.equals(bytes, ((Script) o).bytes); + } + + @Override + public int hashCode() { + return Arrays.hashCode(bytes); + } + + public static Script buildOutput(String address) throws BitcoinException { + //noinspection TryWithIdenticalCatches + byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); + if (addressWithCheckSumAndNetworkCode[0] == 0 || addressWithCheckSumAndNetworkCode[0] == 111) { + return buildOutputP2H(address); + } + + if(addressWithCheckSumAndNetworkCode[0] == 5 || addressWithCheckSumAndNetworkCode[0] == (byte)0xc4) { + return buildOutputP2SH(address); + } + + throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); + } + public static Script buildOutputP2SH(String address) throws BitcoinException { + try { + byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); + if (addressWithCheckSumAndNetworkCode[0] != 5 && addressWithCheckSumAndNetworkCode[0] != (byte)0xc4) { + throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); + } + + byte[] bareAddress = new byte[20]; + System.arraycopy(addressWithCheckSumAndNetworkCode, 1, bareAddress, 0, bareAddress.length); + + ByteArrayOutputStream buf = new ByteArrayOutputStream(23); + buf.write(OP_HASH160); + writeBytes(bareAddress, buf); + buf.write(OP_EQUAL); + return new Script(buf.toByteArray()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + + public static Script buildOutputP2H(String address) throws BitcoinException { + //noinspection TryWithIdenticalCatches + try { + byte[] addressWithCheckSumAndNetworkCode = Base58.decodeBase58(address); + if (addressWithCheckSumAndNetworkCode[0] != 0 && addressWithCheckSumAndNetworkCode[0] != 111) { + throw new BitcoinException(BitcoinException.ERR_UNSUPPORTED, "Unknown address type", address); + } + + byte[] bareAddress = new byte[20]; + System.arraycopy(addressWithCheckSumAndNetworkCode, 1, bareAddress, 0, bareAddress.length); + + MessageDigest digestSha = MessageDigest.getInstance("SHA-256"); + digestSha.update(addressWithCheckSumAndNetworkCode, 0, addressWithCheckSumAndNetworkCode.length - 4); + + byte[] calculatedDigest = digestSha.digest(digestSha.digest()); + for (int i = 0; i < 4; i++) { + if (calculatedDigest[i] != addressWithCheckSumAndNetworkCode[addressWithCheckSumAndNetworkCode.length - 4 + i]) { + throw new BitcoinException(BitcoinException.ERR_BAD_FORMAT, "Bad address", address); + } + } + + ByteArrayOutputStream buf = new ByteArrayOutputStream(25); + buf.write(OP_DUP); + buf.write(OP_HASH160); + writeBytes(bareAddress, buf); + buf.write(OP_EQUALVERIFY); + buf.write(OP_CHECKSIG); + return new Script(buf.toByteArray()); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } +} diff --git a/app/src/main/java/com/tangem/wallet/UnspentOutputInfo.java b/app/src/main/java/com/tangem/domain/wallet/UnspentOutputInfo.java similarity index 93% rename from app/src/main/java/com/tangem/wallet/UnspentOutputInfo.java rename to app/src/main/java/com/tangem/domain/wallet/UnspentOutputInfo.java index fdf0788adc..a9d12d0170 100644 --- a/app/src/main/java/com/tangem/wallet/UnspentOutputInfo.java +++ b/app/src/main/java/com/tangem/domain/wallet/UnspentOutputInfo.java @@ -1,28 +1,28 @@ -package com.tangem.wallet; - -/** - * Created by Ilia on 29.09.2017. - */ - -@SuppressWarnings("WeakerAccess") -public class UnspentOutputInfo { - public final byte[] txHash; - public final Transaction.Script script; - public final long value; - public final int outputIndex; - public final long confirmations; - public String txHashForBuild; - public byte[] scriptForBuild; - public byte[] bodyDoubleHash; - public byte[] bodyHash; - - public UnspentOutputInfo(byte[] txHash, Transaction.Script script, long value, int outputIndex, long confirmations, String hashForBuild, byte[] sign) { - this.txHash = txHash; - this.script = script; - this.value = value; - this.outputIndex = outputIndex; - this.confirmations = confirmations; - this.txHashForBuild = hashForBuild; - this.scriptForBuild = sign; - } +package com.tangem.domain.wallet; + +/** + * Created by Ilia on 29.09.2017. + */ + +@SuppressWarnings("WeakerAccess") +public class UnspentOutputInfo { + public final byte[] txHash; + public final Transaction.Script script; + public final long value; + public final int outputIndex; + public final long confirmations; + public String txHashForBuild; + public byte[] scriptForBuild; + public byte[] bodyDoubleHash; + public byte[] bodyHash; + + public UnspentOutputInfo(byte[] txHash, Transaction.Script script, long value, int outputIndex, long confirmations, String hashForBuild, byte[] sign) { + this.txHash = txHash; + this.script = script; + this.value = value; + this.outputIndex = outputIndex; + this.confirmations = confirmations; + this.txHashForBuild = hashForBuild; + this.scriptForBuild = sign; + } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/activity/CardInfoActivity.java b/app/src/main/java/com/tangem/presentation/activity/CardInfoActivity.java index 067a3d8d61..751c84d00b 100644 --- a/app/src/main/java/com/tangem/presentation/activity/CardInfoActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/CardInfoActivity.java @@ -10,8 +10,8 @@ import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; +import com.tangem.domain.wallet.TangemCard; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import com.tangem.presentation.fragment.WalletInfoFragment; public class CardInfoActivity extends AppCompatActivity implements WalletInfoFragment.OnFragmentInteractionListener { @@ -32,7 +32,7 @@ public class CardInfoActivity extends AppCompatActivity implements WalletInfoFra private ViewPager mViewPager; - private Tangem_Card mCard; + private TangemCard mCard; @Override protected void onCreate(Bundle savedInstanceState) { @@ -51,7 +51,7 @@ public class CardInfoActivity extends AppCompatActivity implements WalletInfoFra tabLayout.setupWithViewPager(mViewPager); String UID = getIntent().getStringExtra("UID"); - mCard = new Tangem_Card(UID); + mCard = new TangemCard(UID); mCard.LoadFromBundle(getIntent().getBundleExtra("Card")); } diff --git a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java index 6b4bf0ac08..98980a0b9c 100644 --- a/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/ConfirmPaymentActivity.java @@ -22,25 +22,25 @@ import android.widget.RadioGroup; import android.widget.TextView; import android.widget.Toast; +import com.tangem.data.network.request.ElectrumRequest; 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.data.network.request.Electrum_Request; -import com.tangem.data.network.task.Electrum_Task; -import com.tangem.wallet.Fee_Request; -import com.tangem.data.network.task.Fee_Task; -import com.tangem.wallet.FormatUtil; -import com.tangem.wallet.Infura_Request; -import com.tangem.data.network.task.Infura_Task; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; +import com.tangem.domain.wallet.BTCUtils; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.domain.wallet.DerEncodingUtil; +import com.tangem.data.network.task.ElectrumTask; +import com.tangem.data.network.request.FeeRequest; +import com.tangem.data.network.task.FeeTask; +import com.tangem.domain.wallet.FormatUtil; +import com.tangem.domain.wallet.Infura_Request; +import com.tangem.data.network.task.InfuraTask; import com.tangem.wallet.R; -import com.tangem.wallet.SharedData; -import com.tangem.wallet.Tangem_Card; -import com.tangem.wallet.Transaction; -import com.tangem.wallet.UnspentOutputInfo; +import com.tangem.domain.wallet.SharedData; +import com.tangem.domain.wallet.Transaction; +import com.tangem.domain.wallet.UnspentOutputInfo; import org.json.JSONException; @@ -65,7 +65,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap EditText etAmount; EditText etFee; ImageView ivCamera; - Tangem_Card mCard; + TangemCard mCard; RadioGroup rgFee; String minFee = null, maxFee = null, normalFee = null; Long minFeeInInternalUnits = 0L; @@ -83,7 +83,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap MainActivity.commonInit(getApplicationContext()); mNfcManager = new NfcManager(this, this); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); progressBar = findViewById(R.id.progressBar); @@ -269,8 +269,8 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap //ConnectTask connectTaskEx = new ConnectTask(Blockchain.getNextServiceHost(mCard), Blockchain.getNextServicePort(mCard), data); ConnectTask connectTaskEx = new ConnectTask(nodeAddress, nodePort, data); - //connectTaskEx.execute(Electrum_Request.CheckBalance(mCard.getWallet())); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(mCard.getWallet())); + //connectTaskEx.execute(ElectrumRequest.CheckBalance(mCard.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet())); } String nodeAddress = engineCoin.GetNode(mCard); @@ -279,7 +279,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap //ConnectTask connectTask = new ConnectTask(Blockchain.getServiceHost(mCard), Blockchain.getServicePort(mCard)); - connectTask.execute(/*Electrum_Request.CheckBalance(mCard.getWallet()), */Electrum_Request.GetFee(mCard.getWallet())); + connectTask.execute(/*ElectrumRequest.CheckBalance(mCard.getWallet()), */ElectrumRequest.GetFee(mCard.getWallet())); int calcSize = 256; try { @@ -295,9 +295,9 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap ConnectFeeTask feeTask = new ConnectFeeTask(sharedFee); - feeTask.execute(Fee_Request.GetFee(mCard.getWallet(), calcSize, Fee_Request.NORMAL), - Fee_Request.GetFee(mCard.getWallet(), calcSize, Fee_Request.MINIMAL), - Fee_Request.GetFee(mCard.getWallet(), calcSize, Fee_Request.PRIORITY)); + feeTask.execute(FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.NORMAL), + FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.MINIMAL), + FeeRequest.GetFee(mCard.getWallet(), calcSize, FeeRequest.PRIORITY)); } } @@ -322,7 +322,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_SIGN_PAYMENT) { if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) { - Tangem_Card updatedCard = new Tangem_Card(data.getStringExtra("UID")); + TangemCard updatedCard = new TangemCard(data.getStringExtra("UID")); updatedCard.LoadFromBundle(data.getBundleExtra("Card")); mCard = updatedCard; } @@ -377,7 +377,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap byte[] pbComprKey = mCard.getWalletPublicKeyRar(); // Build script for our address - List rawTxList = mCard.getUnspentTransactions(); + List rawTxList = mCard.getUnspentTransactions(); byte[] outputScriptWeAreAbleToSpend = Transaction.Script.buildOutput(myAddress).bytes; // Collect unspent @@ -437,7 +437,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap return realTX.length; } - private class ConnectTask extends Electrum_Task { + private class ConnectTask extends ElectrumTask { public ConnectTask(String host, int port) { super(host, port); } @@ -452,12 +452,12 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap } @Override - protected void onPostExecute(List requests) { + protected void onPostExecute(List requests) { super.onPostExecute(requests); - for (Electrum_Request request : requests) { + for (ElectrumRequest request : requests) { try { if (request.error == null) { - if (request.isMethod(Electrum_Request.METHOD_GetBalance)) { + if (request.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { etFee.setText("--"); @@ -490,7 +490,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap FinishActivityWithError(Activity.RESULT_CANCELED, "Cannot check balance! No connection with blockchain nodes"); } } - } else if (request.isMethod(Electrum_Request.METHOD_GetFee)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetFee)) { if (request.getResultString() == "-1") { etFee.setText("3"); } @@ -526,7 +526,7 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap } } - private class ETHRequestTask extends Infura_Task { + private class ETHRequestTask extends InfuraTask { ETHRequestTask(Blockchain blockchain) { super(blockchain); } @@ -577,15 +577,15 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap } } - private class ConnectFeeTask extends Fee_Task { + private class ConnectFeeTask extends FeeTask { public ConnectFeeTask(SharedData sharedData) { super(sharedData); } @Override - protected void onPostExecute(List requests) { + protected void onPostExecute(List requests) { super.onPostExecute(requests); - for (Fee_Request request : requests) { + for (FeeRequest request : requests) { if (request.error == null) { long minFeeRate = 0; @@ -651,12 +651,12 @@ public class ConfirmPaymentActivity extends AppCompatActivity implements NfcAdap finalFee = Math.round(finalFee) / (float) 10000; - if (request.getBlockCount() == Fee_Request.MINIMAL) { + if (request.getBlockCount() == FeeRequest.MINIMAL) { minFee = String.valueOf(finalFee); minFeeInInternalUnits = mCard.InternalUnitsFromString(String.valueOf(finalFee)); - } else if (request.getBlockCount() == Fee_Request.NORMAL) { + } else if (request.getBlockCount() == FeeRequest.NORMAL) { normalFee = String.valueOf(finalFee); - } else if (request.getBlockCount() == Fee_Request.PRIORITY) { + } else if (request.getBlockCount() == FeeRequest.PRIORITY) { maxFee = String.valueOf(finalFee); } diff --git a/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.java b/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.java index 0699a29470..3ce28331d9 100644 --- a/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/CreateNewWalletActivity.java @@ -17,17 +17,17 @@ import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class CreateNewWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER; - private Tangem_Card mCard; + private TangemCard mCard; private TextView tvCardID; private NfcManager mNfcManager; private static final String logTag = "CreateNewActivity"; @@ -41,7 +41,7 @@ public class CreateNewWalletActivity extends AppCompatActivity implements NfcAda setContentView(R.layout.activity_create_new_wallet); MainActivity.commonInit(getApplicationContext()); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); tvCardID = (TextView) findViewById(R.id.tvCardID); diff --git a/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.java b/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.java index 9e7c4f35e9..1f7e858384 100644 --- a/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/EmptyWalletActivity.java @@ -19,11 +19,11 @@ import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.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.data.network.task.VerifyCardTask; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class EmptyWalletActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { @@ -31,7 +31,7 @@ public class EmptyWalletActivity extends AppCompatActivity implements NfcAdapter private static final int REQUEST_CODE_CREATE_NEW_WALLET_ACTIVITY = 2; private static final int REQUEST_CODE_REQUEST_PIN2 = 3; private static final int REQUEST_CODE_VERIFY_CARD = 4; - Tangem_Card mCard; + TangemCard mCard; TextView tvCardID, tvIssuer, tvIssuerData, tvBlockchain; ProgressBar progressBar; ImageView ivBlockchain, ivPIN, ivPIN2orSecurityDelay, ivDeveloperVersion; @@ -51,7 +51,7 @@ public class EmptyWalletActivity extends AppCompatActivity implements NfcAdapter MainActivity.commonInit(getApplicationContext()); mNfcManager = new NfcManager(this, this); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); tvCardID = findViewById(R.id.tvCardID); @@ -181,7 +181,7 @@ public class EmptyWalletActivity extends AppCompatActivity implements NfcAdapter finish(); } else { if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) { - Tangem_Card updatedCard = new Tangem_Card(data.getStringExtra("UID")); + TangemCard updatedCard = new TangemCard(data.getStringExtra("UID")); updatedCard.LoadFromBundle(data.getBundleExtra("Card")); mCard = updatedCard; } diff --git a/app/src/main/java/com/tangem/presentation/activity/LoadedWalletActivity.java b/app/src/main/java/com/tangem/presentation/activity/LoadedWalletActivity.java index ae60bfb60b..8f95153a90 100644 --- a/app/src/main/java/com/tangem/presentation/activity/LoadedWalletActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/LoadedWalletActivity.java @@ -7,7 +7,7 @@ import android.nfc.Tag; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import com.tangem.presentation.fragment.LoadedWalletActivityFragment; +import com.tangem.presentation.fragment.LoadedWalletFragment; import com.tangem.wallet.R; @@ -23,7 +23,7 @@ public class LoadedWalletActivity extends AppCompatActivity { { Tag tag=getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG); if (tag != null ) { - LoadedWalletActivityFragment fragment=(LoadedWalletActivityFragment)(getSupportFragmentManager().findFragmentById(R.id.loaded_wallet_fragment)); + LoadedWalletFragment fragment=(LoadedWalletFragment)(getSupportFragmentManager().findFragmentById(R.id.loaded_wallet_fragment)); fragment.onTagDiscovered(tag); } } @@ -31,8 +31,8 @@ public class LoadedWalletActivity extends AppCompatActivity { @Override public void onBackPressed() { - LoadedWalletActivityFragment loadedWalletActivityFragment=(LoadedWalletActivityFragment) getSupportFragmentManager().findFragmentById(R.id.loaded_wallet_fragment); - Intent data= loadedWalletActivityFragment.prepareResultIntent(); + LoadedWalletFragment loadedWalletFragment =(LoadedWalletFragment) getSupportFragmentManager().findFragmentById(R.id.loaded_wallet_fragment); + Intent data= loadedWalletFragment.prepareResultIntent(); data.putExtra("modification", "update"); setResult(Activity.RESULT_OK, data); finish(); diff --git a/app/src/main/java/com/tangem/presentation/activity/LogoActivity.java b/app/src/main/java/com/tangem/presentation/activity/LogoActivity.java index cd5f60b0d2..7cc9bca29c 100644 --- a/app/src/main/java/com/tangem/presentation/activity/LogoActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/LogoActivity.java @@ -3,7 +3,6 @@ package com.tangem.presentation.activity; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import android.view.View; import android.widget.ImageView; import android.widget.TextView; @@ -23,39 +22,33 @@ public class LogoActivity extends AppCompatActivity { } }; - ImageView imgLogo; + private ImageView imgLogo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.activity_logo); - imgLogo= (ImageView) findViewById(R.id.imgLogo); - // Set up the user interaction to manually show or hide the system UI. - imgLogo.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) {hide(); - } - }); + imgLogo = findViewById(R.id.imgLogo); + + // set up the user interaction to manually show or hide the system UI. + imgLogo.setOnClickListener(view -> hide()); } @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); - // Trigger the initial hide() shortly after the activity has been - // created, to briefly hint to the user that UI controls - // are available. - TextView AppVersion = (TextView) findViewById(R.id.AppVersion); + // trigger the initial hide() shortly after the activity has been created, to briefly hint to the user that UI controls are available. + TextView AppVersion = findViewById(R.id.AppVersion); AppVersion.setText("BETA v." + BuildConfig.VERSION_NAME); - if( !getIntent().getBooleanExtra("skipAutoHide",false)) { + if (!getIntent().getBooleanExtra("skipAutoHide", false)) { delayedHide(1000); } } private void hide() { - Intent intent=new Intent(getBaseContext(),MainActivity.class); + Intent intent = new Intent(getBaseContext(), MainActivity.class); startActivity(intent); finish(); } diff --git a/app/src/main/java/com/tangem/presentation/activity/MainActivity.java b/app/src/main/java/com/tangem/presentation/activity/MainActivity.java index 34fb4d16b8..9190a4c7e3 100644 --- a/app/src/main/java/com/tangem/presentation/activity/MainActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/MainActivity.java @@ -30,14 +30,14 @@ import android.widget.TextView; import com.scottyab.rootbeer.RootBeer; import com.skyfishjy.library.RippleBackground; +import com.tangem.LogFileProvider; +import com.tangem.domain.wallet.DeviceNFCAntennaLocation; +import com.tangem.domain.wallet.LastSignStorage; +import com.tangem.domain.wallet.Logger; +import com.tangem.domain.wallet.PINStorage; +import com.tangem.util.PhoneUtility; +import com.tangem.presentation.fragment.MainFragment; import com.tangem.wallet.BuildConfig; -import com.tangem.wallet.DeviceNFCAntennaLocation; -import com.tangem.wallet.LastSignStorage; -import com.tangem.wallet.LogFileProvider; -import com.tangem.wallet.Logger; -import com.tangem.presentation.fragment.MainActivityFragment; -import com.tangem.wallet.PINStorage; -import com.tangem.wallet.PhoneUtility; import com.tangem.wallet.R; import java.io.BufferedInputStream; @@ -165,8 +165,8 @@ public class MainActivity extends AppCompatActivity implements PopupMenu.OnMenuI } }); - MainActivityFragment mainActivityFragment=(MainActivityFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentMain); - if( mainActivityFragment.getCardListAdapter().getItemCount()>0 ) + MainFragment mainFragment =(MainFragment)getSupportFragmentManager().findFragmentById(R.id.fragmentMain); + if( mainFragment.getCardListAdapter().getItemCount()>0 ) { showCleanButton(); }else { diff --git a/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.java b/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.java index cfc7d913bb..2ea644fb6c 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/PreparePaymentActivity.java @@ -18,12 +18,12 @@ import android.widget.ImageView; import android.widget.TextView; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.wallet.Blockchain; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; -import com.tangem.wallet.FormatUtil; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.domain.wallet.FormatUtil; +import com.tangem.domain.wallet.TangemCard; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import java.io.IOException; @@ -38,7 +38,7 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap TextView tvCardId, tvBalance, tvBalanceEquivalent, tvAmountEquivalent; ImageView ivCamera; boolean use_mCurrency; - Tangem_Card mCard; + TangemCard mCard; private NfcManager mNfcManager; @Override @@ -50,7 +50,7 @@ public class PreparePaymentActivity extends AppCompatActivity implements NfcAdap mNfcManager = new NfcManager(this, this); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); btnVerify = (Button) findViewById(R.id.btnVerify); diff --git a/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.java b/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.java index a67dd5e36d..2caca8b0b3 100644 --- a/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/PurgeActivity.java @@ -17,18 +17,18 @@ import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class PurgeActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER; - private Tangem_Card mCard; + private TangemCard mCard; private TextView tvCardID; private NfcManager mNfcManager; private static final String logTag = "Purge"; @@ -42,7 +42,7 @@ public class PurgeActivity extends AppCompatActivity implements NfcAdapter.Reade MainActivity.commonInit(getApplicationContext()); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); tvCardID = (TextView) findViewById(R.id.tvCardID); diff --git a/app/src/main/java/com/tangem/presentation/activity/RequestPINActivity.java b/app/src/main/java/com/tangem/presentation/activity/RequestPINActivity.java index e68938c105..e10c13d5ab 100644 --- a/app/src/main/java/com/tangem/presentation/activity/RequestPINActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/RequestPINActivity.java @@ -27,10 +27,10 @@ import android.widget.ImageView; import android.widget.TextView; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.wallet.FingerprintHelper; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.FingerprintHelper; +import com.tangem.domain.wallet.PINStorage; +import com.tangem.domain.wallet.TangemCard; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import java.io.IOException; import java.security.KeyStore; @@ -149,10 +149,10 @@ public class RequestPINActivity extends AppCompatActivity implements NfcAdapter. tvPrompt.setText("Confirm new PIN2"); } else if (mode == Mode.RequestPIN2) { String UID = getIntent().getStringExtra("UID"); - Tangem_Card mCard = new Tangem_Card(UID); + TangemCard mCard = new TangemCard(UID); mCard.LoadFromBundle(getIntent().getBundleExtra("Card")); - if (mCard.PIN2 == Tangem_Card.PIN2_Mode.DefaultPIN2 || mCard.PIN2 == Tangem_Card.PIN2_Mode.Unchecked) { + if (mCard.PIN2 == TangemCard.PIN2_Mode.DefaultPIN2 || mCard.PIN2 == TangemCard.PIN2_Mode.Unchecked) { // if we know PIN2 or not try default previously - use it PINStorage.setPIN2(PINStorage.getDefaultPIN2()); setResult(Activity.RESULT_OK); diff --git a/app/src/main/java/com/tangem/presentation/activity/SavePINActivity.java b/app/src/main/java/com/tangem/presentation/activity/SavePINActivity.java index b2172ed82d..56298fd2ce 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SavePINActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/SavePINActivity.java @@ -23,8 +23,8 @@ import android.widget.CheckBox; import android.widget.TextView; import android.widget.Toast; -import com.tangem.wallet.FingerprintHelper; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.FingerprintHelper; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; import java.io.IOException; diff --git a/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.java b/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.java index 606b27315e..d46e73980c 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/SendTransactionActivity.java @@ -8,17 +8,17 @@ import android.view.KeyEvent; import android.widget.ProgressBar; import android.widget.Toast; -import com.tangem.wallet.Blockchain; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; -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.data.network.task.Infura_Task; -import com.tangem.wallet.LastSignStorage; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.data.network.request.ElectrumRequest; +import com.tangem.data.network.task.ElectrumTask; +import com.tangem.domain.wallet.Infura_Request; +import com.tangem.data.network.task.InfuraTask; +import com.tangem.domain.wallet.LastSignStorage; +import com.tangem.domain.wallet.TangemCard; import com.tangem.wallet.R; -import com.tangem.wallet.SharedData; -import com.tangem.wallet.Tangem_Card; +import com.tangem.domain.wallet.SharedData; import org.json.JSONException; import org.json.JSONObject; @@ -29,7 +29,7 @@ import java.util.List; public class SendTransactionActivity extends AppCompatActivity { ProgressBar progressBar; - private Tangem_Card mCard; + private TangemCard mCard; private String tx; @Override @@ -42,7 +42,7 @@ public class SendTransactionActivity extends AppCompatActivity { progressBar = findViewById(R.id.progressBar); Intent intent = getIntent(); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(intent.getExtras().getBundle("Card")); tx = intent.getStringExtra("TX"); @@ -57,13 +57,13 @@ public class SendTransactionActivity extends AppCompatActivity { String nodeAddress = engine.GetNode(mCard); int nodePort = engine.GetNodePort(mCard); ConnectTask connectTask = new ConnectTask(nodeAddress, nodePort); - connectTask.execute(Electrum_Request.Broadcast(mCard.getWallet(), tx)); + connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx)); } else if (mCard.getBlockchain() == Blockchain.BitcoinCash || mCard.getBlockchain() == Blockchain.BitcoinCashTestNet ) { String nodeAddress = engine.GetNode(mCard); int nodePort = engine.GetNodePort(mCard); ConnectTask connectTask = new ConnectTask(nodeAddress, nodePort); - connectTask.execute(Electrum_Request.Broadcast(mCard.getWallet(), tx)); + connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx)); } } @@ -93,7 +93,7 @@ public class SendTransactionActivity extends AppCompatActivity { finish(); } - private class ETHRequestTask extends Infura_Task { + private class ETHRequestTask extends InfuraTask { ETHRequestTask(Blockchain blockchain){ super(blockchain); } @@ -152,7 +152,7 @@ public class SendTransactionActivity extends AppCompatActivity { } } - private class ConnectTask extends Electrum_Task { + private class ConnectTask extends ElectrumTask { public ConnectTask(String host, int port) { super(host, port); } @@ -167,14 +167,14 @@ public class SendTransactionActivity extends AppCompatActivity { } @Override - protected void onPostExecute(List requests) { + protected void onPostExecute(List requests) { super.onPostExecute(requests); CoinEngine engine = CoinEngineFactory.Create(Blockchain.Bitcoin); - for (Electrum_Request request : requests) { + for (ElectrumRequest request : requests) { try { if (request.error == null) { - if (request.isMethod(Electrum_Request.METHOD_SendTransaction)) { + if (request.isMethod(ElectrumRequest.METHOD_SendTransaction)) { try { String hashTX = request.getResultString(); diff --git a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.java b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.java index be424269a1..dc242e47ff 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/SignPaymentActivity.java @@ -1 +1 @@ -package com.tangem.presentation.activity; import android.app.Activity; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Color; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; 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.LastSignStorage; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; import com.tangem.wallet.R; import com.tangem.wallet.Tangem_Card; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class SignPaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { private static final int REQUEST_CODE_SEND_PAYMENT = 1; public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER; private Tangem_Card mCard; private TextView tvCardID; private NfcManager mNfcManager; private static final String logTag = "SignPayment"; private ProgressBar progressBar; private SignPaymentTask signPaymentTask; private String amountStr; private String feeStr; private String outAddressStr; private boolean lastReadSuccess = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_payment); MainActivity.commonInit(getApplicationContext()); mCard = new Tangem_Card(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); amountStr = getIntent().getStringExtra("Amount"); feeStr = getIntent().getStringExtra("Fee"); outAddressStr = getIntent().getStringExtra("Wallet"); tvCardID = findViewById(R.id.tvCardID); tvCardID.setText(mCard.getCIDDescription()); mNfcManager = new NfcManager(this, this); progressBar = findViewById(R.id.progressBar); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } @Override public void onTagDiscovered(Tag tag) { try { // get IsoDep handle and run cardReader thread final IsoDep isoDep = IsoDep.get(tag); if (isoDep == null) { throw new CardProtocol.TangemException(getString(R.string.wrong_tag_err)); } byte UID[] = tag.getId(); String sUID = Util.byteArrayToHexString(UID); Log.v(logTag, "UID: " + sUID); if (sUID.equals(mCard.getUID())) { if (lastReadSuccess) { isoDep.setTimeout(mCard.getPauseBeforePIN2() + 5000); } else { isoDep.setTimeout(mCard.getPauseBeforePIN2() + 65000); } signPaymentTask = new SignPaymentTask(isoDep, this, amountStr, feeStr, outAddressStr); signPaymentTask.start(); } else { Log.d(logTag, "Mismatch card UID (" + sUID + " instead of " + mCard.getUID() + ")"); mNfcManager.IgnoreTag(isoDep.getTag()); return; } } catch (Exception e) { e.printStackTrace(); } } @Override public void onResume() { super.onResume(); mNfcManager.onResume(); } @Override public void onPause() { mNfcManager.onPause(); if (signPaymentTask != null) { signPaymentTask.cancel(true); } super.onPause(); } @Override public void onStop() { // dismiss enable NFC dialog mNfcManager.onStop(); if (signPaymentTask != null) { signPaymentTask.cancel(true); } super.onStop(); } // @Override // public Dialog CreateNFCDialog(int id, AlertDialogWrapper.Builder builder, LayoutInflater li) { // return mNfcManager.onCreateDialog(id, builder, li); // } private class SignPaymentTask extends Thread { String txAmount = ""; String txFee = ""; public void SetTransactionValue(String amount, String fee) { txAmount = amount; txFee = fee; } private String txOutAddress; IsoDep mIsoDep; CardProtocol.Notifications mNotifications; private boolean isCancelled = false; public SignPaymentTask(IsoDep isoDep, CardProtocol.Notifications notifications, String amount, String fee, String outAddress) { mIsoDep = isoDep; mNotifications = notifications; txOutAddress = outAddress; SetTransactionValue(amount, fee); } @Override public void run() { if (mIsoDep == null) { return; } CardProtocol protocol = new CardProtocol(getBaseContext(), mIsoDep, mCard, mNotifications); mNotifications.OnReadStart(protocol); try { // for Samsung's bugs - // Workaround for the Samsung Galaxy S5 (since the // first connection always hangs on transceive). int timeout = mIsoDep.getTimeout(); mIsoDep.connect(); mIsoDep.close(); mIsoDep.connect(); mIsoDep.setTimeout(timeout); try { mNotifications.OnReadProgress(protocol, 5); Log.i("SignPaymentTask", "[-- Start sign payment --]"); if (isCancelled) return; protocol.run_VerifyCard(); Log.i("SignPaymentTask", "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName()); mNotifications.OnReadProgress(protocol, 30); if (isCancelled) return; // // if (mCard.getBlockchain() == Blockchain.Ethereum) { // SignETH_TX(protocol); // } else { // SignBTC_TX(protocol); // } CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); if (engine != null) { if (mCard.getPauseBeforePIN2() > 0) { mNotifications.OnReadWait(mCard.getPauseBeforePIN2()); } byte[] tx; // try { tx = engine.Sign(txFee, txAmount, txOutAddress, mCard, protocol); // } // finally { // mNotifications.OnReadWait(0); // } if (tx != null) { String txStr = BTCUtils.toHex(tx); if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) { txStr = String.format("0x%s", txStr); } LastSignStorage.setLastTX(mCard.getWallet(), txStr); Intent intent = new Intent(getBaseContext(), SendTransactionActivity.class); intent.putExtra("UID", mCard.getUID()); intent.putExtra("Card", mCard.getAsBundle()); intent.putExtra("TX", txStr); startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT); } } mNotifications.OnReadProgress(protocol, 100); if (isCancelled) return; } finally { mNfcManager.IgnoreTag(mIsoDep.getTag()); } } catch (CardProtocol.TangemException_InvalidPIN e) { e.printStackTrace(); protocol.setError(e); } catch (Exception e) { e.printStackTrace(); protocol.setError(e); } finally { Log.i("SignPaymentTask", "[-- Finish sign payment --]"); mNotifications.OnReadFinish(protocol); } } public void cancel(Boolean AllowInterrupt) { try { if (this.isAlive()) { isCancelled = true; join(500); } if (this.isAlive() && AllowInterrupt) { interrupt(); mNotifications.OnReadCancel(); } } catch (Exception e) { e.printStackTrace(); } } } public void OnReadStart(CardProtocol cardProtocol) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(5); } }); } public void OnReadFinish(final CardProtocol cardProtocol) { signPaymentTask = null; if (cardProtocol != null) { if (cardProtocol.getError() == null) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN)); } }); } else { lastReadSuccess = false; if (cardProtocol.getError().getClass().equals(CardProtocol.TangemException_InvalidPIN.class)) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED)); } }); progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); Intent intent = new Intent(); intent.putExtra("message", "Cannot sign transaction. Make sure you enter correct PIN2!"); intent.putExtra("UID", cardProtocol.getCard().getUID()); intent.putExtra("Card", cardProtocol.getCard().getAsBundle()); setResult(RESULT_INVALID_PIN, intent); finish(); } catch (Exception e) { e.printStackTrace(); } } }, 500); return; } else { progressBar.post(new Runnable() { @Override public void run() { if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) { if (!NoExtendedLengthSupportDialog.allreadyShowed) { new NoExtendedLengthSupportDialog().show(getFragmentManager(), "NoExtendedLengthSupportDialog"); } } else { Toast.makeText(getBaseContext(), "Try to scan again", Toast.LENGTH_LONG).show(); } progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED)); } }); } } } progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } catch (Exception e) { e.printStackTrace(); } } }, 500); } public void OnReadProgress(CardProtocol protocol, final int progress) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(progress); } }); } public void OnReadCancel() { signPaymentTask = null; progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } catch (Exception e) { e.printStackTrace(); } } }, 500); } @Override public void OnReadWait(final int msec) { WaitSecurityDelayDialog.OnReadWait(this, msec); } @Override public void OnReadBeforeRequest(int timeout) { WaitSecurityDelayDialog.onReadBeforeRequest(this, timeout); } @Override public void OnReadAfterRequest() { WaitSecurityDelayDialog.onReadAfterRequest(this); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: Intent intent = new Intent(); intent.putExtra("message", "Operation canceled by user"); setResult(Activity.RESULT_CANCELED, intent); finish(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_SEND_PAYMENT) { setResult(resultCode, data); finish(); return; } super.onActivityResult(requestCode, resultCode, data); } } \ No newline at end of file +package com.tangem.presentation.activity; import android.app.Activity; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Color; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.IsoDep; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; import com.tangem.domain.wallet.TangemCard; import com.tangem.util.Util; import com.tangem.domain.wallet.BTCUtils; import com.tangem.domain.wallet.Blockchain; import com.tangem.domain.wallet.CoinEngine; import com.tangem.domain.wallet.CoinEngineFactory; import com.tangem.domain.wallet.LastSignStorage; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; import com.tangem.wallet.R; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class SignPaymentActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { private static final int REQUEST_CODE_SEND_PAYMENT = 1; public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER; private TangemCard mCard; private TextView tvCardID; private NfcManager mNfcManager; private static final String logTag = "SignPayment"; private ProgressBar progressBar; private SignPaymentTask signPaymentTask; private String amountStr; private String feeStr; private String outAddressStr; private boolean lastReadSuccess = true; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_payment); MainActivity.commonInit(getApplicationContext()); mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); amountStr = getIntent().getStringExtra("Amount"); feeStr = getIntent().getStringExtra("Fee"); outAddressStr = getIntent().getStringExtra("Wallet"); tvCardID = findViewById(R.id.tvCardID); tvCardID.setText(mCard.getCIDDescription()); mNfcManager = new NfcManager(this, this); progressBar = findViewById(R.id.progressBar); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } @Override public void onTagDiscovered(Tag tag) { try { // get IsoDep handle and run cardReader thread final IsoDep isoDep = IsoDep.get(tag); if (isoDep == null) { throw new CardProtocol.TangemException(getString(R.string.wrong_tag_err)); } byte UID[] = tag.getId(); String sUID = Util.byteArrayToHexString(UID); Log.v(logTag, "UID: " + sUID); if (sUID.equals(mCard.getUID())) { if (lastReadSuccess) { isoDep.setTimeout(mCard.getPauseBeforePIN2() + 5000); } else { isoDep.setTimeout(mCard.getPauseBeforePIN2() + 65000); } signPaymentTask = new SignPaymentTask(isoDep, this, amountStr, feeStr, outAddressStr); signPaymentTask.start(); } else { Log.d(logTag, "Mismatch card UID (" + sUID + " instead of " + mCard.getUID() + ")"); mNfcManager.IgnoreTag(isoDep.getTag()); return; } } catch (Exception e) { e.printStackTrace(); } } @Override public void onResume() { super.onResume(); mNfcManager.onResume(); } @Override public void onPause() { mNfcManager.onPause(); if (signPaymentTask != null) { signPaymentTask.cancel(true); } super.onPause(); } @Override public void onStop() { // dismiss enable NFC dialog mNfcManager.onStop(); if (signPaymentTask != null) { signPaymentTask.cancel(true); } super.onStop(); } // @Override // public Dialog CreateNFCDialog(int id, AlertDialogWrapper.Builder builder, LayoutInflater li) { // return mNfcManager.onCreateDialog(id, builder, li); // } private class SignPaymentTask extends Thread { String txAmount = ""; String txFee = ""; public void SetTransactionValue(String amount, String fee) { txAmount = amount; txFee = fee; } private String txOutAddress; IsoDep mIsoDep; CardProtocol.Notifications mNotifications; private boolean isCancelled = false; public SignPaymentTask(IsoDep isoDep, CardProtocol.Notifications notifications, String amount, String fee, String outAddress) { mIsoDep = isoDep; mNotifications = notifications; txOutAddress = outAddress; SetTransactionValue(amount, fee); } @Override public void run() { if (mIsoDep == null) { return; } CardProtocol protocol = new CardProtocol(getBaseContext(), mIsoDep, mCard, mNotifications); mNotifications.OnReadStart(protocol); try { // for Samsung's bugs - // Workaround for the Samsung Galaxy S5 (since the // first connection always hangs on transceive). int timeout = mIsoDep.getTimeout(); mIsoDep.connect(); mIsoDep.close(); mIsoDep.connect(); mIsoDep.setTimeout(timeout); try { mNotifications.OnReadProgress(protocol, 5); Log.i("SignPaymentTask", "[-- Start sign payment --]"); if (isCancelled) return; protocol.run_VerifyCard(); Log.i("SignPaymentTask", "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName()); mNotifications.OnReadProgress(protocol, 30); if (isCancelled) return; // // if (mCard.getBlockchain() == Blockchain.Ethereum) { // SignETH_TX(protocol); // } else { // SignBTC_TX(protocol); // } CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); if (engine != null) { if (mCard.getPauseBeforePIN2() > 0) { mNotifications.OnReadWait(mCard.getPauseBeforePIN2()); } byte[] tx; // try { tx = engine.Sign(txFee, txAmount, txOutAddress, mCard, protocol); // } // finally { // mNotifications.OnReadWait(0); // } if (tx != null) { String txStr = BTCUtils.toHex(tx); if (mCard.getBlockchain() == Blockchain.Ethereum || mCard.getBlockchain() == Blockchain.EthereumTestNet || mCard.getBlockchain() == Blockchain.Token) { txStr = String.format("0x%s", txStr); } LastSignStorage.setLastTX(mCard.getWallet(), txStr); Intent intent = new Intent(getBaseContext(), SendTransactionActivity.class); intent.putExtra("UID", mCard.getUID()); intent.putExtra("Card", mCard.getAsBundle()); intent.putExtra("TX", txStr); startActivityForResult(intent, REQUEST_CODE_SEND_PAYMENT); } } mNotifications.OnReadProgress(protocol, 100); if (isCancelled) return; } finally { mNfcManager.IgnoreTag(mIsoDep.getTag()); } } catch (CardProtocol.TangemException_InvalidPIN e) { e.printStackTrace(); protocol.setError(e); } catch (Exception e) { e.printStackTrace(); protocol.setError(e); } finally { Log.i("SignPaymentTask", "[-- Finish sign payment --]"); mNotifications.OnReadFinish(protocol); } } public void cancel(Boolean AllowInterrupt) { try { if (this.isAlive()) { isCancelled = true; join(500); } if (this.isAlive() && AllowInterrupt) { interrupt(); mNotifications.OnReadCancel(); } } catch (Exception e) { e.printStackTrace(); } } } public void OnReadStart(CardProtocol cardProtocol) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setVisibility(View.VISIBLE); progressBar.setProgress(5); } }); } public void OnReadFinish(final CardProtocol cardProtocol) { signPaymentTask = null; if (cardProtocol != null) { if (cardProtocol.getError() == null) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.GREEN)); } }); } else { lastReadSuccess = false; if (cardProtocol.getError().getClass().equals(CardProtocol.TangemException_InvalidPIN.class)) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED)); } }); progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); Intent intent = new Intent(); intent.putExtra("message", "Cannot sign transaction. Make sure you enter correct PIN2!"); intent.putExtra("UID", cardProtocol.getCard().getUID()); intent.putExtra("Card", cardProtocol.getCard().getAsBundle()); setResult(RESULT_INVALID_PIN, intent); finish(); } catch (Exception e) { e.printStackTrace(); } } }, 500); return; } else { progressBar.post(new Runnable() { @Override public void run() { if (cardProtocol.getError() instanceof CardProtocol.TangemException_ExtendedLengthNotSupported) { if (!NoExtendedLengthSupportDialog.allreadyShowed) { new NoExtendedLengthSupportDialog().show(getFragmentManager(), "NoExtendedLengthSupportDialog"); } } else { Toast.makeText(getBaseContext(), "Try to scan again", Toast.LENGTH_LONG).show(); } progressBar.setProgress(100); progressBar.setProgressTintList(ColorStateList.valueOf(Color.RED)); } }); } } } progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } catch (Exception e) { e.printStackTrace(); } } }, 500); } public void OnReadProgress(CardProtocol protocol, final int progress) { progressBar.post(new Runnable() { @Override public void run() { progressBar.setProgress(progress); } }); } public void OnReadCancel() { signPaymentTask = null; progressBar.postDelayed(new Runnable() { @Override public void run() { try { progressBar.setProgress(0); progressBar.setProgressTintList(ColorStateList.valueOf(Color.DKGRAY)); progressBar.setVisibility(View.INVISIBLE); } catch (Exception e) { e.printStackTrace(); } } }, 500); } @Override public void OnReadWait(final int msec) { WaitSecurityDelayDialog.OnReadWait(this, msec); } @Override public void OnReadBeforeRequest(int timeout) { WaitSecurityDelayDialog.onReadBeforeRequest(this, timeout); } @Override public void OnReadAfterRequest() { WaitSecurityDelayDialog.onReadAfterRequest(this); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_BACK: Intent intent = new Intent(); intent.putExtra("message", "Operation canceled by user"); setResult(Activity.RESULT_CANCELED, intent); finish(); return true; } return super.onKeyDown(keyCode, event); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_CODE_SEND_PAYMENT) { setResult(resultCode, data); finish(); return; } super.onActivityResult(requestCode, resultCode, data); } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/presentation/activity/SwapPINActivity.java b/app/src/main/java/com/tangem/presentation/activity/SwapPINActivity.java index 25e0c243b3..1e55df0011 100644 --- a/app/src/main/java/com/tangem/presentation/activity/SwapPINActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/SwapPINActivity.java @@ -17,17 +17,17 @@ import android.widget.Toast; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; public class SwapPINActivity extends AppCompatActivity implements NfcAdapter.ReaderCallback, CardProtocol.Notifications { public static final int RESULT_INVALID_PIN = Activity.RESULT_FIRST_USER; - private Tangem_Card mCard; + private TangemCard mCard; private NfcManager mNfcManager; private static final String logTag = "SwapPIN"; private ProgressBar progressBar; @@ -42,7 +42,7 @@ public class SwapPINActivity extends AppCompatActivity implements NfcAdapter.Rea MainActivity.commonInit(getApplicationContext()); - mCard = new Tangem_Card(getIntent().getStringExtra("UID")); + mCard = new TangemCard(getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getIntent().getExtras().getBundle("Card")); newPIN = getIntent().getStringExtra("newPIN"); diff --git a/app/src/main/java/com/tangem/presentation/activity/VerifyCardActivity.java b/app/src/main/java/com/tangem/presentation/activity/VerifyCardActivity.java index e3e3821430..38bd0103e5 100644 --- a/app/src/main/java/com/tangem/presentation/activity/VerifyCardActivity.java +++ b/app/src/main/java/com/tangem/presentation/activity/VerifyCardActivity.java @@ -6,7 +6,7 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import com.tangem.wallet.R; -import com.tangem.presentation.fragment.VerifyCardActivityFragment; +import com.tangem.presentation.fragment.VerifyCardFragment; public class VerifyCardActivity extends AppCompatActivity { @@ -21,8 +21,8 @@ public class VerifyCardActivity extends AppCompatActivity { @Override public void onBackPressed() { //super.onBackPressed(); - VerifyCardActivityFragment verifyCardActivityFragment = (VerifyCardActivityFragment) getSupportFragmentManager().findFragmentById(R.id.verify_card_fragment); - Intent data = verifyCardActivityFragment.prepareResultIntent(); + VerifyCardFragment verifyCardFragment = (VerifyCardFragment) getSupportFragmentManager().findFragmentById(R.id.verify_card_fragment); + Intent data = verifyCardFragment.prepareResultIntent(); data.putExtra("modification", "update"); setResult(Activity.RESULT_OK, data); finish(); diff --git a/app/src/main/java/com/tangem/presentation/adapter/CardListAdapter.java b/app/src/main/java/com/tangem/presentation/adapter/CardListAdapter.java index 5c541fe60e..d6ddb400a9 100644 --- a/app/src/main/java/com/tangem/presentation/adapter/CardListAdapter.java +++ b/app/src/main/java/com/tangem/presentation/adapter/CardListAdapter.java @@ -12,11 +12,11 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import com.tangem.wallet.Blockchain; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.domain.wallet.TangemCard; import com.tangem.wallet.R; -import com.tangem.wallet.Tangem_Card; import org.json.JSONArray; import org.json.JSONException; @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import static com.tangem.wallet.Tangem_Card.CountOurTx; +import static com.tangem.domain.wallet.TangemCard.CountOurTx; public class CardListAdapter extends RecyclerView.Adapter { @@ -81,7 +81,7 @@ public class CardListAdapter extends RecyclerView.Adapter mCards = new ArrayList<>(100); + private List mCards = new ArrayList<>(100); public CardListAdapter(LayoutInflater layoutInflater, Bundle instate, UiCallbacks uiCallbacks) { mLayoutInflater = layoutInflater; @@ -94,7 +94,7 @@ public class CardListAdapter extends RecyclerView.Adapter UIDs = new ArrayList(mCards.size()); - for (Tangem_Card card : mCards) { + for (TangemCard card : mCards) { Bundle B = new Bundle(); card.SaveToBundle(B); outstate.putBundle(String.format("card_%s", card.getUID()), B); @@ -119,12 +119,12 @@ public class CardListAdapter extends RecyclerView.Adapter listTx = c.getUnspentTransactions(); - for (Tangem_Card.UnspentTransaction tx : listTx) { + List listTx = c.getUnspentTransactions(); + for (TangemCard.UnspentTransaction tx : listTx) { if (tx.txID.equals(txHash)) { tx.Raw = raw; } } - List listHTx = c.getHistoryTransactions(); - for (Tangem_Card.HistoryTransaction tx : listHTx) { + List listHTx = c.getHistoryTransactions(); + for (TangemCard.HistoryTransaction tx : listHTx) { if (tx.txID.equals(txHash)) { tx.Raw = raw; CountOurTx(listHTx); @@ -345,7 +345,7 @@ public class CardListAdapter extends RecyclerView.Adapter%d mBTC
%s", unspentTransaction.Amount, unspentTransaction.txID); @@ -76,7 +76,7 @@ public class CardUnspentListAdapter extends BaseAdapter { } public void UpdateUnspent(String tx_hash, int value, int height) { - Tangem_Card.UnspentTransaction newUT=new Tangem_Card.UnspentTransaction(); + TangemCard.UnspentTransaction newUT=new TangemCard.UnspentTransaction(); newUT.txID=tx_hash; newUT.Amount=value; newUT.Height=height; diff --git a/app/src/main/java/com/tangem/presentation/fragment/LoadedWalletActivityFragment.java b/app/src/main/java/com/tangem/presentation/fragment/LoadedWalletFragment.java similarity index 94% rename from app/src/main/java/com/tangem/presentation/fragment/LoadedWalletActivityFragment.java rename to app/src/main/java/com/tangem/presentation/fragment/LoadedWalletFragment.java index 793f0a924f..f679fe01b4 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/LoadedWalletActivityFragment.java +++ b/app/src/main/java/com/tangem/presentation/fragment/LoadedWalletFragment.java @@ -39,33 +39,33 @@ 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.data.network.request.ElectrumRequest; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; import com.tangem.presentation.activity.CreateNewWalletActivity; import com.tangem.presentation.activity.PreparePaymentActivity; import com.tangem.presentation.activity.PurgeActivity; import com.tangem.presentation.activity.RequestPINActivity; import com.tangem.presentation.activity.SwapPINActivity; import com.tangem.presentation.activity.VerifyCardActivity; -import com.tangem.wallet.BTCUtils; -import com.tangem.wallet.BitcoinException; -import com.tangem.wallet.Blockchain; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; -import com.tangem.data.network.request.Electrum_Request; -import com.tangem.data.network.task.Electrum_Task; +import com.tangem.domain.wallet.BTCUtils; +import com.tangem.domain.wallet.BitcoinException; +import com.tangem.domain.wallet.Blockchain; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.data.network.task.ElectrumTask; import com.tangem.data.network.request.ExchangeRequest; import com.tangem.data.network.task.ExchangeTask; -import com.tangem.wallet.Infura_Request; -import com.tangem.data.network.task.Infura_Task; -import com.tangem.wallet.LastSignStorage; +import com.tangem.domain.wallet.Infura_Request; +import com.tangem.data.network.task.InfuraTask; +import com.tangem.domain.wallet.LastSignStorage; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; -import com.tangem.wallet.SharedData; -import com.tangem.wallet.Tangem_Card; -import com.tangem.wallet.VerifyCardTask; +import com.tangem.domain.wallet.SharedData; +import com.tangem.data.network.task.VerifyCardTask; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; import org.json.JSONArray; @@ -84,7 +84,7 @@ import static android.content.Context.CLIPBOARD_SERVICE; /** * A placeholder fragment containing a simple view. */ -public class LoadedWalletActivityFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback, CardProtocol.Notifications { +public class LoadedWalletFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback, CardProtocol.Notifications { private static final int REQUEST_CODE_SEND_PAYMENT = 1; @@ -95,7 +95,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre private static final int REQUEST_CODE_ENTER_NEW_PIN2 = 6; private static final int REQUEST_CODE_REQUEST_PIN2_FOR_SWAP_PIN = 7; private static final int REQUEST_CODE_SWAP_PIN = 8; - Tangem_Card mCard; + TangemCard mCard; TextView tvCardID, tvBalance, tvOffline, tvBalanceEquivalent, tvWallet, tvInputs, lbInputs, tvOutputs, tvSend, tvPurge, tvError, tvMessage, tvIssuer, tvIssuerData, tvBlockchain, tvLastInput, tvLastOutput, lbLastOutput, tvValidationNode; TextView tvHeader, tvCaution; ImageView imgLookup; @@ -110,7 +110,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre private VerifyCardTask verifyCardTask = null; private int requestPIN2Count = 0; - public LoadedWalletActivityFragment() { + public LoadedWalletFragment() { } @@ -136,14 +136,14 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre String nodeAddress = engine.GetNextNode(mCard); int nodePort = engine.GetNextNodePort(mCard); UpdateWalletInfoTask connectTaskEx = new UpdateWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(mCard.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet())); } String nodeAddress = engine.GetNode(mCard); int nodePort = engine.GetNodePort(mCard); UpdateWalletInfoTask updateWalletInfoTask = new UpdateWalletInfoTask(nodeAddress, nodePort, data); updateTasks.add(updateWalletInfoTask); - updateWalletInfoTask.execute(Electrum_Request.ListUnspent(mCard.getWallet()), Electrum_Request.ListHistory(mCard.getWallet())); + updateWalletInfoTask.execute(ElectrumRequest.ListUnspent(mCard.getWallet()), ElectrumRequest.ListHistory(mCard.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "bitcoin", "bitcoin"); @@ -156,7 +156,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre String nodeAddress = engine.GetNextNode(mCard); int nodePort = engine.GetNextNodePort(mCard); UpdateWalletInfoTask connectTaskEx = new UpdateWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(mCard.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(mCard.getWallet())); } String nodeAddress = engine.GetNode(mCard); @@ -164,7 +164,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre UpdateWalletInfoTask updateWalletInfoTask = new UpdateWalletInfoTask(nodeAddress, nodePort, data); updateTasks.add(updateWalletInfoTask); - updateWalletInfoTask.execute(Electrum_Request.ListUnspent(mCard.getWallet()), Electrum_Request.ListHistory(mCard.getWallet())); + updateWalletInfoTask.execute(ElectrumRequest.ListUnspent(mCard.getWallet()), ElectrumRequest.ListHistory(mCard.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(mCard.getWallet(), "bitcoin-cash", "bitcoin-cash"); @@ -263,7 +263,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre mSwipeRefreshLayout = v.findViewById(R.id.swipe_container); mSwipeRefreshLayout.setOnRefreshListener(this); - mCard = new Tangem_Card(getActivity().getIntent().getStringExtra("UID")); + mCard = new TangemCard(getActivity().getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getActivity().getIntent().getExtras().getBundle("Card")); tvCardID = v.findViewById(R.id.tvCardID); @@ -784,14 +784,14 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre int nodePort = engine.GetNodePort(mCard); UpdateWalletInfoTask connectTask = new UpdateWalletInfoTask(nodeAddress, nodePort); - connectTask.execute(Electrum_Request.Broadcast(mCard.getWallet(), tx)); + connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx)); } else if (mCard.getBlockchain() == Blockchain.BitcoinCash ||mCard.getBlockchain() == Blockchain.BitcoinCashTestNet) { String nodeAddress = engine.GetNode(mCard); int nodePort = engine.GetNodePort(mCard); UpdateWalletInfoTask connectTask = new UpdateWalletInfoTask(nodeAddress, nodePort); - connectTask.execute(Electrum_Request.Broadcast(mCard.getWallet(), tx)); + connectTask.execute(ElectrumRequest.Broadcast(mCard.getWallet(), tx)); } } @@ -872,7 +872,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre getActivity().finish(); } else { if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) { - Tangem_Card updatedCard = new Tangem_Card(data.getStringExtra("UID")); + TangemCard updatedCard = new TangemCard(data.getStringExtra("UID")); updatedCard.LoadFromBundle(data.getBundleExtra("Card")); mCard = updatedCard; } @@ -914,7 +914,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre getActivity().finish(); } else { if (data != null && data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) { - Tangem_Card updatedCard = new Tangem_Card(data.getStringExtra("UID")); + TangemCard updatedCard = new TangemCard(data.getStringExtra("UID")); updatedCard.LoadFromBundle(data.getBundleExtra("Card")); mCard = updatedCard; } @@ -949,7 +949,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre if (data != null) { if (data.getExtras().containsKey("UID") && data.getExtras().containsKey("Card")) { - Tangem_Card updatedCard = new Tangem_Card(data.getStringExtra("UID")); + TangemCard updatedCard = new TangemCard(data.getStringExtra("UID")); updatedCard.LoadFromBundle(data.getBundleExtra("Card")); mCard = updatedCard; } @@ -1054,7 +1054,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre UpdateViews(); } - private class ETHRequestTask extends Infura_Task { + private class ETHRequestTask extends InfuraTask { ETHRequestTask(Blockchain blockchain) { super(blockchain); } @@ -1316,7 +1316,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre } } - private class UpdateWalletInfoTask extends Electrum_Task { + private class UpdateWalletInfoTask extends ElectrumTask { public UpdateWalletInfoTask(String host, int port) { super(host, port); } @@ -1339,17 +1339,17 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre } @Override - protected void onPostExecute(List requests) { + protected void onPostExecute(List requests) { super.onPostExecute(requests); Log.i("RequestWalletInfoTask", "onPostExecute[" + String.valueOf(updateTasks.size()) + "]"); updateTasks.remove(this); CoinEngine engine = CoinEngineFactory.Create(mCard.getBlockchain()); - for (Electrum_Request request : requests) { + for (ElectrumRequest request : requests) { try { if (request.error == null) { - if (request.isMethod(Electrum_Request.METHOD_GetBalance)) { + if (request.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { String mWalletAddress = request.getParams().getString(0); Long confBalance = request.getResult().getLong("confirmed"); @@ -1379,7 +1379,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre engine.SwitchNode(mCard); } } - } else if (request.isMethod(Electrum_Request.METHOD_SendTransaction)) { + } else if (request.isMethod(ElectrumRequest.METHOD_SendTransaction)) { try { String hashTX = request.getResultString(); @@ -1403,7 +1403,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre ErrorOnUpdate("Failed to send transaction. Try again."); engine.SwitchNode(mCard); } - } else if (request.isMethod(Electrum_Request.METHOD_ListUnspent)) { + } else if (request.isMethod(ElectrumRequest.METHOD_ListUnspent)) { try { String mWalletAddress = request.getParams().getString(0); @@ -1412,7 +1412,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre mCard.getUnspentTransactions().clear(); for (int i = 0; i < jsUnspentArray.length(); i++) { JSONObject jsUnspent = jsUnspentArray.getJSONObject(i); - Tangem_Card.UnspentTransaction trUnspent = new Tangem_Card.UnspentTransaction(); + TangemCard.UnspentTransaction trUnspent = new TangemCard.UnspentTransaction(); trUnspent.txID = jsUnspent.getString("tx_hash"); trUnspent.Amount = jsUnspent.getInt("value"); trUnspent.Height = jsUnspent.getInt("height"); @@ -1435,8 +1435,8 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre updateTasks.add(updateWalletInfoTask); - updateWalletInfoTask.execute(Electrum_Request.GetHeader(mWalletAddress, String.valueOf(height)), - Electrum_Request.GetTransaction(mWalletAddress, hash)); + updateWalletInfoTask.execute(ElectrumRequest.GetHeader(mWalletAddress, String.valueOf(height)), + ElectrumRequest.GetTransaction(mWalletAddress, hash)); } } } catch (JSONException e) { @@ -1444,7 +1444,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre ErrorOnUpdate(e.toString()); engine.SwitchNode(mCard); } - } else if (request.isMethod(Electrum_Request.METHOD_GetHistory)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetHistory)) { try { String mWalletAddress = request.getParams().getString(0); @@ -1453,7 +1453,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre mCard.getHistoryTransactions().clear(); for (int i = 0; i < jsHistoryArray.length(); i++) { JSONObject jsUnspent = jsHistoryArray.getJSONObject(i); - Tangem_Card.HistoryTransaction trHistory = new Tangem_Card.HistoryTransaction(); + TangemCard.HistoryTransaction trHistory = new TangemCard.HistoryTransaction(); trHistory.txID = jsUnspent.getString("tx_hash"); trHistory.Height = jsUnspent.getInt("height"); mCard.getHistoryTransactions().add(trHistory); @@ -1475,8 +1475,8 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre UpdateWalletInfoTask updateWalletInfoTask = new UpdateWalletInfoTask(nodeAddress, nodePort); updateTasks.add(updateWalletInfoTask); - updateWalletInfoTask.execute(Electrum_Request.GetHeader(mWalletAddress, String.valueOf(height)), - Electrum_Request.GetTransaction(mWalletAddress, hash)); + updateWalletInfoTask.execute(ElectrumRequest.GetHeader(mWalletAddress, String.valueOf(height)), + ElectrumRequest.GetTransaction(mWalletAddress, hash)); } } @@ -1485,12 +1485,12 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre ErrorOnUpdate(e.toString()); engine.SwitchNode(mCard); } - } else if (request.isMethod(Electrum_Request.METHOD_GetHeader)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetHeader)) { try { JSONObject jsHeader = request.getResult(); try { mCard.getHaedersInfo(); - mCard.UpdateHeaderInfo(new Tangem_Card.HeaderInfo( + mCard.UpdateHeaderInfo(new TangemCard.HeaderInfo( jsHeader.getInt("block_height"), jsHeader.getInt("timestamp"))); } catch (JSONException e) { @@ -1506,21 +1506,21 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre engine.SwitchNode(mCard); } - } else if (request.isMethod(Electrum_Request.METHOD_GetTransaction)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetTransaction)) { try { String txHash = request.TxHash; String raw = request.getResultString(); - List listTx = mCard.getUnspentTransactions(); - for (Tangem_Card.UnspentTransaction tx : listTx) { + List listTx = mCard.getUnspentTransactions(); + for (TangemCard.UnspentTransaction tx : listTx) { if (tx.txID.equals(txHash)) { tx.Raw = raw; } } - List listHTx = mCard.getHistoryTransactions(); - for (Tangem_Card.HistoryTransaction tx : listHTx) { + List listHTx = mCard.getHistoryTransactions(); + for (TangemCard.HistoryTransaction tx : listHTx) { if (tx.txID.equals(txHash)) { tx.Raw = raw; try { @@ -1529,7 +1529,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre boolean isOur = false; for (byte[] hash : prevHashes) { String checkID = BTCUtils.toHex(hash); - for (Tangem_Card.HistoryTransaction txForCheck : listHTx) { + for (TangemCard.HistoryTransaction txForCheck : listHTx) { if (txForCheck.txID == checkID) { isOur = true; } @@ -1587,7 +1587,7 @@ public class LoadedWalletActivityFragment extends Fragment implements SwipeRefre public static class PINSwapWarningDialog extends DialogFragment { - LoadedWalletActivityFragment activityFragment = null; + LoadedWalletFragment activityFragment = null; String message; @Override diff --git a/app/src/main/java/com/tangem/presentation/fragment/MainActivityFragment.java b/app/src/main/java/com/tangem/presentation/fragment/MainFragment.java similarity index 92% rename from app/src/main/java/com/tangem/presentation/fragment/MainActivityFragment.java rename to app/src/main/java/com/tangem/presentation/fragment/MainFragment.java index 48c1237287..d1b2921ae5 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/MainActivityFragment.java +++ b/app/src/main/java/com/tangem/presentation/fragment/MainFragment.java @@ -24,28 +24,28 @@ import android.view.ViewGroup; import android.widget.ProgressBar; import android.widget.Toast; +import com.tangem.data.network.request.ElectrumRequest; import com.tangem.domain.cardReader.CardProtocol; import com.tangem.domain.cardReader.NfcManager; -import com.tangem.domain.cardReader.Util; +import com.tangem.domain.wallet.TangemCard; +import com.tangem.util.Util; import com.tangem.presentation.activity.EmptyWalletActivity; import com.tangem.presentation.activity.LoadedWalletActivity; import com.tangem.presentation.activity.MainActivity; import com.tangem.presentation.activity.RequestPINActivity; -import com.tangem.wallet.Blockchain; +import com.tangem.domain.wallet.Blockchain; import com.tangem.presentation.adapter.CardListAdapter; -import com.tangem.wallet.CoinEngine; -import com.tangem.wallet.CoinEngineFactory; -import com.tangem.data.network.request.Electrum_Request; -import com.tangem.data.network.task.Electrum_Task; +import com.tangem.domain.wallet.CoinEngine; +import com.tangem.domain.wallet.CoinEngineFactory; +import com.tangem.data.network.task.ElectrumTask; import com.tangem.data.network.request.ExchangeRequest; import com.tangem.data.network.task.ExchangeTask; -import com.tangem.wallet.Infura_Request; -import com.tangem.data.network.task.Infura_Task; +import com.tangem.domain.wallet.Infura_Request; +import com.tangem.data.network.task.InfuraTask; import com.tangem.presentation.dialog.NoExtendedLengthSupportDialog; -import com.tangem.wallet.PINStorage; +import com.tangem.domain.wallet.PINStorage; import com.tangem.wallet.R; -import com.tangem.wallet.SharedData; -import com.tangem.wallet.Tangem_Card; +import com.tangem.domain.wallet.SharedData; import com.tangem.presentation.dialog.WaitSecurityDelayDialog; import org.json.JSONArray; @@ -60,14 +60,14 @@ import java.util.List; /** * A placeholder fragment containing a simple view. */ -public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderCallback, CardListAdapter.UiCallbacks, CardProtocol.Notifications, MainActivity.OnCardsClean { +public class MainFragment extends Fragment implements NfcAdapter.ReaderCallback, CardListAdapter.UiCallbacks, CardProtocol.Notifications, MainActivity.OnCardsClean { private static final int REQUEST_CODE_SHOW_CARD_ACTIVITY = 1; private static final int REQUEST_CODE_ENTER_PIN_ACTIVITY = 2; private static final int REQUEST_CODE_REQUEST_CAMERA_PERMISSIONS = 3; private NfcManager mNfcManager; private ArrayList slCardUIDs = new ArrayList<>(); - private static final String logTag = "MainActivityFragment"; + private static final String logTag = "MainFragment"; private ProgressBar progressBar; private CardListAdapter mCardListAdapter; @@ -80,7 +80,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC private SwipeRefreshLayout mSwipeRefreshLayout; //TODO: tmp List requestTasks = new ArrayList<>(); - public MainActivityFragment() { + public MainFragment() { } @Override @@ -237,7 +237,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC super.onStop(); } - public void refreshCard(Tangem_Card card) { + public void refreshCard(TangemCard card) { CoinEngine engine = CoinEngineFactory.Create(card.getBlockchain()); if (card.getBlockchain() == Blockchain.Ethereum || card.getBlockchain() == Blockchain.EthereumTestNet) { ETHRequestTask task = new ETHRequestTask(card.getBlockchain()); @@ -261,7 +261,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC String nodeAddress = engine.GetNextNode(card); int nodePort = engine.GetNextNodePort(card); RequestWalletInfoTask connectTaskEx = new RequestWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(card.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(card.getWallet())); } String nodeAddress = engine.GetNode(card); @@ -269,7 +269,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC RequestWalletInfoTask task = new RequestWalletInfoTask(nodeAddress, nodePort); if( mSwipeRefreshLayout!=null ) mSwipeRefreshLayout.setRefreshing(true); //TODO: tmp requestTasks.add(task); - task.execute(Electrum_Request.ListUnspent(card.getWallet()), Electrum_Request.ListHistory(card.getWallet())); + task.execute(ElectrumRequest.ListUnspent(card.getWallet()), ElectrumRequest.ListHistory(card.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(card.getWallet(), "bitcoin", "bitcoin"); taskRate.execute(rate); @@ -282,7 +282,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC String nodeAddress = engine.GetNextNode(card); int nodePort = engine.GetNextNodePort(card); RequestWalletInfoTask connectTaskEx = new RequestWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(card.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(card.getWallet())); } String nodeAddress = engine.GetNode(card); @@ -290,7 +290,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC RequestWalletInfoTask task = new RequestWalletInfoTask(nodeAddress, nodePort); if( mSwipeRefreshLayout!=null ) mSwipeRefreshLayout.setRefreshing(true); //TODO: tmp requestTasks.add(task); - task.execute(Electrum_Request.ListUnspent(card.getWallet()), Electrum_Request.ListHistory(card.getWallet())); + task.execute(ElectrumRequest.ListUnspent(card.getWallet()), ElectrumRequest.ListHistory(card.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(card.getWallet(), "bitcoin-cash", "bitcoin-cash"); taskRate.execute(rate); @@ -319,7 +319,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC } } - public void addCard(final Tangem_Card card) { + public void addCard(final TangemCard card) { if (mCardListAdapter != null) { getActivity().runOnUiThread(new Runnable() { @Override @@ -330,7 +330,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC CoinEngine engine = CoinEngineFactory.Create(card.getBlockchain()); - if (card.getStatus() == Tangem_Card.Status.Loaded) { + if (card.getStatus() == TangemCard.Status.Loaded) { if (card.getBlockchain() == Blockchain.Ethereum || card.getBlockchain() == Blockchain.EthereumTestNet) { ETHRequestTask task = new ETHRequestTask(card.getBlockchain()); @@ -355,7 +355,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC int nodePort = engine.GetNextNodePort(card); RequestWalletInfoTask connectTaskEx = new RequestWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(card.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(card.getWallet())); } String nodeAddress = engine.GetNode(card); @@ -365,7 +365,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if( mSwipeRefreshLayout!=null ) mSwipeRefreshLayout.setRefreshing(true); //TODO: tmp requestTasks.add(task); - task.execute(Electrum_Request.ListUnspent(card.getWallet()), Electrum_Request.ListHistory(card.getWallet())); + task.execute(ElectrumRequest.ListUnspent(card.getWallet()), ElectrumRequest.ListHistory(card.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(card.getWallet(), "bitcoin", "bitcoin"); taskRate.execute(rate); @@ -378,7 +378,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC int nodePort = engine.GetNextNodePort(card); RequestWalletInfoTask connectTaskEx = new RequestWalletInfoTask(nodeAddress, nodePort, data); - connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, Electrum_Request.CheckBalance(card.getWallet())); + connectTaskEx.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, ElectrumRequest.CheckBalance(card.getWallet())); } String nodeAddress = engine.GetNode(card); @@ -388,7 +388,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if( mSwipeRefreshLayout!=null ) mSwipeRefreshLayout.setRefreshing(true); //TODO: tmp requestTasks.add(task); - task.execute(Electrum_Request.ListUnspent(card.getWallet()), Electrum_Request.ListHistory(card.getWallet())); + task.execute(ElectrumRequest.ListUnspent(card.getWallet()), ElectrumRequest.ListHistory(card.getWallet())); RateInfoTask taskRate = new RateInfoTask(); ExchangeRequest rate = ExchangeRequest.GetRate(card.getWallet(), "bitcoin-cash", "bitcoin-cash"); taskRate.execute(rate); @@ -431,17 +431,17 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if( mSwipeRefreshLayout!=null ) mSwipeRefreshLayout.setRefreshing(false); //TODO: tmp String UID = cardInfo.getString("UID"); - Tangem_Card card = new Tangem_Card(UID); + TangemCard card = new TangemCard(UID); card.LoadFromBundle(cardInfo.getBundle("Card")); Intent intent; - if (card.getStatus() == Tangem_Card.Status.Empty) { + if (card.getStatus() == TangemCard.Status.Empty) { intent = new Intent(getActivity(), EmptyWalletActivity.class); - } else if (card.getStatus() == Tangem_Card.Status.Loaded) { + } else if (card.getStatus() == TangemCard.Status.Loaded) { intent = new Intent(getActivity(), LoadedWalletActivity.class); - } else if (card.getStatus() == Tangem_Card.Status.NotPersonalized || card.getStatus() == Tangem_Card.Status.Purged) { + } else if (card.getStatus() == TangemCard.Status.NotPersonalized || card.getStatus() == TangemCard.Status.Purged) { return; } else { intent = new Intent(getActivity(), LoadedWalletActivity.class); @@ -457,7 +457,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC // если пришло ОК if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_SHOW_CARD_ACTIVITY) { if (data != null && data.getExtras().containsKey("UID")) { - final Tangem_Card card = new Tangem_Card(data.getStringExtra("UID")); + final TangemCard card = new TangemCard(data.getStringExtra("UID")); card.LoadFromBundle(data.getBundleExtra("Card")); if (data.getStringExtra("modification").equals("delete")) { mCardListAdapter.removeCard(card); @@ -501,7 +501,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC private static String lastRead_UID = ""; private static ArrayList lastRead_UnsuccessfullPINs = new ArrayList<>(); - private static Tangem_Card.EncryptionMode lastRead_Encryption = null; + private static TangemCard.EncryptionMode lastRead_Encryption = null; private class ReadCardInfoTask extends Thread { @@ -569,7 +569,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if (lastRead_Encryption == null) { // we try get supported encryption on this time lastRead_Encryption = protocol.getCard().encryptionMode; - if (protocol.getCard().encryptionMode == Tangem_Card.EncryptionMode.None) { + if (protocol.getCard().encryptionMode == TangemCard.EncryptionMode.None) { // default pin not accepted lastRead_UnsuccessfullPINs.add(PINStorage.getDefaultPIN()); } @@ -594,7 +594,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC try { protocol.setPIN(PIN); - if (protocol.getCard().encryptionMode != Tangem_Card.EncryptionMode.None) { + if (protocol.getCard().encryptionMode != TangemCard.EncryptionMode.None) { protocol.CreateProtocolKey(); } protocol.run_Read(); @@ -752,7 +752,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC WaitSecurityDelayDialog.onReadAfterRequest(getActivity()); } - private class RequestWalletInfoTask extends Electrum_Task { + private class RequestWalletInfoTask extends ElectrumTask { public RequestWalletInfoTask(String host, int port) { super(host, port); } @@ -780,18 +780,18 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC } @Override - protected void onPostExecute(List requests) { + protected void onPostExecute(List requests) { super.onPostExecute(requests); requestTasks.remove(this); Log.i("RequestWalletInfoTask", "onPostExecute[" + String.valueOf(requests.size()) + "]"); CoinEngine engine = CoinEngineFactory.Create(Blockchain.Bitcoin); - for (Electrum_Request request : requests) { + for (ElectrumRequest request : requests) { try { if (request.error == null) { - if (request.isMethod(Electrum_Request.METHOD_GetBalance)) { + if (request.isMethod(ElectrumRequest.METHOD_GetBalance)) { try { Long conf = request.getResult().getLong("confirmed"); Long unconf = request.getResult().getLong("unconfirmed"); @@ -817,7 +817,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC engine.SwitchNode(null); } } - } else if (request.isMethod(Electrum_Request.METHOD_ListUnspent)) { + } else if (request.isMethod(ElectrumRequest.METHOD_ListUnspent)) { try { String mWalletAddress = request.getParams().getString(0); mCardListAdapter.UpdateWalletUnspent(mWalletAddress, request.getResultArray()); @@ -831,8 +831,8 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if (height != -1) { RequestWalletInfoTask task = new RequestWalletInfoTask(request.Host, request.Port); requestTasks.add(task); - task.execute(Electrum_Request.GetHeader(mWalletAddress, String.valueOf(height)), - Electrum_Request.GetTransaction(mWalletAddress, hash)); + task.execute(ElectrumRequest.GetHeader(mWalletAddress, String.valueOf(height)), + ElectrumRequest.GetTransaction(mWalletAddress, hash)); } } } catch (JSONException e) { @@ -840,7 +840,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC FinishWithError(request.WalletAddress, e.toString()); engine.SwitchNode(null); } - } else if (request.isMethod(Electrum_Request.METHOD_GetHistory)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetHistory)) { try { String mWalletAddress = request.getParams().getString(0); mCardListAdapter.UpdateWalletHistory(mWalletAddress, request.getResultArray()); @@ -855,8 +855,8 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC RequestWalletInfoTask task = new RequestWalletInfoTask(request.Host, request.Port); requestTasks.add(task); - task.execute(Electrum_Request.GetHeader(mWalletAddress, String.valueOf(height)), - Electrum_Request.GetTransaction(mWalletAddress, hash)); + task.execute(ElectrumRequest.GetHeader(mWalletAddress, String.valueOf(height)), + ElectrumRequest.GetTransaction(mWalletAddress, hash)); } } } catch (JSONException e) { @@ -864,7 +864,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC FinishWithError(request.WalletAddress, e.toString()); engine.SwitchNode(null); } - } else if (request.isMethod(Electrum_Request.METHOD_GetHeader)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetHeader)) { try { String mWalletAddress = request.WalletAddress; @@ -875,7 +875,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC FinishWithError(request.WalletAddress, e.toString()); engine.SwitchNode(null); } - } else if (request.isMethod(Electrum_Request.METHOD_GetTransaction)) { + } else if (request.isMethod(ElectrumRequest.METHOD_GetTransaction)) { try { Log.e("MainActivityFragment_TX", request.TxHash); String mWalletAddress = request.WalletAddress; @@ -926,7 +926,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC } - private class ETHRequestTask extends Infura_Task { + private class ETHRequestTask extends InfuraTask { ETHRequestTask(Blockchain blockchain) { super(blockchain); } @@ -969,7 +969,7 @@ public class MainActivityFragment extends Fragment implements NfcAdapter.ReaderC if (l.compareTo(BigInteger.ZERO) == 0) { mCardListAdapter.UpdateWalletBlockchain(mWalletAddress, Blockchain.Ethereum); mCardListAdapter.AddWalletBlockchainNameToken(mWalletAddress); - Tangem_Card card = mCardListAdapter.getCardByWallet(request.WalletAddress); + TangemCard card = mCardListAdapter.getCardByWallet(request.WalletAddress); if (card != null) { refreshCard(card); } diff --git a/app/src/main/java/com/tangem/presentation/fragment/VerifyCardActivityFragment.java b/app/src/main/java/com/tangem/presentation/fragment/VerifyCardFragment.java similarity index 96% rename from app/src/main/java/com/tangem/presentation/fragment/VerifyCardActivityFragment.java rename to app/src/main/java/com/tangem/presentation/fragment/VerifyCardFragment.java index f37a84d807..022b2323f6 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/VerifyCardActivityFragment.java +++ b/app/src/main/java/com/tangem/presentation/fragment/VerifyCardFragment.java @@ -16,23 +16,23 @@ import android.widget.TextView; import android.widget.Toast; import com.tangem.domain.cardReader.NfcManager; +import com.tangem.domain.wallet.TangemCard; 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 { +public class VerifyCardFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener, NfcAdapter.ReaderCallback { - Tangem_Card mCard; + TangemCard 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 VerifyCardFragment() { } @@ -53,7 +53,7 @@ public class VerifyCardActivityFragment extends Fragment implements SwipeRefresh mSwipeRefreshLayout = v.findViewById(R.id.swipe_container); mSwipeRefreshLayout.setOnRefreshListener(this); - mCard = new Tangem_Card(getActivity().getIntent().getStringExtra("UID")); + mCard = new TangemCard(getActivity().getIntent().getStringExtra("UID")); mCard.LoadFromBundle(getActivity().getIntent().getExtras().getBundle("Card")); tvCardID = v.findViewById(R.id.tvCardID); @@ -166,7 +166,7 @@ public class VerifyCardActivityFragment extends Fragment implements SwipeRefresh tvSigningMethod.setText(mCard.getSigningMethod().getDescription()); - if (mCard.getStatus() == Tangem_Card.Status.Loaded || mCard.getStatus() == Tangem_Card.Status.Purged) { + if (mCard.getStatus() == TangemCard.Status.Loaded || mCard.getStatus() == TangemCard.Status.Purged) { tvLastSigned.setText(mCard.getLastSignedDescription()); if (mCard.getRemainingSignatures() == 0) { @@ -285,7 +285,7 @@ public class VerifyCardActivityFragment extends Fragment implements SwipeRefresh ivDeveloperVersion.setVisibility(View.INVISIBLE); } - if (mCard.getStatus() == Tangem_Card.Status.Loaded) { + if (mCard.getStatus() == TangemCard.Status.Loaded) { tvWallet.setText(mCard.getShortWalletString()); if (mCard.isWalletPublicKeyValid()) { tvWalletIdentity.setText("Possession proved"); diff --git a/app/src/main/java/com/tangem/presentation/fragment/WalletInfoFragment.java b/app/src/main/java/com/tangem/presentation/fragment/WalletInfoFragment.java index c6260930d2..c6bed94eee 100644 --- a/app/src/main/java/com/tangem/presentation/fragment/WalletInfoFragment.java +++ b/app/src/main/java/com/tangem/presentation/fragment/WalletInfoFragment.java @@ -21,7 +21,7 @@ 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 com.tangem.domain.wallet.TangemCard; import java.util.Hashtable; @@ -38,7 +38,7 @@ import static android.content.Context.CLIPBOARD_SERVICE; public class WalletInfoFragment extends Fragment { // TODO: Rename and change types of parameters - private Tangem_Card mCard; + private TangemCard mCard; private OnFragmentInteractionListener mListener; @@ -53,7 +53,7 @@ public class WalletInfoFragment extends Fragment { * @return A new instance of fragment WalletInfoFragment. */ // TODO: Rename and change types and number of parameters - public static WalletInfoFragment newInstance(Tangem_Card card) { + public static WalletInfoFragment newInstance(TangemCard card) { WalletInfoFragment fragment = new WalletInfoFragment(); Bundle args = new Bundle(); args.putString("UID",card.getUID()); @@ -66,7 +66,7 @@ public class WalletInfoFragment extends Fragment { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { - mCard = new Tangem_Card(getArguments().getString("UID")); + mCard = new TangemCard(getArguments().getString("UID")); mCard.LoadFromBundle(getArguments()); } } diff --git a/app/src/main/java/com/tangem/wallet/PhoneUtility.java b/app/src/main/java/com/tangem/util/PhoneUtility.java similarity index 95% rename from app/src/main/java/com/tangem/wallet/PhoneUtility.java rename to app/src/main/java/com/tangem/util/PhoneUtility.java index 7e04e1b7fc..9ea7beada5 100644 --- a/app/src/main/java/com/tangem/wallet/PhoneUtility.java +++ b/app/src/main/java/com/tangem/util/PhoneUtility.java @@ -1,35 +1,37 @@ -package com.tangem.wallet; - -import android.os.Build; - -/** - * Created by Ilia on 20.04.2018. - */ - -public class PhoneUtility { - public static String GetPhoneName() - { - return DeviceName.getDeviceName(); - - } - - public static String getDeviceInfo() { - StringBuilder stringBuilder = new StringBuilder(); - - stringBuilder.append("----------------------------------------\n"); - stringBuilder.append("MODEL: ").append(Build.MODEL).append("\n"); - stringBuilder.append("ID: ").append(Build.ID).append("\n"); - stringBuilder.append("Manufacturer: ").append(Build.MANUFACTURER).append("\n"); - stringBuilder.append("Brand: ").append(Build.BRAND).append("\n"); - stringBuilder.append("Hardware: ").append(Build.HARDWARE).append("\n"); - stringBuilder.append("Version: ").append(Build.VERSION.RELEASE).append(", ").append(Build.VERSION.INCREMENTAL).append("\n"); - stringBuilder.append("OS: ").append(Build.VERSION.BASE_OS).append("\n"); - stringBuilder.append("SDK: ").append(Build.VERSION.SDK_INT).append("\n"); - stringBuilder.append("BOARD: ").append(Build.BOARD).append("\n"); - stringBuilder.append("FINGERPRINT: ").append(Build.FINGERPRINT).append("\n"); - stringBuilder.append("----------------------------------------\n"); - - return stringBuilder.toString(); - - } -} +package com.tangem.util; + +import android.os.Build; + +import com.tangem.domain.wallet.DeviceName; + +/** + * Created by Ilia on 20.04.2018. + */ + +public class PhoneUtility { + public static String GetPhoneName() + { + return DeviceName.getDeviceName(); + + } + + public static String getDeviceInfo() { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append("----------------------------------------\n"); + stringBuilder.append("MODEL: ").append(Build.MODEL).append("\n"); + stringBuilder.append("ID: ").append(Build.ID).append("\n"); + stringBuilder.append("Manufacturer: ").append(Build.MANUFACTURER).append("\n"); + stringBuilder.append("Brand: ").append(Build.BRAND).append("\n"); + stringBuilder.append("Hardware: ").append(Build.HARDWARE).append("\n"); + stringBuilder.append("Version: ").append(Build.VERSION.RELEASE).append(", ").append(Build.VERSION.INCREMENTAL).append("\n"); + stringBuilder.append("OS: ").append(Build.VERSION.BASE_OS).append("\n"); + stringBuilder.append("SDK: ").append(Build.VERSION.SDK_INT).append("\n"); + stringBuilder.append("BOARD: ").append(Build.BOARD).append("\n"); + stringBuilder.append("FINGERPRINT: ").append(Build.FINGERPRINT).append("\n"); + stringBuilder.append("----------------------------------------\n"); + + return stringBuilder.toString(); + + } +} diff --git a/app/src/main/java/com/tangem/domain/cardReader/Util.java b/app/src/main/java/com/tangem/util/Util.java similarity index 99% rename from app/src/main/java/com/tangem/domain/cardReader/Util.java rename to app/src/main/java/com/tangem/util/Util.java index f03605a7f9..7bf0fd2132 100644 --- a/app/src/main/java/com/tangem/domain/cardReader/Util.java +++ b/app/src/main/java/com/tangem/util/Util.java @@ -1,4 +1,4 @@ -package com.tangem.domain.cardReader; +package com.tangem.util; import android.text.format.DateUtils; diff --git a/app/src/main/java/com/tangem/wallet/CoinEngine.java b/app/src/main/java/com/tangem/wallet/CoinEngine.java deleted file mode 100644 index cdb6688911..0000000000 --- a/app/src/main/java/com/tangem/wallet/CoinEngine.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.tangem.wallet; - -import android.net.Uri; - -import com.tangem.domain.cardReader.CardProtocol; - -import java.security.NoSuchAlgorithmException; -import java.security.NoSuchProviderException; - -/** - * Created by Ilia on 15.02.2018. - */ - -public abstract class CoinEngine { - - public abstract String GetNextNode(Tangem_Card mCard); - - public abstract int GetNextNodePort(Tangem_Card mCard); - - public abstract String GetNode(Tangem_Card mCard); - - public abstract int GetNodePort(Tangem_Card mCard); - - public abstract void SwitchNode(Tangem_Card mCard); - - public abstract boolean AwaitingConfirmation(Tangem_Card card); - - public abstract boolean HasBalanceInfo(Tangem_Card card); - - public abstract boolean IsBalanceNotZero(Tangem_Card card); - - public abstract boolean IsBalanceAlterNotZero(Tangem_Card card); - - public abstract boolean CheckAmount(Tangem_Card card, String amount) throws Exception; - - public abstract int GetTokenDecimals(Tangem_Card card); - - public abstract String GetContractAddress(Tangem_Card card); - - public abstract byte[] Sign(String feeValue, String amountValue, String toValue, Tangem_Card mCard, CardProtocol protocol) throws Exception; - - public abstract boolean CheckUnspentTransaction(Tangem_Card mCard); - - public abstract Uri getShareWalletURIExplorer(Tangem_Card mCard); - - public abstract Long GetBalanceLong(Tangem_Card mCard); - - public abstract Uri getShareWalletURI(Tangem_Card mCard); - - public abstract String EvaluteFeeEquivalent(Tangem_Card mCard, String fee); - - public abstract boolean CheckAmountValie(Tangem_Card mCard, String amount, String fee, Long minFeeInInternalUnits); - - public abstract boolean InOutPutVisible(); - - public abstract String GetBalance(Tangem_Card mCard); - - public abstract String GetBalanceWithAlter(Tangem_Card mCard); - - public abstract String GetBalanceCurrency(Tangem_Card card); - - public abstract String GetFeeCurrency(); - - public abstract boolean IsNeedCheckNode(); - - public abstract String GetBalanceEquivalent(Tangem_Card mCard); - - public abstract String GetBalanceValue(Tangem_Card mCard); - - public abstract String GetAmountDescription(Tangem_Card mCard, String amount) throws Exception; - - public abstract String GetAmountEqualentDescriptor(Tangem_Card mCard, String value); - - public abstract boolean ValdateAddress(String address, Tangem_Card catd); - - public abstract String calculateAddress(Tangem_Card mCard, byte[] pkUncompressed) throws NoSuchProviderException, NoSuchAlgorithmException; - - public abstract String ConvertByteArrayToAmount(Tangem_Card mCard, byte[] bytes) throws Exception; - - public abstract byte[] ConvertAmountToByteArray(Tangem_Card mCard, String amount) throws Exception; - -} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_logo.xml b/app/src/main/res/layout/activity_logo.xml index 333c6ca2ad..9115764ffd 100644 --- a/app/src/main/res/layout/activity_logo.xml +++ b/app/src/main/res/layout/activity_logo.xml @@ -5,7 +5,7 @@ android:background="#FFFFFF" android:gravity="bottom" android:orientation="vertical" - tools:context="com.tangem.wallet.com.tangem.presentation.activity.LogoActivity"> + tools:context="com.tangem.presentation.activity.LogoActivity">