Updated on 2026-08-14

This commit is contained in:
Tangem 2019-04-02 10:55:09 +03:00
parent ce7b5e9f84
commit 517d3e1ccd
5 changed files with 198 additions and 21 deletions

View file

@ -55,6 +55,10 @@ android {
buildToolsVersion '28.0.3'
}
configurations {
all*.exclude group: 'com.google.guava', module: 'listenablefuture'
}
dependencies {
implementation project(':card-common')
implementation project(':card-android')
@ -64,12 +68,12 @@ dependencies {
// implementation 'com.github.TangemCash:card-android:0.1.3'
// implementation 'com.github.TangemCash:server-android:0.1.4'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
implementation 'androidx.biometric:biometric:1.0.0-alpha03'
implementation 'co.nstant.in:cbor:0.8'
implementation 'com.google.android.material:material:1.1.0-alpha02'
implementation 'com.google.android.material:material:1.1.0-alpha05'
implementation 'com.google.dagger:dagger:2.21'
kapt 'com.google.dagger:dagger-compiler:2.21'
annotationProcessor 'com.google.dagger:dagger-compiler:2.21'
@ -94,5 +98,7 @@ dependencies {
implementation 'io.reactivex.rxjava2:rxjava:2.2.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.0.2'
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.0.0"
//implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
}

View file

@ -61,14 +61,14 @@ class LogoActivity : AppCompatActivity() {
}
private fun hide() {
when (BuildConfig.FLAVOR) {
Constant.FLAVOR_TANGEM_CARDANO -> {
navigator.showPrepareTransaction(this)
}
else -> {
// when (BuildConfig.FLAVOR) {
// Constant.FLAVOR_TANGEM_CARDANO -> {
// navigator.showPrepareTransaction(this)
// }
// else -> {
navigator.showMain(this)
}
}
// }
// }
finish()
}

View file

@ -1,3 +1,5 @@
@file:Suppress("ObsoleteExperimentalCoroutines")
package com.tangem.ui.activity
import android.Manifest
@ -25,14 +27,23 @@ import com.tangem.card_android.android.nfc.NfcDeviceAntennaLocation
import com.tangem.card_android.android.nfc.NfcLifecycleObserver
import com.tangem.card_android.android.reader.NfcManager
import com.tangem.card_android.android.reader.NfcReader
import com.tangem.card_android.data.EXTRA_TANGEM_CARD
import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
import com.tangem.card_android.data.loadFromBundle
import com.tangem.card_android.data.saveToBundle
import com.tangem.card_common.data.TangemCard
import com.tangem.card_common.reader.CardProtocol
import com.tangem.card_common.tasks.CustomReadCardTask
import com.tangem.card_common.tasks.OneTouchSignTask
import com.tangem.card_common.tasks.ReadCardInfoTask
import com.tangem.card_common.tasks.SignTask
import com.tangem.card_common.util.Log
import com.tangem.data.Blockchain
import com.tangem.data.Logger
import com.tangem.data.network.ServerApiCommon
import com.tangem.di.Navigator
import com.tangem.di.ToastHelper
import com.tangem.domain.wallet.CoinEngine
import com.tangem.domain.wallet.CoinEngineFactory
import com.tangem.domain.wallet.TangemContext
import com.tangem.ui.dialog.NoExtendedLengthSupportDialog
@ -48,9 +59,9 @@ import kotlinx.android.synthetic.main.layout_touch_card.*
import java.io.File
import java.util.*
import javax.inject.Inject
import com.tangem.card_android.data.EXTRA_TANGEM_CARD
import com.tangem.card_android.data.EXTRA_TANGEM_CARD_UID
import com.tangem.di.ToastHelper
import kotlinx.coroutines.runBlocking
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtocol.Notifications, PopupMenu.OnMenuItemClickListener {
@ -70,7 +81,8 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
private lateinit var nfcDeviceAntenna: NfcDeviceAntennaLocation
private var unsuccessReadCount = 0
private var lastTag: Tag? = null
private var readCardInfoTask: ReadCardInfoTask? = null
// private var readCardInfoTask: ReadCardInfoTask? = null
private var task: CustomReadCardTask? = null
private var onNfcReaderCallback: NfcAdapter.ReaderCallback? = null
override fun onNewIntent(intent: Intent?) {
@ -234,8 +246,77 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
lastTag = tag
readCardInfoTask = ReadCardInfoTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this)
readCardInfoTask?.start()
// readCardInfoTask = ReadCardInfoTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this)
//readCardInfoTask?.start()
val tx: OneTouchSignTask.TransactionToSign = object : OneTouchSignTask.TransactionToSign {
var txToSign: SignTask.TransactionToSign?=null
var ctx: TangemContext?=null
var coinEngine: CoinEngine?=null
val amount: CoinEngine.Amount=CoinEngine.Amount(10,"")
val fee: CoinEngine.Amount=CoinEngine.Amount(1,"")
val incFee: Boolean = true
val targetAddress: String = "aaaa"
suspend fun requestBalanceAndUnspentTransactions(): Boolean = suspendCoroutine { cont ->
coinEngine!!.requestBalanceAndUnspentTransactions(object : CoinEngine.BlockchainRequestsCallbacks {
override fun onComplete(success: Boolean?) {
cont.resume(success!!)
}
override fun onProgress() {
}
override fun allowAdvance(): Boolean {
return true
}
})
}
fun initData(card: TangemCard)
{
if( ctx==null ) ctx= TangemContext(card)
if( coinEngine==null ) {
coinEngine=CoinEngineFactory.createCardano(ctx!!)!!
coinEngine!!.defineWallet()
runBlocking { requestBalanceAndUnspentTransactions() }
Log.e(TAG, "requestBalanceAndUnspentTransactions completed")
}
if( txToSign==null ) txToSign=coinEngine!!.constructTransaction(amount,fee,true, targetAddress)
}
override fun isSigningOnCardSupported(card: TangemCard?): Boolean {
initData(card!!)
return (card?.blockchainID==Blockchain.Cardano.id)and(txToSign!!.isSigningMethodSupported(card?.signingMethod))
}
override fun getHashesToSign(card: TangemCard?): Array<ByteArray> {
initData(card!!)
return txToSign!!.hashesToSign
}
override fun getRawDataToSign(card: TangemCard?): ByteArray {
initData(card!!)
return txToSign!!.rawDataToSign
}
override fun getHashAlgToSign(card: TangemCard?): String {
initData(card!!)
return txToSign!!.hashAlgToSign
}
override fun getIssuerTransactionSignature(card: TangemCard?, dataToSignByIssuer: ByteArray?): ByteArray {
initData(card!!)
return txToSign!!.getIssuerTransactionSignature(dataToSignByIssuer)
}
override fun onSignCompleted(card: TangemCard?, signature: ByteArray?) {
initData(card!!)
txToSign!!.onSignCompleted(signature)
}
}
task = OneTouchSignTask(NfcReader(nfcManager, isoDep), App.localStorage, App.pinStorage, this, tx)
task?.start()
} catch (e: Exception) {
e.printStackTrace()
nfcManager.notifyReadResult(false)
@ -249,12 +330,12 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
}
public override fun onPause() {
readCardInfoTask?.cancel(true)
task?.cancel(true)
super.onPause()
}
public override fun onStop() {
readCardInfoTask?.cancel(true)
task?.cancel(true)
super.onStop()
}
@ -267,7 +348,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
}
override fun onReadFinish(cardProtocol: CardProtocol?) {
readCardInfoTask = null
task = null
if (cardProtocol != null) {
if (cardProtocol.error == null) {
nfcManager.notifyReadResult(true)
@ -333,7 +414,7 @@ class MainActivity : AppCompatActivity(), NfcAdapter.ReaderCallback, CardProtoco
}
override fun onReadCancel() {
readCardInfoTask = null
task = null
ReadCardInfoTask.resetLastReadInfo()
rlProgressBar.postDelayed({
try {

View file

@ -0,0 +1,90 @@
package com.tangem.card_common.tasks;
import com.tangem.card_common.data.TangemCard;
import com.tangem.card_common.data.external.CardDataSubstitutionProvider;
import com.tangem.card_common.data.external.PINsProvider;
import com.tangem.card_common.reader.CardProtocol;
import com.tangem.card_common.reader.NfcReader;
import com.tangem.card_common.reader.TLV;
import com.tangem.card_common.reader.TLVList;
import com.tangem.card_common.util.Log;
import java.io.ByteArrayOutputStream;
public class OneTouchSignTask extends ReadCardInfoTask {
public static final String TAG = OneTouchSignTask.class.getSimpleName();
/**
* Transaction Engine request/notifications during sign process
*/
public interface TransactionToSign {
boolean isSigningOnCardSupported(TangemCard card);
byte[][] getHashesToSign(TangemCard card) throws Exception;
byte[] getRawDataToSign(TangemCard card) throws Exception;
String getHashAlgToSign(TangemCard card) throws Exception;
byte[] getIssuerTransactionSignature(TangemCard card, byte[] dataToSignByIssuer) throws Exception;
void onSignCompleted(TangemCard card, byte[] signature) throws Exception;
}
private TransactionToSign transactionToSign;
public OneTouchSignTask(NfcReader reader, CardDataSubstitutionProvider cardDataSubstitutionProvider, PINsProvider pinsProvider, CardProtocol.Notifications notifications, TransactionToSign transactionToSign) {
super(reader, cardDataSubstitutionProvider, pinsProvider, notifications);
this.transactionToSign = transactionToSign;
}
@Override
public void run_Task() throws Exception {
super.run_Task();
Log.i(TAG, "Manufacturer: " + protocol.getCard().getManufacturer().getOfficialName());
mNotifications.onReadProgress(protocol, 30);
if (isCancelled) return;
if (mCard.getPauseBeforePIN2() > 0) {
mNotifications.onReadWait(mCard.getPauseBeforePIN2());
}
if (!transactionToSign.isSigningOnCardSupported(mCard)) {
throw new CardProtocol.TangemException("Signing method isn't supported!");
}
TLVList signResult;
switch (mCard.getSigningMethod()) {
case Sign_Hash:
signResult = protocol.run_SignHashes(pinsProvider.getPIN2(), transactionToSign.getHashesToSign(mCard), null, null, null);
break;
case Sign_Hash_Validated_By_Issuer:
case Sign_Hash_Validated_By_Issuer_And_WriteIssuerData:
ByteArrayOutputStream bs = new ByteArrayOutputStream();
byte[][] hashes = transactionToSign.getHashesToSign(mCard);
if (hashes.length > 10) throw new CardProtocol.TangemException("To much hashes in one transaction!");
for (int i = 0; i < hashes.length; i++) {
if (i != 0 && hashes[0].length != hashes[i].length)
throw new CardProtocol.TangemException("Hashes length must be identical!");
bs.write(hashes[i]);
}
signResult = protocol.run_SignHashes(pinsProvider.getPIN2(), hashes, transactionToSign.getIssuerTransactionSignature(mCard, bs.toByteArray()), null, null);
break;
case Sign_Raw:
signResult = protocol.run_SignRaw(pinsProvider.getPIN2(), transactionToSign.getHashAlgToSign(mCard), transactionToSign.getRawDataToSign(mCard), null, null, null);
break;
case Sign_Raw_Validated_By_Issuer:
case Sign_Raw_Validated_By_Issuer_And_WriteIssuerData:
byte[] txOut = transactionToSign.getRawDataToSign(mCard);
signResult = protocol.run_SignRaw(pinsProvider.getPIN2(), transactionToSign.getHashAlgToSign(mCard), txOut, transactionToSign.getIssuerTransactionSignature(mCard, txOut), null, null);
break;
default:
throw new CardProtocol.TangemException("Signing method isn't supported!");
}
transactionToSign.onSignCompleted(mCard, signResult.getTLV(TLV.Tag.TAG_Signature).Value);
mNotifications.onReadProgress(protocol, 100);
}
}

View file

@ -29,7 +29,7 @@ dependencies {
implementation project(':card-common')
// implementation 'com.github.TangemCash.card_android-common:card_android-android:0.1.0'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
implementation 'com.squareup.retrofit2:retrofit:2.5.0'