diff --git a/README.md b/README.md index a3fe7460..3e821c7f 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Then add the following dependency to your module's build.gradle ```gradle dependencies { ... - implementation "com.metallicus:protonsdk:0.5.5" + implementation "com.metallicus:protonsdk:0.5.6" } ``` diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 1f997fe0..e40b7f61 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -23,8 +23,8 @@ const val kotlinVersion = "1.4.10" const val orchidVersion = "0.21.1" object ProtonSdk { - const val versionCode = 17 - const val versionName = "0.5.5" + const val versionCode = 18 + const val versionName = "0.5.6" } object BuildPlugins { diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/ActionsModule.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/ActionsModule.kt index 79de8c4a..cf286870 100644 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/ActionsModule.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/ActionsModule.kt @@ -24,6 +24,7 @@ package com.metallicus.protonsdk import android.content.Context import com.google.gson.Gson import com.google.gson.JsonObject +import com.google.gson.JsonParser import com.metallicus.protonsdk.common.Prefs import com.metallicus.protonsdk.common.Resource import com.metallicus.protonsdk.common.SecureKeys @@ -201,11 +202,15 @@ class ActionsModule { ActionTrace(actionTrxId, actionTraceAct)) } - suspend fun transferTokens(chainUrl: String, pin: String, contract: String, from: String, to: String, quantity: String, memo: String): Resource { + suspend fun transferTokens(chainUrl: String, pin: String, contract: String, from: String, + to: String, quantity: String, memo: String): Resource { return try { val eosTransfer = EosTransfer(from, to, quantity, memo) val jsonToBinArgs = eosTransfer.jsonToBinArgs() + val action = Action(contract, eosTransfer.action) + action.setAuthorization(eosTransfer.activePermission) + val jsonToBinResponse = actionRepository.jsonToBin( chainUrl, @@ -217,51 +222,96 @@ class ActionsModule { requireNotNull(jsonToBin) - val action = Action(contract, eosTransfer.action) action.setData(jsonToBin.binArgs) - action.setAuthorization(eosTransfer.activePermission) val signedTransaction = SignedTransaction() signedTransaction.addAction(action) - val chainInfoResponse = actionRepository.getChainInfo(chainUrl) - if (chainInfoResponse.isSuccessful) { - val chainInfo = chainInfoResponse.body() + signAndPushTransaction(chainUrl, pin, signedTransaction) + } else { + val msg = jsonToBinResponse.errorBody()?.string() + val errorMsg = if (msg.isNullOrEmpty()) { + jsonToBinResponse.message() + } else { + msg + } - requireNotNull(chainInfo) + Resource.error(errorMsg) + } + } catch (e: Exception) { + Resource.error(e.localizedMessage.orEmpty()) + } + } - signedTransaction.setReferenceBlock(chainInfo.headBlockId) - signedTransaction.expiration = chainInfo.getTimeAfterHeadBlockTime(30000) + suspend fun pushTransactions(chainUrl: String, pin: String, actions: List): Resource { + try { + if (actions.isNotEmpty()) { + actions.forEach { action -> + val jsonToBinResponse = actionRepository.jsonToBin( + chainUrl, + action.account, + action.name, + JsonParser.parseString(action.data.asString) + ) + if (jsonToBinResponse.isSuccessful) { + val jsonToBin = jsonToBinResponse.body() + + requireNotNull(jsonToBin) + + action.setData(jsonToBin.binArgs) + } else { + val msg = jsonToBinResponse.errorBody()?.string() + val errorMsg = if (msg.isNullOrEmpty()) { + jsonToBinResponse.message() + } else { + msg + } - val publicKey = prefs.getActivePublicKey() + return Resource.error(errorMsg) + } + } + } else { + return Resource.error("No Actions") + } + } catch (e: Exception) { + return Resource.error(e.localizedMessage.orEmpty()) + } - val privateKeyStr = secureKeys.getPrivateKey(publicKey, pin) + val signedTransaction = SignedTransaction() + signedTransaction.actions = actions + return signAndPushTransaction(chainUrl, pin, signedTransaction) + } - require(privateKeyStr != null && privateKeyStr != "") { "No private key found" } + private suspend fun signAndPushTransaction(chainUrl: String, pin: String, signedTransaction: SignedTransaction): Resource { + return try { + val chainInfoResponse = actionRepository.getChainInfo(chainUrl) + if (chainInfoResponse.isSuccessful) { + val chainInfo = chainInfoResponse.body() - val privateKey = EosPrivateKey(privateKeyStr) + requireNotNull(chainInfo) - signedTransaction.sign(privateKey, TypeChainId(chainInfo.chainId)) + signedTransaction.setReferenceBlock(chainInfo.headBlockId) + signedTransaction.expiration = chainInfo.getTimeAfterHeadBlockTime(30000) - val packedTransaction = PackedTransaction(signedTransaction) + val publicKey = prefs.getActivePublicKey() - val pushTransactionResponse = actionRepository.pushTransaction(chainUrl, packedTransaction) - if (pushTransactionResponse.isSuccessful) { - Resource.success(pushTransactionResponse.body()) - } else { - val msg = pushTransactionResponse.errorBody()?.string() - val errorMsg = if (msg.isNullOrEmpty()) { - pushTransactionResponse.message() - } else { - msg - } + val privateKeyStr = secureKeys.getPrivateKey(publicKey, pin) - Resource.error(errorMsg) - } + require(privateKeyStr != null && privateKeyStr != "") { "No private key found" } + + val privateKey = EosPrivateKey(privateKeyStr) + + signedTransaction.sign(privateKey, TypeChainId(chainInfo.chainId)) + + val packedTransaction = PackedTransaction(signedTransaction) + + val pushTransactionResponse = actionRepository.pushTransaction(chainUrl, packedTransaction) + if (pushTransactionResponse.isSuccessful) { + Resource.success(pushTransactionResponse.body()) } else { - val msg = chainInfoResponse.errorBody()?.string() + val msg = pushTransactionResponse.errorBody()?.string() val errorMsg = if (msg.isNullOrEmpty()) { - chainInfoResponse.message() + pushTransactionResponse.message() } else { msg } @@ -269,9 +319,9 @@ class ActionsModule { Resource.error(errorMsg) } } else { - val msg = jsonToBinResponse.errorBody()?.string() + val msg = chainInfoResponse.errorBody()?.string() val errorMsg = if (msg.isNullOrEmpty()) { - jsonToBinResponse.message() + chainInfoResponse.message() } else { msg } diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/CurrencyBalancesModule.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/CurrencyBalancesModule.kt index f1379293..bc289bce 100644 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/CurrencyBalancesModule.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/CurrencyBalancesModule.kt @@ -71,7 +71,7 @@ class CurrencyBalancesModule { currencyBalanceRepository.addCurrencyBalance(currencyBalance) } - val tokenCurrencyBalances = currencyBalanceRepository.getTokenCurrencyBalance(tokenContractId) + val tokenCurrencyBalances = currencyBalanceRepository.getTokenCurrencyBalance(accountName, tokenContractId) Resource.success(tokenCurrencyBalances) } else { diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt index 285a8f5b..2b1b37f2 100644 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/Proton.kt @@ -31,6 +31,7 @@ import com.metallicus.protonsdk.di.DaggerInjector import com.metallicus.protonsdk.di.ProtonModule import com.metallicus.protonsdk.eosio.commander.digest.Sha256 import com.metallicus.protonsdk.eosio.commander.ec.EosPrivateKey +import com.metallicus.protonsdk.eosio.commander.model.chain.Action as ChainAction import com.metallicus.protonsdk.model.* import kotlinx.coroutines.* import timber.log.Timber @@ -402,7 +403,7 @@ class Proton private constructor(context: Context) { } } - fun transferTokens(pin: String, tokenContractId: String, toAccount: String, amount: String, memo: String): LiveData> = liveData { + fun transferTokensByTokenContractId(pin: String, tokenContractId: String, toAccount: String, amount: String, memo: String): LiveData> = liveData { emit(Resource.loading()) try { @@ -426,4 +427,65 @@ class Proton private constructor(context: Context) { emit(error) } } + + fun transferTokensByContract(pin: String, contract: String, toAccount: String, amount: String, memo: String): LiveData> = liveData { + emit(Resource.loading()) + + try { + val activeAccount = getActiveAccountAsync() + + emit(actionsModule.transferTokens( + activeAccount.chainProvider.chainUrl, + pin, + contract, + activeAccount.account.accountName, + toAccount, + amount, + memo)) + } catch (e: ProtonException) { + val error: Resource = Resource.error(e) + emit(error) + } catch (e: Exception) { + val error: Resource = Resource.error(e.localizedMessage.orEmpty()) + emit(error) + } + } + + /*fun pushTransaction(pin: String, action: ChainAction): LiveData> = liveData { + emit(Resource.loading()) + + try { + val activeAccount = getActiveAccountAsync() + + emit(actionsModule.pushTransaction( + activeAccount.chainProvider.chainUrl, + pin, + action)) + } catch (e: ProtonException) { + val error: Resource = Resource.error(e) + emit(error) + } catch (e: Exception) { + val error: Resource = Resource.error(e.localizedMessage.orEmpty()) + emit(error) + } + }*/ + + fun pushTransactions(pin: String, actions: List): LiveData> = liveData { + emit(Resource.loading()) + + try { + val activeAccount = getActiveAccountAsync() + + emit(actionsModule.pushTransactions( + activeAccount.chainProvider.chainUrl, + pin, + actions)) + } catch (e: ProtonException) { + val error: Resource = Resource.error(e) + emit(error) + } catch (e: Exception) { + val error: Resource = Resource.error(e.localizedMessage.orEmpty()) + emit(error) + } + } } \ No newline at end of file diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/db/AccountDao.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/db/AccountDao.kt index 31df6f0f..d01d6952 100755 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/db/AccountDao.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/db/AccountDao.kt @@ -36,7 +36,6 @@ interface AccountDao { @Update suspend fun update(account: Account) - @Transaction @Query("SELECT * FROM account WHERE accountName = :accountName") suspend fun findByAccountName(accountName: String): ChainAccount diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/db/CurrencyBalanceDao.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/db/CurrencyBalanceDao.kt index 1bcda21a..945c6772 100755 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/db/CurrencyBalanceDao.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/db/CurrencyBalanceDao.kt @@ -36,11 +36,9 @@ interface CurrencyBalanceDao { @Query("UPDATE currencyBalance SET amount = :amount WHERE accountName = :accountName AND contract = :contract AND symbol = :symbol") suspend fun updateAmount(accountName: String, contract: String, symbol: String, amount: String) - @Transaction - @Query("SELECT * FROM currencyBalance WHERE tokenContractId = :tokenContractId") - suspend fun findByTokenContract(tokenContractId: String): TokenCurrencyBalance + @Query("SELECT * FROM currencyBalance WHERE accountName = :accountName AND tokenContractId = :tokenContractId") + suspend fun findByTokenContract(accountName: String, tokenContractId: String): TokenCurrencyBalance - @Transaction @Query("SELECT * FROM currencyBalance WHERE accountName = :accountName") suspend fun findByAccountName(accountName: String): List diff --git a/protonsdk/src/main/java/com/metallicus/protonsdk/repository/CurrencyBalanceRepository.kt b/protonsdk/src/main/java/com/metallicus/protonsdk/repository/CurrencyBalanceRepository.kt index bdff9fe6..b2e3332e 100755 --- a/protonsdk/src/main/java/com/metallicus/protonsdk/repository/CurrencyBalanceRepository.kt +++ b/protonsdk/src/main/java/com/metallicus/protonsdk/repository/CurrencyBalanceRepository.kt @@ -46,8 +46,8 @@ class CurrencyBalanceRepository @Inject constructor( return protonChainService.getCurrencyBalances("$chainUrl/v2/state/get_tokens", accountName) } - suspend fun getTokenCurrencyBalance(tokenContractId: String): TokenCurrencyBalance { - return currencyBalanceDao.findByTokenContract(tokenContractId) + suspend fun getTokenCurrencyBalance(accountName: String, tokenContractId: String): TokenCurrencyBalance { + return currencyBalanceDao.findByTokenContract(accountName, tokenContractId) } suspend fun getTokenCurrencyBalances(accountName: String): List {