Merge pull request #231 from zcash/release/1.3.0-beta14
Release/1.3.0 beta14
This commit is contained in:
commit
81266f01e5
|
@ -1,6 +1,12 @@
|
|||
Change Log
|
||||
==========
|
||||
|
||||
Version 1.3.0-beta14 *(2021-06-21)*
|
||||
------------------------------------
|
||||
- New: Add separate flows for sapling, orchard and tranparent balances.
|
||||
- Fix: Continue troubleshooting and fixing server disconnects.
|
||||
- Updated dependencies.
|
||||
|
||||
Version 1.3.0-beta12 *(2021-06-07)*
|
||||
------------------------------------
|
||||
- New: Expose network height as StateFlow.
|
||||
|
|
|
@ -9,8 +9,8 @@ targetSdkVersion = 30
|
|||
|
||||
publish {
|
||||
group = 'cash.z.ecc.android'
|
||||
versionName = '1.3.0-beta12'
|
||||
versionCode = 1_03_00_212 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
|
||||
versionName = '1.3.0-beta14'
|
||||
versionCode = 1_03_00_214 // last digits are alpha(0XX) beta(2XX) rc(4XX) release(8XX). Ex: 1_08_04_401 is an release candidate build of version 1.8.4 and 1_08_04_800 would be the final release.
|
||||
artifactId = 'zcash-android-sdk'
|
||||
target = 'release'
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<lint>
|
||||
<!-- Generated by `./gradlew refreshVersions` to avoid errors when using _ as a version. -->
|
||||
<issue id="GradlePluginVersion" severity="ignore" />
|
||||
<issue id="GradleDependency" severity="ignore" />
|
||||
</lint>
|
|
@ -1,10 +1,9 @@
|
|||
import de.fayard.refreshVersions.RefreshVersionsSetup
|
||||
|
||||
buildscript {
|
||||
repositories { gradlePluginPortal() }
|
||||
dependencies.classpath("de.fayard.refreshVersions:refreshVersions:0.9.7")
|
||||
}
|
||||
plugins {
|
||||
// See https://jmfayard.github.io/refreshVersions
|
||||
id 'de.fayard.refreshVersions' version '0.10.1'
|
||||
}
|
||||
|
||||
RefreshVersionsSetup.bootstrap(settings)
|
||||
|
||||
rootProject.name = 'zcash-android-sdk'
|
||||
|
|
|
@ -56,7 +56,7 @@ class TestnetIntegrationTest : ScopedTest() {
|
|||
@Test
|
||||
fun testBalance() = runBlocking {
|
||||
var availableBalance: Long = 0L
|
||||
synchronizer.balances.onFirst {
|
||||
synchronizer.saplingBalances.onFirst {
|
||||
availableBalance = it.availableZatoshi
|
||||
}
|
||||
|
||||
|
@ -74,7 +74,7 @@ class TestnetIntegrationTest : ScopedTest() {
|
|||
@Ignore
|
||||
fun testSpend() = runBlocking {
|
||||
var success = false
|
||||
synchronizer.balances.filter { it.availableZatoshi > 0 }.onEach {
|
||||
synchronizer.saplingBalances.filter { it.availableZatoshi > 0 }.onEach {
|
||||
success = sendFunds()
|
||||
}.first()
|
||||
log("asserting $success")
|
||||
|
|
|
@ -31,6 +31,6 @@ class ShieldFundsSample {
|
|||
// wallet.shieldFunds()
|
||||
|
||||
Twig.clip("ShieldFundsSample")
|
||||
Assert.assertEquals(5, wallet.synchronizer.latestBalance.availableZatoshi)
|
||||
Assert.assertEquals(5, wallet.synchronizer.saplingBalances.value.availableZatoshi)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -206,7 +206,7 @@ class DarksideTestCoordinator(val wallet: TestWallet) {
|
|||
}
|
||||
|
||||
fun validateMinBalance(available: Long = -1, total: Long = -1) {
|
||||
val balance = synchronizer.latestBalance
|
||||
val balance = synchronizer.saplingBalances.value
|
||||
if (available > 0) {
|
||||
assertTrue("invalid available balance. Expected a minimum of $available but found ${balance.availableZatoshi}", available <= balance.availableZatoshi)
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ class TestWallet(
|
|||
val synchronizer: SdkSynchronizer = Synchronizer(initializer) as SdkSynchronizer
|
||||
val service = (synchronizer.processor.downloader.lightWalletService as LightWalletGrpcService)
|
||||
|
||||
val available get() = synchronizer.latestBalance.availableZatoshi
|
||||
val available get() = synchronizer.saplingBalances.value.availableZatoshi
|
||||
val shieldedAddress = DerivationTool.deriveShieldedAddress(seed, network = network)
|
||||
val transparentAddress = DerivationTool.deriveTransparentAddress(seed, network = network)
|
||||
val birthdayHeight get() = synchronizer.latestBirthdayHeight
|
||||
|
|
|
@ -66,8 +66,10 @@ import kotlinx.coroutines.SupervisorJob
|
|||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.channels.ConflatedBroadcastChannel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
|
@ -99,7 +101,12 @@ class SdkSynchronizer internal constructor(
|
|||
private val txManager: OutboundTransactionManager,
|
||||
val processor: CompactBlockProcessor
|
||||
) : Synchronizer {
|
||||
private val _balances = ConflatedBroadcastChannel(WalletBalance())
|
||||
|
||||
// pools
|
||||
private val _orchardBalances = MutableStateFlow(WalletBalance())
|
||||
private val _saplingBalances = MutableStateFlow(WalletBalance())
|
||||
private val _transparentBalances = MutableStateFlow(WalletBalance())
|
||||
|
||||
private val _status = ConflatedBroadcastChannel<Synchronizer.Status>(DISCONNECTED)
|
||||
|
||||
/**
|
||||
|
@ -133,11 +140,18 @@ class SdkSynchronizer internal constructor(
|
|||
|
||||
override var isStarted = false
|
||||
|
||||
//
|
||||
// Balances
|
||||
//
|
||||
|
||||
override val orchardBalances = _orchardBalances.asStateFlow()
|
||||
override val saplingBalances = _saplingBalances.asStateFlow()
|
||||
override val transparentBalances = _transparentBalances.asStateFlow()
|
||||
|
||||
//
|
||||
// Transactions
|
||||
//
|
||||
|
||||
override val balances: Flow<WalletBalance> = _balances.asFlow()
|
||||
override val clearedTransactions get() = storage.allTransactions
|
||||
override val pendingTransactions = txManager.getAll()
|
||||
override val sentTransactions get() = storage.sentTransactions
|
||||
|
@ -223,12 +237,6 @@ class SdkSynchronizer internal constructor(
|
|||
// Public API
|
||||
//
|
||||
|
||||
/**
|
||||
* Convenience function for the latest balance. Instead of using this, a wallet will more likely
|
||||
* want to consume the flow of balances using [balances].
|
||||
*/
|
||||
override val latestBalance: WalletBalance get() = _balances.value
|
||||
|
||||
/**
|
||||
* Convenience function for the latest height. Specifically, this value represents the last
|
||||
* height that the synchronizer has observed from the lightwalletd server. Instead of using
|
||||
|
@ -284,8 +292,6 @@ class SdkSynchronizer internal constructor(
|
|||
processor.stop()
|
||||
twig("Synchronizer::stop: coroutineScope.cancel()")
|
||||
coroutineScope.cancel()
|
||||
twig("Synchronizer::stop: _balances.cancel()")
|
||||
_balances.cancel()
|
||||
twig("Synchronizer::stop: _status.cancel()")
|
||||
_status.cancel()
|
||||
twig("Synchronizer::stop: COMPLETE")
|
||||
|
@ -359,9 +365,21 @@ class SdkSynchronizer internal constructor(
|
|||
* Calculate the latest balance, based on the blocks that have been scanned and transmit this
|
||||
* information into the flow of [balances].
|
||||
*/
|
||||
suspend fun refreshBalance() {
|
||||
twig("refreshing balance")
|
||||
_balances.send(processor.getBalanceInfo())
|
||||
suspend fun refreshAllBalances() {
|
||||
refreshSaplingBalance()
|
||||
refreshTransparentBalance()
|
||||
// TODO: refresh orchard balance
|
||||
twig("Warning: Orchard balance does not yet refresh. Only some of the plumbing is in place.")
|
||||
}
|
||||
|
||||
suspend fun refreshSaplingBalance() {
|
||||
twig("refreshing sapling balance")
|
||||
_saplingBalances.value = processor.getBalanceInfo()
|
||||
}
|
||||
|
||||
suspend fun refreshTransparentBalance() {
|
||||
twig("refreshing transparent balance")
|
||||
_transparentBalances.value = processor.getUtxoCacheBalance(getTransparentAddress())
|
||||
}
|
||||
|
||||
suspend fun isValidAddress(address: String): Boolean {
|
||||
|
@ -501,7 +519,7 @@ class SdkSynchronizer internal constructor(
|
|||
refreshUtxos()
|
||||
}
|
||||
twigTask("Triggering balance refresh since $reason!") {
|
||||
refreshBalance()
|
||||
refreshAllBalances()
|
||||
}
|
||||
twigTask("Triggering pending transaction refresh since $reason!") {
|
||||
refreshPendingTransactions()
|
||||
|
@ -578,7 +596,7 @@ class SdkSynchronizer internal constructor(
|
|||
twig("[cleanup] deleting expired transactions from storage")
|
||||
hasCleaned = hasCleaned || (storage.deleteExpired(lastScannedHeight) > 0)
|
||||
|
||||
if (hasCleaned) refreshBalance()
|
||||
if (hasCleaned) refreshAllBalances()
|
||||
twig("[cleanup] done refreshing and cleaning up pending transactions")
|
||||
}
|
||||
|
||||
|
@ -619,7 +637,7 @@ class SdkSynchronizer internal constructor(
|
|||
// only submit if it wasn't cancelled. Otherwise cleanup, immediately for best UX.
|
||||
if (encodedTx.isCancelled()) {
|
||||
twig("[cleanup] this tx has been cancelled so we will cleanup instead of submitting")
|
||||
if (cleanupCancelledTx(encodedTx)) refreshBalance()
|
||||
if (cleanupCancelledTx(encodedTx)) refreshAllBalances()
|
||||
encodedTx
|
||||
} else {
|
||||
txManager.submit(encodedTx)
|
||||
|
@ -650,7 +668,7 @@ class SdkSynchronizer internal constructor(
|
|||
// only submit if it wasn't cancelled. Otherwise cleanup, immediately for best UX.
|
||||
if (encodedTx.isCancelled()) {
|
||||
twig("[cleanup] this shielding tx has been cancelled so we will cleanup instead of submitting")
|
||||
if (cleanupCancelledTx(encodedTx)) refreshBalance()
|
||||
if (cleanupCancelledTx(encodedTx)) refreshAllBalances()
|
||||
encodedTx
|
||||
} else {
|
||||
txManager.submit(encodedTx)
|
||||
|
|
|
@ -100,9 +100,19 @@ interface Synchronizer {
|
|||
val networkHeight: StateFlow<Int>
|
||||
|
||||
/**
|
||||
* A stream of balance values, separately reflecting both the available and total balance.
|
||||
* A stream of balance values for the orchard pool. Includes the available and total balance.
|
||||
*/
|
||||
val balances: Flow<WalletBalance>
|
||||
val orchardBalances: Flow<WalletBalance>
|
||||
|
||||
/**
|
||||
* A stream of balance values for the sapling pool. Includes the available and total balance.
|
||||
*/
|
||||
val saplingBalances: Flow<WalletBalance>
|
||||
|
||||
/**
|
||||
* A stream of balance values for the transparent pool. Includes the available and total balance.
|
||||
*/
|
||||
val transparentBalances: Flow<WalletBalance>
|
||||
|
||||
/* Transactions */
|
||||
|
||||
|
@ -136,11 +146,6 @@ interface Synchronizer {
|
|||
*/
|
||||
val latestHeight: Int
|
||||
|
||||
/**
|
||||
* An in-memory reference to the most recently calculated balance.
|
||||
*/
|
||||
val latestBalance: WalletBalance
|
||||
|
||||
/**
|
||||
* An in-memory reference to the best known birthday height, which can change if the first
|
||||
* transaction has not yet occurred.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package cash.z.ecc.android.sdk.block // iimport cash.z.ecc.android.sdk.exception.LightWalletException
|
||||
import cash.z.ecc.android.sdk.exception.LightWalletException
|
||||
import cash.z.ecc.android.sdk.ext.retryUpTo
|
||||
import cash.z.ecc.android.sdk.ext.tryWarn
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.sdk.service.LightWalletService
|
||||
|
@ -77,13 +78,17 @@ open class CompactBlockDownloader private constructor(val compactBlockStore: Com
|
|||
}
|
||||
|
||||
suspend fun getServerInfo(): Service.LightdInfo = withContext<Service.LightdInfo>(IO) {
|
||||
lateinit var result: Service.LightdInfo
|
||||
try {
|
||||
lightWalletService.getServerInfo()
|
||||
result = lightWalletService.getServerInfo()
|
||||
} catch (e: StatusRuntimeException) {
|
||||
twig("WARNING: reconnecting to service in response to failure: $e")
|
||||
lightWalletService.reconnect()
|
||||
lightWalletService.getServerInfo()
|
||||
retryUpTo(2) {
|
||||
twig("WARNING: reconnecting to service in response to failure (retry #${it + 1}): $e")
|
||||
lightWalletService.reconnect()
|
||||
result = lightWalletService.getServerInfo()
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
suspend fun changeService(
|
||||
|
|
|
@ -11,6 +11,7 @@ import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc
|
|||
import cash.z.wallet.sdk.rpc.Service
|
||||
import com.google.protobuf.ByteString
|
||||
import io.grpc.Channel
|
||||
import io.grpc.ConnectivityState
|
||||
import io.grpc.ManagedChannel
|
||||
import io.grpc.android.AndroidChannelBuilder
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
@ -66,20 +67,17 @@ class LightWalletGrpcService private constructor(
|
|||
override fun getBlockRange(heightRange: IntRange): List<CompactFormats.CompactBlock> {
|
||||
if (heightRange.isEmpty()) return listOf()
|
||||
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub(streamingRequestTimeoutSec)
|
||||
return requireChannel().createStub(streamingRequestTimeoutSec)
|
||||
.getBlockRange(heightRange.toBlockRange()).toList()
|
||||
}
|
||||
|
||||
override fun getLatestBlockHeight(): Int {
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub(singleRequestTimeoutSec)
|
||||
return requireChannel().createStub(singleRequestTimeoutSec)
|
||||
.getLatestBlock(Service.ChainSpec.newBuilder().build()).height.toInt()
|
||||
}
|
||||
|
||||
override fun getServerInfo(): Service.LightdInfo {
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub(singleRequestTimeoutSec)
|
||||
return requireChannel().createStub(singleRequestTimeoutSec)
|
||||
.getLightdInfo(Service.Empty.newBuilder().build())
|
||||
}
|
||||
|
||||
|
@ -92,11 +90,10 @@ class LightWalletGrpcService private constructor(
|
|||
)
|
||||
.build()
|
||||
}
|
||||
channel.resetConnectBackoff()
|
||||
val request =
|
||||
Service.RawTransaction.newBuilder().setData(ByteString.copyFrom(spendTransaction))
|
||||
.build()
|
||||
return channel.createStub().sendTransaction(request)
|
||||
return requireChannel().createStub().sendTransaction(request)
|
||||
}
|
||||
|
||||
override fun shutdown() {
|
||||
|
@ -107,8 +104,7 @@ class LightWalletGrpcService private constructor(
|
|||
override fun fetchTransaction(txId: ByteArray): Service.RawTransaction? {
|
||||
if (txId.isEmpty()) return null
|
||||
|
||||
channel.resetConnectBackoff()
|
||||
return channel.createStub().getTransaction(
|
||||
return requireChannel().createStub().getTransaction(
|
||||
Service.TxFilter.newBuilder().setHash(ByteString.copyFrom(txId)).build()
|
||||
)
|
||||
}
|
||||
|
@ -117,8 +113,7 @@ class LightWalletGrpcService private constructor(
|
|||
tAddress: String,
|
||||
startHeight: Int
|
||||
): List<Service.GetAddressUtxosReply> {
|
||||
channel.resetConnectBackoff()
|
||||
val result = channel.createStub().getAddressUtxos(
|
||||
val result = requireChannel().createStub().getAddressUtxos(
|
||||
Service.GetAddressUtxosArg.newBuilder().setAddress(tAddress)
|
||||
.setStartHeight(startHeight.toLong()).build()
|
||||
)
|
||||
|
@ -131,8 +126,7 @@ class LightWalletGrpcService private constructor(
|
|||
): List<Service.RawTransaction> {
|
||||
if (blockHeightRange.isEmpty() || tAddress.isBlank()) return listOf()
|
||||
|
||||
channel.resetConnectBackoff()
|
||||
val result = channel.createStub().getTaddressTxids(
|
||||
val result = requireChannel().createStub().getTaddressTxids(
|
||||
Service.TransparentAddressBlockFilter.newBuilder().setAddress(tAddress)
|
||||
.setRange(blockHeightRange.toBlockRange()).build()
|
||||
)
|
||||
|
@ -153,6 +147,19 @@ class LightWalletGrpcService private constructor(
|
|||
)
|
||||
}
|
||||
|
||||
// test code
|
||||
var stateCount = 0
|
||||
var state: ConnectivityState? = null
|
||||
private fun requireChannel(): ManagedChannel {
|
||||
state = channel.getState(false).let { new ->
|
||||
if (state == new) stateCount++ else stateCount = 0
|
||||
new
|
||||
}
|
||||
channel.resetConnectBackoff()
|
||||
twig("getting channel isShutdown: ${channel.isShutdown} isTerminated: ${channel.isTerminated} getState: $state stateCount: $stateCount")
|
||||
return channel
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
|
|
@ -1,35 +1,13 @@
|
|||
## suppress inspection "SpellCheckingInspection" for whole file
|
||||
## suppress inspection "UnusedProperty" for whole file
|
||||
##
|
||||
## Dependencies and Plugin versions with their available updates
|
||||
## Generated by $ ./gradlew refreshVersions
|
||||
## Please, don't put extra comments in that file yet, keeping them is not supported yet.
|
||||
#### Dependencies and Plugin versions with their available updates.
|
||||
#### Generated by `./gradlew refreshVersions` version 0.10.1
|
||||
####
|
||||
#### Don't manually edit or split the comments that start with four hashtags (####),
|
||||
#### they will be overwritten by refreshVersions.
|
||||
####
|
||||
#### suppress inspection "SpellCheckingInspection" for whole file
|
||||
#### suppress inspection "UnusedProperty" for whole file
|
||||
|
||||
plugin.android=4.1.3
|
||||
## # available=4.2.0-alpha01
|
||||
## # available=4.2.0-alpha02
|
||||
## # available=4.2.0-alpha03
|
||||
## # available=4.2.0-alpha04
|
||||
## # available=4.2.0-alpha05
|
||||
## # available=4.2.0-alpha06
|
||||
## # available=4.2.0-alpha07
|
||||
## # available=4.2.0-alpha08
|
||||
## # available=4.2.0-alpha09
|
||||
## # available=4.2.0-alpha10
|
||||
## # available=4.2.0-alpha11
|
||||
## # available=4.2.0-alpha12
|
||||
## # available=4.2.0-alpha13
|
||||
## # available=4.2.0-alpha14
|
||||
## # available=4.2.0-alpha15
|
||||
## # available=4.2.0-alpha16
|
||||
## # available=4.2.0-beta01
|
||||
## # available=4.2.0-beta02
|
||||
## # available=4.2.0-beta03
|
||||
## # available=4.2.0-beta04
|
||||
## # available=4.2.0-beta05
|
||||
## # available=4.2.0-beta06
|
||||
## # available=4.2.0-rc01
|
||||
## # available=4.2.0
|
||||
plugin.android=4.2.1
|
||||
## # available=7.0.0-alpha01
|
||||
## # available=7.0.0-alpha02
|
||||
## # available=7.0.0-alpha03
|
||||
|
@ -45,13 +23,22 @@ plugin.android=4.1.3
|
|||
## # available=7.0.0-alpha13
|
||||
## # available=7.0.0-alpha14
|
||||
## # available=7.0.0-alpha15
|
||||
## # available=7.0.0-beta01
|
||||
## # available=7.0.0-beta02
|
||||
## # available=7.0.0-beta03
|
||||
## # available=7.0.0-beta04
|
||||
## # available=7.1.0-alpha01
|
||||
## # available=7.1.0-alpha02
|
||||
|
||||
version.androidx.appcompat=1.3.0-rc01
|
||||
version.androidx.appcompat=1.3.0
|
||||
## # available=1.4.0-alpha01
|
||||
## # available=1.4.0-alpha02
|
||||
|
||||
version.androidx.arch.core=2.1.0
|
||||
|
||||
version.androidx.lifecycle=2.3.1
|
||||
## # available=2.4.0-alpha01
|
||||
## # available=2.4.0-alpha02
|
||||
|
||||
version.androidx.multidex=2.0.1
|
||||
|
||||
|
@ -74,34 +61,18 @@ version.androidx.paging=2.1.2
|
|||
## # available=3.0.0-beta03
|
||||
## # available=3.0.0-rc01
|
||||
## # available=3.0.0
|
||||
## # available=3.1.0-alpha01
|
||||
|
||||
version.androidx.room=2.3.0
|
||||
## # available=2.4.0-alpha01
|
||||
## # available=2.4.0-alpha02
|
||||
## # available=2.4.0-alpha03
|
||||
|
||||
version.androidx.test=1.3.0
|
||||
## # available=1.3.1-alpha01
|
||||
## # available=1.3.1-alpha02
|
||||
## # available=1.3.1-alpha03
|
||||
## # available=1.4.0-alpha04
|
||||
## # available=1.4.0-alpha05
|
||||
## # available=1.4.0-alpha06
|
||||
version.androidx.test=1.4.0-beta02
|
||||
|
||||
version.androidx.test.core=1.3.0
|
||||
## # available=1.3.1-alpha01
|
||||
## # available=1.3.1-alpha02
|
||||
## # available=1.3.1-alpha03
|
||||
## # available=1.4.0-alpha04
|
||||
## # available=1.4.0-alpha05
|
||||
## # available=1.4.0-alpha06
|
||||
version.androidx.test.core=1.4.0-beta02
|
||||
|
||||
version.androidx.test.ext.junit=1.1.2
|
||||
## # available=1.1.3-alpha01
|
||||
## # available=1.1.3-alpha02
|
||||
## # available=1.1.3-alpha03
|
||||
## # available=1.1.3-alpha04
|
||||
## # available=1.1.3-alpha05
|
||||
## # available=1.1.3-alpha06
|
||||
version.androidx.test.ext.junit=1.1.3-beta02
|
||||
|
||||
version.cash.z.ecc.android..kotlin-bip39=1.0.2
|
||||
|
||||
|
@ -115,43 +86,51 @@ version.com.nhaarman.mockitokotlin2..mockito-kotlin=2.2.0
|
|||
|
||||
version.com.vanniktech..gradle-maven-publish-plugin=0.15.1
|
||||
|
||||
version.io.grpc..grpc-android=1.37.0
|
||||
version.io.grpc..grpc-android=1.38.1
|
||||
|
||||
version.io.grpc..grpc-okhttp=1.37.0
|
||||
version.io.grpc..grpc-okhttp=1.38.1
|
||||
|
||||
version.io.grpc..grpc-protobuf-lite=1.37.0
|
||||
version.io.grpc..grpc-protobuf-lite=1.38.1
|
||||
|
||||
version.io.grpc..grpc-stub=1.37.0
|
||||
version.io.grpc..grpc-stub=1.38.1
|
||||
|
||||
version.io.grpc..grpc-testing=1.37.0
|
||||
version.io.grpc..grpc-testing=1.38.1
|
||||
|
||||
version.javax.annotation..javax.annotation-api=1.3.2
|
||||
|
||||
version.kotlin=1.4.32
|
||||
## # available=1.5.0-M1
|
||||
## # available=1.5.0-M2
|
||||
## # available=1.5.0-RC
|
||||
## # available=1.5.0
|
||||
version.junit=5.7.2
|
||||
### available=5.8.0-M1
|
||||
|
||||
version.kotlinx.coroutines=1.4.3
|
||||
## # available=1.5.0-RC-native-mt
|
||||
## # available=1.5.0-RC
|
||||
version.kotlin=1.5.10
|
||||
## # available=1.5.20-M1
|
||||
## # available=1.5.20-RC
|
||||
|
||||
version.kotlinx.coroutines=1.5.0
|
||||
|
||||
version.mockito=3.11.1
|
||||
|
||||
version.org.jetbrains.dokka..dokka-gradle-plugin=1.4.32
|
||||
|
||||
version.org.junit.jupiter..junit-jupiter-api=5.7.1
|
||||
version.org.junit.jupiter..junit-jupiter-api=5.7.2
|
||||
## # available=5.7.2
|
||||
## # available=5.8.0-M1
|
||||
|
||||
version.org.junit.jupiter..junit-jupiter-engine=5.7.1
|
||||
version.org.junit.jupiter..junit-jupiter-engine=5.7.2
|
||||
## # available=5.7.2
|
||||
## # available=5.8.0-M1
|
||||
|
||||
version.org.junit.jupiter..junit-jupiter-migrationsupport=5.7.1
|
||||
version.org.junit.jupiter..junit-jupiter-migrationsupport=5.7.2
|
||||
## # available=5.7.2
|
||||
## # available=5.8.0-M1
|
||||
|
||||
version.org.mockito..mockito-android=3.10.0
|
||||
version.org.mockito..mockito-android=3.11.1
|
||||
## # available=3.11.0
|
||||
## # available=3.11.1
|
||||
|
||||
version.org.mockito..mockito-junit-jupiter=3.10.0
|
||||
version.org.mockito..mockito-junit-jupiter=3.11.1
|
||||
## # available=3.11.0
|
||||
## # available=3.11.1
|
||||
|
||||
version.org.owasp..dependency-check-gradle=6.1.6
|
||||
version.org.owasp..dependency-check-gradle=6.2.2
|
||||
|
||||
version.ru.gildor.coroutines..kotlin-coroutines-okhttp=1.0
|
||||
|
|
Loading…
Reference in New Issue