[#593] Refactor ZcashNetwork
Splits the ZcashNetwork and Lightwalletd server information, making it easier to configure different servers
This commit is contained in:
parent
2362c60dd6
commit
e01a906407
|
@ -1,6 +1,10 @@
|
|||
Change Log
|
||||
==========
|
||||
|
||||
Upcoming
|
||||
------------------------------------
|
||||
- Split `ZcashNetwork` into `ZcashNetwork` and `LightWalletEndpoint` to decouple network and server configuration
|
||||
|
||||
Version 1.8.0-beta01
|
||||
------------------------------------
|
||||
- Added `BlockHeight` typesafe object to represent block heights
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
Troubleshooting Migrations
|
||||
==========
|
||||
|
||||
Upcoming
|
||||
--------------------------------------
|
||||
`ZcashNetwork` is no longer an enum. The prior enum values are now declared as object properties `ZcashNetwork.Mainnet` and `ZcashNetwork.Testnet`. For the most part, this change should have minimal impact. ZcashNetwork was also moved from the package `cash.z.ecc.android.sdk.type` to `cash.z.ecc.android.sdk.model`, which will require a change to your import statements. The server fields have been removed from `ZcashNetwork`, allowing server and network configuration to be done independently.
|
||||
|
||||
`LightWalletEndpoint` is a new object to represent server information. Default values can be obtained from `LightWalletEndpoint.defaultForNetwork(ZcashNetwork)`
|
||||
|
||||
`Synchronizer` no longer allows changing the endpoint after construction. Instead, construct a new `Synchronizer` with the desired endpoint.
|
||||
|
||||
Migration to Version 1.8 from 1.7
|
||||
--------------------------------------
|
||||
Various APIs used `Int` to represent network block heights. Those APIs now use a typesafe `BlockHeight` type. BlockHeight is constructed with a factory method `BlockHeight.new(ZcashNetwork, Long)` which uses the network to validate the height is above the network's sapling activation height.
|
||||
|
||||
`WalletBirthday` has been renamed to `Checkpoint` and removed from the public API. Where clients previously passed in a `WalletBirthday` object, now a `BlockHeight` can be passed in instead.
|
||||
|
|
|
@ -5,7 +5,7 @@ import cash.z.ecc.android.sdk.darkside.test.DarksideTestCoordinator
|
|||
import cash.z.ecc.android.sdk.darkside.test.ScopedTest
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
|
|
@ -4,7 +4,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
|
|||
import cash.z.ecc.android.sdk.darkside.test.DarksideTestCoordinator
|
||||
import cash.z.ecc.android.sdk.darkside.test.ScopedTest
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
|
|
|
@ -5,7 +5,7 @@ import cash.z.ecc.android.sdk.darkside.test.DarksideTestCoordinator
|
|||
import cash.z.ecc.android.sdk.darkside.test.ScopedTest
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package cash.z.ecc.android.sdk.darkside.test
|
||||
|
||||
import android.content.Context
|
||||
import cash.z.ecc.android.sdk.R
|
||||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.Darkside
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.wallet.sdk.rpc.Darkside
|
||||
import cash.z.wallet.sdk.rpc.Darkside.DarksideTransactionsURL
|
||||
import cash.z.wallet.sdk.rpc.DarksideStreamerGrpc
|
||||
|
@ -23,17 +24,11 @@ class DarksideApi(
|
|||
|
||||
constructor(
|
||||
appContext: Context,
|
||||
host: String,
|
||||
port: Int = ZcashNetwork.Mainnet.defaultPort,
|
||||
usePlainText: Boolean = appContext.resources.getBoolean(
|
||||
R.bool.lightwalletd_allow_very_insecure_connections
|
||||
)
|
||||
lightWalletEndpoint: LightWalletEndpoint
|
||||
) : this(
|
||||
LightWalletGrpcService.createDefaultChannel(
|
||||
appContext,
|
||||
host,
|
||||
port,
|
||||
usePlainText
|
||||
lightWalletEndpoint
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
@ -5,7 +5,9 @@ import cash.z.ecc.android.sdk.SdkSynchronizer
|
|||
import cash.z.ecc.android.sdk.Synchronizer
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.Darkside
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import io.grpc.StatusRuntimeException
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.filter
|
||||
|
@ -23,10 +25,9 @@ class DarksideTestCoordinator(val wallet: TestWallet) {
|
|||
alias: String = "DarksideTestCoordinator",
|
||||
seedPhrase: String = DEFAULT_SEED_PHRASE,
|
||||
startHeight: BlockHeight = DEFAULT_START_HEIGHT,
|
||||
host: String = COMPUTER_LOCALHOST,
|
||||
network: ZcashNetwork = ZcashNetwork.Mainnet,
|
||||
port: Int = network.defaultPort
|
||||
) : this(TestWallet(seedPhrase, alias, network, host, startHeight = startHeight, port = port))
|
||||
endpoint: LightWalletEndpoint = LightWalletEndpoint.Darkside
|
||||
) : this(TestWallet(seedPhrase, alias, network, endpoint, startHeight = startHeight))
|
||||
|
||||
private val targetHeight = BlockHeight.new(wallet.network, 663250)
|
||||
private val context = InstrumentationRegistry.getInstrumentation().context
|
||||
|
|
|
@ -11,10 +11,12 @@ import cash.z.ecc.android.sdk.internal.Twig
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.Darkside
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -36,9 +38,8 @@ class TestWallet(
|
|||
val seedPhrase: String,
|
||||
val alias: String = "TestWallet",
|
||||
val network: ZcashNetwork = ZcashNetwork.Testnet,
|
||||
val host: String = network.defaultHost,
|
||||
startHeight: BlockHeight? = null,
|
||||
val port: Int = network.defaultPort
|
||||
val endpoint: LightWalletEndpoint = LightWalletEndpoint.Darkside,
|
||||
startHeight: BlockHeight? = null
|
||||
) {
|
||||
constructor(
|
||||
backup: Backups,
|
||||
|
@ -66,7 +67,7 @@ class TestWallet(
|
|||
runBlocking { DerivationTool.deriveTransparentSecretKey(seed, network = network) }
|
||||
val initializer = runBlocking {
|
||||
Initializer.new(context) { config ->
|
||||
runBlocking { config.importWallet(seed, startHeight, network, host, alias = alias) }
|
||||
runBlocking { config.importWallet(seed, startHeight, network, endpoint, alias = alias) }
|
||||
}
|
||||
}
|
||||
val synchronizer: SdkSynchronizer = runBlocking { Synchronizer.new(initializer) } as SdkSynchronizer
|
||||
|
@ -79,7 +80,6 @@ class TestWallet(
|
|||
runBlocking { DerivationTool.deriveTransparentAddress(seed, network = network) }
|
||||
val birthdayHeight get() = synchronizer.latestBirthdayHeight
|
||||
val networkName get() = synchronizer.network.networkName
|
||||
val connectionInfo get() = service.connectionInfo.toString()
|
||||
|
||||
suspend fun transparentBalance(): WalletBalance {
|
||||
synchronizer.refreshUtxos(transparentAddress, synchronizer.latestBirthdayHeight)
|
||||
|
@ -166,11 +166,46 @@ class TestWallet(
|
|||
|
||||
enum class Backups(val seedPhrase: String, val testnetBirthday: BlockHeight, val mainnetBirthday: BlockHeight) {
|
||||
// TODO: get the proper birthday values for these wallets
|
||||
DEFAULT("column rhythm acoustic gym cost fit keen maze fence seed mail medal shrimp tell relief clip cannon foster soldier shallow refuse lunar parrot banana", BlockHeight.new(ZcashNetwork.Testnet, 1_355_928), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
SAMPLE_WALLET("input frown warm senior anxiety abuse yard prefer churn reject people glimpse govern glory crumble swallow verb laptop switch trophy inform friend permit purpose", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
DEV_WALLET("still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread", BlockHeight.new(ZcashNetwork.Testnet, 1_000_000), BlockHeight.new(ZcashNetwork.Mainnet, 991645)),
|
||||
ALICE("quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
BOB("canvas wine sugar acquire garment spy tongue odor hole cage year habit bullet make label human unit option top calm neutral try vocal arena", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
DEFAULT(
|
||||
"column rhythm acoustic gym cost fit keen maze fence seed mail medal shrimp tell relief clip cannon foster soldier shallow refuse lunar parrot banana",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_355_928
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
SAMPLE_WALLET(
|
||||
"input frown warm senior anxiety abuse yard prefer churn reject people glimpse govern glory crumble swallow verb laptop switch trophy inform friend permit purpose",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
DEV_WALLET(
|
||||
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_000_000
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 991645)
|
||||
),
|
||||
ALICE(
|
||||
"quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
BOB(
|
||||
"canvas wine sugar acquire garment spy tongue odor hole cage year habit bullet make label human unit option top calm neutral try vocal arena",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ import cash.z.ecc.android.sdk.internal.Twig
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.Mainnet
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
|
@ -87,15 +89,18 @@ class SampleCodeTest {
|
|||
// ///////////////////////////////////////////////////
|
||||
// Query latest block height
|
||||
@Test fun getLatestBlockHeightTest() {
|
||||
val lightwalletService = LightWalletGrpcService(context, lightwalletdHost)
|
||||
val lightwalletService = LightWalletGrpcService.new(context, lightwalletdHost)
|
||||
log("Latest Block: ${lightwalletService.getLatestBlockHeight()}")
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Download compact block range
|
||||
@Test fun getBlockRange() {
|
||||
val blockRange = BlockHeight.new(ZcashNetwork.Mainnet, 500_000)..BlockHeight.new(ZcashNetwork.Mainnet, 500_009)
|
||||
val lightwalletService = LightWalletGrpcService(context, lightwalletdHost)
|
||||
val blockRange = BlockHeight.new(ZcashNetwork.Mainnet, 500_000)..BlockHeight.new(
|
||||
ZcashNetwork.Mainnet,
|
||||
500_009
|
||||
)
|
||||
val lightwalletService = LightWalletGrpcService.new(context, lightwalletdHost)
|
||||
val blocks = lightwalletService.getBlockRange(blockRange)
|
||||
assertEquals(blockRange.endInclusive.value - blockRange.start.value, blocks.count())
|
||||
|
||||
|
@ -151,7 +156,7 @@ class SampleCodeTest {
|
|||
|
||||
companion object {
|
||||
private val seed = "Insert seed for testing".toByteArray()
|
||||
private val lightwalletdHost: String = ZcashNetwork.Mainnet.defaultHost
|
||||
private val lightwalletdHost = LightWalletEndpoint.Mainnet
|
||||
|
||||
private val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
private val synchronizer: Synchronizer = run {
|
||||
|
|
|
@ -20,7 +20,9 @@ import androidx.viewbinding.ViewBinding
|
|||
import cash.z.ecc.android.sdk.demoapp.util.fromResources
|
||||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.service.LightWalletService
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
|
||||
|
@ -108,7 +110,11 @@ class MainActivity :
|
|||
if (lightwalletService != null) {
|
||||
lightwalletService?.shutdown()
|
||||
}
|
||||
lightwalletService = LightWalletGrpcService(applicationContext, ZcashNetwork.fromResources(applicationContext))
|
||||
val network = ZcashNetwork.fromResources(applicationContext)
|
||||
lightwalletService = LightWalletGrpcService.new(
|
||||
applicationContext,
|
||||
LightWalletEndpoint.defaultForNetwork(network)
|
||||
)
|
||||
}
|
||||
|
||||
private fun onFabClicked(view: View) {
|
||||
|
|
|
@ -9,9 +9,9 @@ import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
|
|||
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentGetAddressBinding
|
||||
import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
|
||||
import cash.z.ecc.android.sdk.demoapp.util.fromResources
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
|
|
@ -14,9 +14,11 @@ import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
|
|||
import cash.z.ecc.android.sdk.demoapp.util.fromResources
|
||||
import cash.z.ecc.android.sdk.ext.collectWith
|
||||
import cash.z.ecc.android.sdk.ext.convertZatoshiToZecString
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
|
@ -50,8 +52,12 @@ class GetBalanceFragment : BaseDemoFragment<FragmentGetBalanceBinding>() {
|
|||
// using the ViewingKey to initialize
|
||||
runBlocking {
|
||||
Initializer.new(requireApplicationContext(), null) {
|
||||
it.setNetwork(ZcashNetwork.fromResources(requireApplicationContext()))
|
||||
it.newWallet(viewingKey, network = ZcashNetwork.fromResources(requireApplicationContext()))
|
||||
val network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
it.newWallet(
|
||||
viewingKey,
|
||||
network = network,
|
||||
lightWalletEndpoint = LightWalletEndpoint.defaultForNetwork(network)
|
||||
)
|
||||
}
|
||||
}.let { initializer ->
|
||||
synchronizer = Synchronizer.newBlocking(initializer)
|
||||
|
|
|
@ -14,7 +14,7 @@ import cash.z.ecc.android.sdk.demoapp.util.toRelativeTime
|
|||
import cash.z.ecc.android.sdk.demoapp.util.withCommas
|
||||
import cash.z.ecc.android.sdk.ext.toHex
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import kotlin.math.min
|
||||
|
||||
/**
|
||||
|
|
|
@ -13,7 +13,7 @@ import cash.z.ecc.android.sdk.demoapp.util.mainActivity
|
|||
import cash.z.ecc.android.sdk.demoapp.util.toRelativeTime
|
||||
import cash.z.ecc.android.sdk.demoapp.util.withCommas
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import kotlin.math.max
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,8 +9,8 @@ import cash.z.ecc.android.sdk.demoapp.BaseDemoFragment
|
|||
import cash.z.ecc.android.sdk.demoapp.databinding.FragmentGetPrivateKeyBinding
|
||||
import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
|
||||
import cash.z.ecc.android.sdk.demoapp.util.fromResources
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,8 +17,10 @@ import cash.z.ecc.android.sdk.demoapp.ext.requireApplicationContext
|
|||
import cash.z.ecc.android.sdk.demoapp.util.fromResources
|
||||
import cash.z.ecc.android.sdk.ext.collectWith
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
/**
|
||||
|
@ -51,11 +53,13 @@ class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBindin
|
|||
initializer = Initializer.newBlocking(
|
||||
requireApplicationContext(),
|
||||
Initializer.Config {
|
||||
val network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
runBlocking {
|
||||
it.importWallet(
|
||||
seed,
|
||||
birthday = null,
|
||||
network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
network = network,
|
||||
lightWalletEndpoint = LightWalletEndpoint.defaultForNetwork(network)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,10 @@ import cash.z.ecc.android.sdk.demoapp.util.mainActivity
|
|||
import cash.z.ecc.android.sdk.ext.collectWith
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -64,8 +66,15 @@ class ListUtxosFragment : BaseDemoFragment<FragmentListUtxosBinding>() {
|
|||
// have the seed stored
|
||||
seed = Mnemonics.MnemonicCode(sharedViewModel.seedPhrase.value).toSeed()
|
||||
initializer = runBlocking {
|
||||
val network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
Initializer.new(requireApplicationContext()) {
|
||||
runBlocking { it.newWallet(seed, network = ZcashNetwork.fromResources(requireApplicationContext())) }
|
||||
runBlocking {
|
||||
it.newWallet(
|
||||
seed,
|
||||
network = network,
|
||||
lightWalletEndpoint = LightWalletEndpoint.defaultForNetwork(network)
|
||||
)
|
||||
}
|
||||
it.alias = "Demo_Utxos"
|
||||
}
|
||||
}
|
||||
|
@ -96,12 +105,19 @@ class ListUtxosFragment : BaseDemoFragment<FragmentListUtxosBinding>() {
|
|||
val network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
binding.textStatus.requestFocus()
|
||||
val addressToUse = binding.inputAddress.text.toString()
|
||||
val startToUse = max(binding.inputRangeStart.text.toString().toLongOrNull() ?: network.saplingActivationHeight.value, network.saplingActivationHeight.value)
|
||||
val startToUse = max(
|
||||
binding.inputRangeStart.text.toString().toLongOrNull()
|
||||
?: network.saplingActivationHeight.value,
|
||||
network.saplingActivationHeight.value
|
||||
)
|
||||
val endToUse = binding.inputRangeEnd.text.toString().toLongOrNull()
|
||||
?: getUxtoEndHeight(requireApplicationContext()).value
|
||||
var allStart = now
|
||||
twig("loading transactions in range $startToUse..$endToUse")
|
||||
val txids = lightwalletService?.getTAddressTransactions(addressToUse, BlockHeight.new(network, startToUse)..BlockHeight.new(network, endToUse))
|
||||
val txids = lightwalletService?.getTAddressTransactions(
|
||||
addressToUse,
|
||||
BlockHeight.new(network, startToUse)..BlockHeight.new(network, endToUse)
|
||||
)
|
||||
var delta = now - allStart
|
||||
updateStatus("found ${txids?.size} transactions in ${delta}ms.", false)
|
||||
|
||||
|
@ -163,7 +179,12 @@ class ListUtxosFragment : BaseDemoFragment<FragmentListUtxosBinding>() {
|
|||
resetInBackground()
|
||||
val seed = Mnemonics.MnemonicCode(sharedViewModel.seedPhrase.value).toSeed()
|
||||
viewLifecycleOwner.lifecycleScope.launchWhenStarted {
|
||||
binding.inputAddress.setText(DerivationTool.deriveTransparentAddress(seed, ZcashNetwork.fromResources(requireApplicationContext())))
|
||||
binding.inputAddress.setText(
|
||||
DerivationTool.deriveTransparentAddress(
|
||||
seed,
|
||||
ZcashNetwork.fromResources(requireApplicationContext())
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,11 @@ import cash.z.ecc.android.sdk.ext.convertZecToZatoshi
|
|||
import cash.z.ecc.android.sdk.ext.toZecString
|
||||
import cash.z.ecc.android.sdk.internal.Twig
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
||||
/**
|
||||
|
@ -66,8 +68,14 @@ class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
|
|||
|
||||
runBlocking {
|
||||
Initializer.new(requireApplicationContext()) {
|
||||
runBlocking { it.newWallet(seed, network = ZcashNetwork.fromResources(requireApplicationContext())) }
|
||||
it.setNetwork(ZcashNetwork.fromResources(requireApplicationContext()))
|
||||
val network = ZcashNetwork.fromResources(requireApplicationContext())
|
||||
runBlocking {
|
||||
it.newWallet(
|
||||
seed,
|
||||
network = network,
|
||||
lightWalletEndpoint = LightWalletEndpoint.defaultForNetwork(network)
|
||||
)
|
||||
}
|
||||
}
|
||||
}.let { initializer ->
|
||||
synchronizer = Synchronizer.newBlocking(initializer)
|
||||
|
|
|
@ -4,10 +4,16 @@ package cash.z.ecc.android.sdk.demoapp.util
|
|||
|
||||
import android.content.Context
|
||||
import cash.z.ecc.android.sdk.demoapp.R
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import java.util.*
|
||||
|
||||
fun ZcashNetwork.Companion.fromResources(context: Context) = ZcashNetwork.valueOf(
|
||||
context.getString(
|
||||
R.string.network_name
|
||||
)
|
||||
)
|
||||
fun ZcashNetwork.Companion.fromResources(context: Context): ZcashNetwork {
|
||||
val networkNameFromResources = context.getString(R.string.network_name).lowercase(Locale.ROOT)
|
||||
return if (networkNameFromResources == Testnet.networkName) {
|
||||
ZcashNetwork.Testnet
|
||||
} else if (networkNameFromResources.lowercase(Locale.ROOT) == Mainnet.networkName) {
|
||||
ZcashNetwork.Mainnet
|
||||
} else {
|
||||
throw IllegalArgumentException("Unknown network name: $networkNameFromResources")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package cash.z.ecc.android.sdk
|
|||
import android.content.Context
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.filters.SmallTest
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.json.JSONObject
|
||||
import org.junit.Assert.assertEquals
|
||||
|
@ -77,6 +77,7 @@ class AssetTest {
|
|||
val expectedNetworkName = when (network) {
|
||||
ZcashNetwork.Mainnet -> "main"
|
||||
ZcashNetwork.Testnet -> "test"
|
||||
else -> IllegalArgumentException("Unsupported network $network")
|
||||
}
|
||||
assertEquals("File: ${it.filename}", expectedNetworkName, jsonObject.getString("network"))
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package cash.z.ecc.android.sdk.ext
|
||||
|
||||
import cash.z.ecc.android.sdk.Initializer
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.util.SimpleMnemonics
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.OkHttpClient
|
||||
|
|
|
@ -4,11 +4,10 @@ import cash.z.ecc.android.sdk.annotation.MaintainedTest
|
|||
import cash.z.ecc.android.sdk.annotation.TestPurpose
|
||||
import cash.z.ecc.android.sdk.ext.BlockExplorer
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.util.TestWallet
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
@ -31,13 +30,6 @@ class SanityTest(
|
|||
val networkName = wallet.networkName
|
||||
val name = "$networkName wallet"
|
||||
|
||||
@Test
|
||||
fun testNotPlaintext() {
|
||||
val message =
|
||||
"is using plaintext. This will cause problems for the test. Ensure that the `lightwalletd_allow_very_insecure_connections` resource value is false"
|
||||
assertFalse("$name $message", wallet.service.connectionInfo.usePlaintext)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePaths() {
|
||||
assertEquals(
|
||||
|
@ -80,24 +72,14 @@ class SanityTest(
|
|||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testServerConnection() {
|
||||
assertEquals(
|
||||
"$name has an invalid server connection",
|
||||
"$networkName.lightwalletd.com:9067?usePlaintext=false",
|
||||
wallet.connectionInfo
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLatestHeight() = runBlocking {
|
||||
if (wallet.networkName == "mainnet") {
|
||||
val expectedHeight = BlockExplorer.fetchLatestHeight()
|
||||
// fetch height directly because the synchronizer hasn't started, yet
|
||||
val downloaderHeight = wallet.service.getLatestBlockHeight()
|
||||
val info = wallet.connectionInfo
|
||||
assertTrue(
|
||||
"$info\n ${wallet.networkName} Lightwalletd is too far behind. Downloader height $downloaderHeight is more than 10 blocks behind block explorer height $expectedHeight",
|
||||
"${wallet.endpoint} ${wallet.networkName} Lightwalletd is too far behind. Downloader height $downloaderHeight is more than 10 blocks behind block explorer height $expectedHeight",
|
||||
expectedHeight - 10 < downloaderHeight.value
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import androidx.test.filters.LargeTest
|
|||
import androidx.test.filters.MediumTest
|
||||
import cash.z.ecc.android.sdk.annotation.MaintainedTest
|
||||
import cash.z.ecc.android.sdk.annotation.TestPurpose
|
||||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.util.TestWallet
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
|
@ -19,16 +18,6 @@ import org.junit.Test
|
|||
@MediumTest
|
||||
class SmokeTest {
|
||||
|
||||
@Test
|
||||
fun testNotPlaintext() {
|
||||
val service =
|
||||
wallet.synchronizer.processor.downloader.lightWalletService as LightWalletGrpcService
|
||||
Assert.assertFalse(
|
||||
"Wallet is using plaintext. This will cause problems for the test. Ensure that the `lightwalletd_allow_very_insecure_connections` resource value is false",
|
||||
service.connectionInfo.usePlaintext
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFilePaths() {
|
||||
Assert.assertEquals("Invalid DataDB file", "/data/user/0/cash.z.ecc.android.sdk.test/databases/TestWallet_testnet_Data.db", wallet.initializer.rustBackend.pathDataDb)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cash.z.wallet.sdk.integration
|
||||
package cash.z.ecc.android.sdk.integration
|
||||
|
||||
import androidx.test.filters.LargeTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
|
@ -13,11 +13,12 @@ import cash.z.ecc.android.sdk.internal.Twig
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.test.ScopedTest
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
|
@ -39,9 +40,9 @@ class TestnetIntegrationTest : ScopedTest() {
|
|||
@Test
|
||||
@Ignore("This test is broken")
|
||||
fun testLatestBlockTest() {
|
||||
val service = LightWalletGrpcService(
|
||||
val service = LightWalletGrpcService.new(
|
||||
context,
|
||||
host
|
||||
lightWalletEndpoint
|
||||
)
|
||||
val height = service.getLatestBlockHeight()
|
||||
assertTrue(height > saplingActivation)
|
||||
|
@ -118,7 +119,7 @@ class TestnetIntegrationTest : ScopedTest() {
|
|||
companion object {
|
||||
init { Twig.plant(TroubleshootingTwig()) }
|
||||
|
||||
const val host = "lightwalletd.testnet.z.cash"
|
||||
val lightWalletEndpoint = LightWalletEndpoint("lightwalletd.testnet.z.cash", 9087, true)
|
||||
private const val birthdayHeight = 963150L
|
||||
private const val targetHeight = 663250
|
||||
private const val seedPhrase = "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread"
|
||||
|
@ -129,8 +130,8 @@ class TestnetIntegrationTest : ScopedTest() {
|
|||
private val context = InstrumentationRegistry.getInstrumentation().context
|
||||
private val initializer = runBlocking {
|
||||
Initializer.new(context) { config ->
|
||||
config.setNetwork(ZcashNetwork.Testnet, host)
|
||||
runBlocking { config.importWallet(seed, BlockHeight.new(ZcashNetwork.Testnet, birthdayHeight), ZcashNetwork.Testnet) }
|
||||
config.setNetwork(ZcashNetwork.Testnet, lightWalletEndpoint)
|
||||
runBlocking { config.importWallet(seed, BlockHeight.new(ZcashNetwork.Testnet, birthdayHeight), ZcashNetwork.Testnet, lightWalletEndpoint) }
|
||||
}
|
||||
}
|
||||
private lateinit var synchronizer: Synchronizer
|
||||
|
|
|
@ -12,8 +12,11 @@ import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.Mainnet
|
||||
import cash.z.ecc.android.sdk.model.Testnet
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.test.ScopedTest
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -35,13 +38,15 @@ import org.mockito.Spy
|
|||
class ChangeServiceTest : ScopedTest() {
|
||||
|
||||
val network = ZcashNetwork.Mainnet
|
||||
val lightWalletEndpoint = LightWalletEndpoint.Mainnet
|
||||
private val eccEndpoint = LightWalletEndpoint("lightwalletd.electriccoin.co", 9087, true)
|
||||
|
||||
@Mock
|
||||
lateinit var mockBlockStore: CompactBlockStore
|
||||
var mockCloseable: AutoCloseable? = null
|
||||
|
||||
@Spy
|
||||
val service = LightWalletGrpcService(context, network)
|
||||
val service = LightWalletGrpcService.new(context, lightWalletEndpoint)
|
||||
|
||||
lateinit var downloader: CompactBlockDownloader
|
||||
lateinit var otherService: LightWalletService
|
||||
|
@ -50,7 +55,7 @@ class ChangeServiceTest : ScopedTest() {
|
|||
fun setup() {
|
||||
initMocks()
|
||||
downloader = CompactBlockDownloader(service, mockBlockStore)
|
||||
otherService = LightWalletGrpcService(context, "lightwalletd.electriccoin.co")
|
||||
otherService = LightWalletGrpcService.new(context, eccEndpoint)
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -106,7 +111,7 @@ class ChangeServiceTest : ScopedTest() {
|
|||
@Test
|
||||
fun testSwitchToInvalidServer() = runBlocking {
|
||||
var caughtException: Throwable? = null
|
||||
downloader.changeService(LightWalletGrpcService(context, "invalid.lightwalletd")) {
|
||||
downloader.changeService(LightWalletGrpcService.new(context, LightWalletEndpoint("invalid.lightwalletd", 9087, true))) {
|
||||
caughtException = it
|
||||
}
|
||||
assertNotNull("Using an invalid host should generate an exception.", caughtException)
|
||||
|
@ -119,7 +124,7 @@ class ChangeServiceTest : ScopedTest() {
|
|||
@Test
|
||||
fun testSwitchToTestnetFails() = runBlocking {
|
||||
var caughtException: Throwable? = null
|
||||
downloader.changeService(LightWalletGrpcService(context, ZcashNetwork.Testnet)) {
|
||||
downloader.changeService(LightWalletGrpcService.new(context, LightWalletEndpoint.Testnet)) {
|
||||
caughtException = it
|
||||
}
|
||||
assertNotNull("Using an invalid host should generate an exception.", caughtException)
|
||||
|
|
|
@ -3,7 +3,7 @@ package cash.z.ecc.android.sdk.jni
|
|||
import cash.z.ecc.android.sdk.annotation.MaintainedTest
|
||||
import cash.z.ecc.android.sdk.annotation.TestPurpose
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
|
|
@ -7,8 +7,8 @@ import cash.z.ecc.android.sdk.annotation.MaintainedTest
|
|||
import cash.z.ecc.android.sdk.annotation.TestPurpose
|
||||
import cash.z.ecc.android.sdk.internal.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.internal.Twig
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.BeforeClass
|
||||
|
|
|
@ -2,7 +2,7 @@ package cash.z.ecc.android.sdk.sample
|
|||
|
||||
import cash.z.ecc.android.sdk.internal.Twig
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.util.TestWallet
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
|
|
|
@ -5,8 +5,7 @@ import cash.z.ecc.android.sdk.ext.ZcashSdk
|
|||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork.Testnet
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.util.TestWallet
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
@ -90,7 +89,7 @@ class TransparentRestoreSample {
|
|||
val wallet0 = TestWallet(
|
||||
TestWallet.Backups.SAMPLE_WALLET.seedPhrase,
|
||||
"tmpabc",
|
||||
Testnet,
|
||||
ZcashNetwork.Testnet,
|
||||
startHeight = BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1330190
|
||||
|
@ -117,7 +116,15 @@ class TransparentRestoreSample {
|
|||
*/
|
||||
// @Test
|
||||
fun hasFunds() = runBlocking<Unit> {
|
||||
val walletSandbox = TestWallet(TestWallet.Backups.SAMPLE_WALLET.seedPhrase, "WalletC", Testnet, startHeight = BlockHeight.new(ZcashNetwork.Testnet, 1330190))
|
||||
val walletSandbox = TestWallet(
|
||||
TestWallet.Backups.SAMPLE_WALLET.seedPhrase,
|
||||
"WalletC",
|
||||
ZcashNetwork.Testnet,
|
||||
startHeight = BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1330190
|
||||
)
|
||||
)
|
||||
// val job = walletA.walletScope.launch {
|
||||
// twig("Syncing WalletA")
|
||||
// walletA.sync()
|
||||
|
|
|
@ -4,8 +4,8 @@ import android.content.Context
|
|||
import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool.IS_FALLBACK_ON_FAILURE
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package cash.z.ecc.android.sdk.util
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
|
@ -9,8 +9,10 @@ import cash.z.ecc.android.sdk.internal.ext.deleteSuspend
|
|||
import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.defaultForNetwork
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
|
@ -82,8 +84,8 @@ class BalancePrinterUtil {
|
|||
}.collect { seed ->
|
||||
// TODO: clear the dataDb but leave the cacheDb
|
||||
val initializer = Initializer.new(context) { config ->
|
||||
runBlocking { config.importWallet(seed, birthdayHeight, network) }
|
||||
config.setNetwork(network)
|
||||
val endpoint = LightWalletEndpoint.defaultForNetwork(network)
|
||||
runBlocking { config.importWallet(seed, birthdayHeight, network, endpoint) }
|
||||
config.alias = alias
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@ import cash.z.ecc.android.sdk.Synchronizer
|
|||
import cash.z.ecc.android.sdk.internal.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.internal.Twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
|
|
|
@ -11,10 +11,12 @@ import cash.z.ecc.android.sdk.internal.Twig
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.Testnet
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.delay
|
||||
|
@ -36,9 +38,8 @@ class TestWallet(
|
|||
val seedPhrase: String,
|
||||
val alias: String = "TestWallet",
|
||||
val network: ZcashNetwork = ZcashNetwork.Testnet,
|
||||
val host: String = network.defaultHost,
|
||||
startHeight: BlockHeight? = null,
|
||||
val port: Int = network.defaultPort
|
||||
val endpoint: LightWalletEndpoint = LightWalletEndpoint.Testnet,
|
||||
startHeight: BlockHeight? = null
|
||||
) {
|
||||
constructor(
|
||||
backup: Backups,
|
||||
|
@ -66,7 +67,7 @@ class TestWallet(
|
|||
runBlocking { DerivationTool.deriveTransparentSecretKey(seed, network = network) }
|
||||
val initializer = runBlocking {
|
||||
Initializer.new(context) { config ->
|
||||
runBlocking { config.importWallet(seed, startHeight, network, host, alias = alias) }
|
||||
runBlocking { config.importWallet(seed, startHeight, network, endpoint, alias = alias) }
|
||||
}
|
||||
}
|
||||
val synchronizer: SdkSynchronizer = Synchronizer.newBlocking(initializer) as SdkSynchronizer
|
||||
|
@ -79,7 +80,6 @@ class TestWallet(
|
|||
runBlocking { DerivationTool.deriveTransparentAddress(seed, network = network) }
|
||||
val birthdayHeight get() = synchronizer.latestBirthdayHeight
|
||||
val networkName get() = synchronizer.network.networkName
|
||||
val connectionInfo get() = service.connectionInfo.toString()
|
||||
|
||||
suspend fun transparentBalance(): WalletBalance {
|
||||
synchronizer.refreshUtxos(transparentAddress, synchronizer.latestBirthdayHeight)
|
||||
|
@ -166,11 +166,46 @@ class TestWallet(
|
|||
|
||||
enum class Backups(val seedPhrase: String, val testnetBirthday: BlockHeight, val mainnetBirthday: BlockHeight) {
|
||||
// TODO: get the proper birthday values for these wallets
|
||||
DEFAULT("column rhythm acoustic gym cost fit keen maze fence seed mail medal shrimp tell relief clip cannon foster soldier shallow refuse lunar parrot banana", BlockHeight.new(ZcashNetwork.Testnet, 1_355_928), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
SAMPLE_WALLET("input frown warm senior anxiety abuse yard prefer churn reject people glimpse govern glory crumble swallow verb laptop switch trophy inform friend permit purpose", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
DEV_WALLET("still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread", BlockHeight.new(ZcashNetwork.Testnet, 1_000_000), BlockHeight.new(ZcashNetwork.Mainnet, 991645)),
|
||||
ALICE("quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
BOB("canvas wine sugar acquire garment spy tongue odor hole cage year habit bullet make label human unit option top calm neutral try vocal arena", BlockHeight.new(ZcashNetwork.Testnet, 1_330_190), BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)),
|
||||
DEFAULT(
|
||||
"column rhythm acoustic gym cost fit keen maze fence seed mail medal shrimp tell relief clip cannon foster soldier shallow refuse lunar parrot banana",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_355_928
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
SAMPLE_WALLET(
|
||||
"input frown warm senior anxiety abuse yard prefer churn reject people glimpse govern glory crumble swallow verb laptop switch trophy inform friend permit purpose",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
DEV_WALLET(
|
||||
"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_000_000
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 991645)
|
||||
),
|
||||
ALICE(
|
||||
"quantum whisper lion route fury lunar pelican image job client hundred sauce chimney barely life cliff spirit admit weekend message recipe trumpet impact kitten",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
BOB(
|
||||
"canvas wine sugar acquire garment spy tongue odor hole cage year habit bullet make label human unit option top calm neutral try vocal arena",
|
||||
BlockHeight.new(
|
||||
ZcashNetwork.Testnet,
|
||||
1_330_190
|
||||
),
|
||||
BlockHeight.new(ZcashNetwork.Mainnet, 1_000_000)
|
||||
),
|
||||
;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,9 @@ import cash.z.ecc.android.sdk.internal.Twig
|
|||
import cash.z.ecc.android.sdk.internal.service.LightWalletGrpcService
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.Mainnet
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
|
@ -14,7 +16,7 @@ class TransactionCounterUtil {
|
|||
|
||||
private val network = ZcashNetwork.Mainnet
|
||||
private val context = InstrumentationRegistry.getInstrumentation().context
|
||||
private val service = LightWalletGrpcService(context, network)
|
||||
private val service = LightWalletGrpcService.new(context, LightWalletEndpoint.Mainnet)
|
||||
|
||||
init {
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
|
|
|
@ -8,7 +8,7 @@ import cash.z.ecc.android.sdk.internal.KEY_VERSION
|
|||
import cash.z.ecc.android.sdk.internal.VERSION_1
|
||||
import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.json.JSONObject
|
||||
|
||||
object CheckpointFixture {
|
||||
|
|
|
@ -10,10 +10,11 @@ import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
|||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.jni.RustBackend
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
@ -21,13 +22,13 @@ import java.io.File
|
|||
/**
|
||||
* Simplified Initializer focused on starting from a ViewingKey.
|
||||
*/
|
||||
@Suppress("LongParameterList")
|
||||
class Initializer private constructor(
|
||||
val context: Context,
|
||||
internal val rustBackend: RustBackend,
|
||||
val network: ZcashNetwork,
|
||||
val alias: String,
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val lightWalletEndpoint: LightWalletEndpoint,
|
||||
val viewingKeys: List<UnifiedViewingKey>,
|
||||
val overwriteVks: Boolean,
|
||||
internal val checkpoint: Checkpoint
|
||||
|
@ -45,10 +46,7 @@ class Initializer private constructor(
|
|||
lateinit var network: ZcashNetwork
|
||||
private set
|
||||
|
||||
lateinit var host: String
|
||||
private set
|
||||
|
||||
var port: Int = ZcashNetwork.Mainnet.defaultPort
|
||||
lateinit var lightWalletEndpoint: LightWalletEndpoint
|
||||
private set
|
||||
|
||||
/**
|
||||
|
@ -160,12 +158,10 @@ class Initializer private constructor(
|
|||
*/
|
||||
fun setNetwork(
|
||||
network: ZcashNetwork,
|
||||
host: String = network.defaultHost,
|
||||
port: Int = network.defaultPort
|
||||
lightWalletEndpoint: LightWalletEndpoint
|
||||
): Config = apply {
|
||||
this.network = network
|
||||
this.host = host
|
||||
this.port = port
|
||||
this.lightWalletEndpoint = lightWalletEndpoint
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,16 +171,14 @@ class Initializer private constructor(
|
|||
seed: ByteArray,
|
||||
birthday: BlockHeight?,
|
||||
network: ZcashNetwork,
|
||||
host: String = network.defaultHost,
|
||||
port: Int = network.defaultPort,
|
||||
lightWalletEndpoint: LightWalletEndpoint,
|
||||
alias: String = ZcashSdk.DEFAULT_ALIAS
|
||||
): Config =
|
||||
importWallet(
|
||||
DerivationTool.deriveUnifiedViewingKeys(seed, network = network)[0],
|
||||
birthday,
|
||||
network,
|
||||
host,
|
||||
port,
|
||||
lightWalletEndpoint,
|
||||
alias
|
||||
)
|
||||
|
||||
|
@ -195,12 +189,11 @@ class Initializer private constructor(
|
|||
viewingKey: UnifiedViewingKey,
|
||||
birthday: BlockHeight?,
|
||||
network: ZcashNetwork,
|
||||
host: String = network.defaultHost,
|
||||
port: Int = network.defaultPort,
|
||||
lightWalletEndpoint: LightWalletEndpoint,
|
||||
alias: String = ZcashSdk.DEFAULT_ALIAS
|
||||
): Config = apply {
|
||||
setViewingKeys(viewingKey)
|
||||
setNetwork(network, host, port)
|
||||
setNetwork(network, lightWalletEndpoint)
|
||||
importedWalletBirthday(birthday)
|
||||
this.alias = alias
|
||||
}
|
||||
|
@ -211,14 +204,12 @@ class Initializer private constructor(
|
|||
suspend fun newWallet(
|
||||
seed: ByteArray,
|
||||
network: ZcashNetwork,
|
||||
host: String = network.defaultHost,
|
||||
port: Int = network.defaultPort,
|
||||
lightWalletEndpoint: LightWalletEndpoint,
|
||||
alias: String = ZcashSdk.DEFAULT_ALIAS
|
||||
): Config = newWallet(
|
||||
DerivationTool.deriveUnifiedViewingKeys(seed, network)[0],
|
||||
network,
|
||||
host,
|
||||
port,
|
||||
lightWalletEndpoint,
|
||||
alias
|
||||
)
|
||||
|
||||
|
@ -228,12 +219,11 @@ class Initializer private constructor(
|
|||
fun newWallet(
|
||||
viewingKey: UnifiedViewingKey,
|
||||
network: ZcashNetwork,
|
||||
host: String = network.defaultHost,
|
||||
port: Int = network.defaultPort,
|
||||
lightWalletEndpoint: LightWalletEndpoint,
|
||||
alias: String = ZcashSdk.DEFAULT_ALIAS
|
||||
): Config = apply {
|
||||
setViewingKeys(viewingKey)
|
||||
setNetwork(network, host, port)
|
||||
setNetwork(network, lightWalletEndpoint)
|
||||
newWalletBirthday()
|
||||
this.alias = alias
|
||||
}
|
||||
|
@ -352,8 +342,7 @@ class Initializer private constructor(
|
|||
rustBackend,
|
||||
config.network,
|
||||
config.alias,
|
||||
config.host,
|
||||
config.port,
|
||||
config.lightWalletEndpoint,
|
||||
config.viewingKeys,
|
||||
config.overwriteVks,
|
||||
loadedCheckpoint
|
||||
|
|
|
@ -50,12 +50,12 @@ import cash.z.ecc.android.sdk.internal.twigTask
|
|||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.AddressType
|
||||
import cash.z.ecc.android.sdk.type.AddressType.Shielded
|
||||
import cash.z.ecc.android.sdk.type.AddressType.Transparent
|
||||
import cash.z.ecc.android.sdk.type.ConsensusMatchType
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
import io.grpc.ManagedChannel
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
|
@ -308,20 +308,6 @@ class SdkSynchronizer internal constructor(
|
|||
*/
|
||||
override suspend fun getServerInfo(): Service.LightdInfo = processor.downloader.getServerInfo()
|
||||
|
||||
/**
|
||||
* Changes the server that is being used to download compact blocks. This will throw an
|
||||
* exception if it detects that the server change is invalid e.g. switching to testnet from
|
||||
* mainnet.
|
||||
*/
|
||||
override suspend fun changeServer(host: String, port: Int, errorHandler: (Throwable) -> Unit) {
|
||||
val info =
|
||||
(processor.downloader.lightWalletService as LightWalletGrpcService).connectionInfo
|
||||
processor.downloader.changeService(
|
||||
LightWalletGrpcService(info.appContext, host, port),
|
||||
errorHandler
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getNearestRewindHeight(height: BlockHeight): BlockHeight =
|
||||
processor.getNearestRewindHeight(height)
|
||||
|
||||
|
@ -800,7 +786,7 @@ object DefaultSynchronizerFactory {
|
|||
CompactBlockDbStore.new(initializer.context, initializer.network, initializer.rustBackend.pathCacheDb)
|
||||
|
||||
fun defaultService(initializer: Initializer): LightWalletService =
|
||||
LightWalletGrpcService(initializer.context, initializer.host, initializer.port)
|
||||
LightWalletGrpcService.new(initializer.context, initializer.lightWalletEndpoint)
|
||||
|
||||
fun defaultEncoder(
|
||||
initializer: Initializer,
|
||||
|
|
|
@ -7,9 +7,9 @@ import cash.z.ecc.android.sdk.ext.ZcashSdk
|
|||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.type.AddressType
|
||||
import cash.z.ecc.android.sdk.type.ConsensusMatchType
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
@ -284,18 +284,6 @@ interface Synchronizer {
|
|||
*/
|
||||
suspend fun getServerInfo(): Service.LightdInfo
|
||||
|
||||
/**
|
||||
* Gracefully change the server that the Synchronizer is currently using. In some cases, this
|
||||
* will require waiting until current network activity is complete. Ideally, this would protect
|
||||
* against accidentally switching between testnet and mainnet, by comparing the service info of
|
||||
* the existing server with that of the new one.
|
||||
*/
|
||||
suspend fun changeServer(
|
||||
host: String,
|
||||
port: Int = network.defaultPort,
|
||||
errorHandler: (Throwable) -> Unit = { throw it }
|
||||
)
|
||||
|
||||
/**
|
||||
* Download all UTXOs for the given address and store any new ones in the database.
|
||||
*
|
||||
|
|
|
@ -2,7 +2,7 @@ package cash.z.ecc.android.sdk.exception
|
|||
|
||||
import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
import io.grpc.Status
|
||||
import io.grpc.Status.Code.UNAVAILABLE
|
||||
|
|
|
@ -2,7 +2,7 @@ package cash.z.ecc.android.sdk.internal
|
|||
|
||||
import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import org.json.JSONObject
|
||||
|
||||
// Version is not returned from the server, so version 1 is implied. A version is declared here
|
||||
|
|
|
@ -8,7 +8,7 @@ import cash.z.ecc.android.sdk.internal.SdkDispatchers
|
|||
import cash.z.ecc.android.sdk.internal.SdkExecutors
|
||||
import cash.z.ecc.android.sdk.internal.db.CompactBlockDb
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.wallet.sdk.rpc.CompactFormats
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
package cash.z.ecc.android.sdk.internal.service
|
||||
|
||||
import android.content.Context
|
||||
import cash.z.ecc.android.sdk.R
|
||||
import cash.z.ecc.android.sdk.annotation.OpenForTesting
|
||||
import cash.z.ecc.android.sdk.exception.LightWalletException
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.LightWalletEndpoint
|
||||
import cash.z.wallet.sdk.rpc.CompactFormats
|
||||
import cash.z.wallet.sdk.rpc.CompactTxStreamerGrpc
|
||||
import cash.z.wallet.sdk.rpc.Service
|
||||
|
@ -31,39 +29,14 @@ import kotlin.time.Duration.Companion.seconds
|
|||
*/
|
||||
@OpenForTesting
|
||||
class LightWalletGrpcService private constructor(
|
||||
context: Context,
|
||||
private val lightWalletEndpoint: LightWalletEndpoint,
|
||||
var channel: ManagedChannel,
|
||||
private val singleRequestTimeout: Duration = 10.seconds,
|
||||
private val streamingRequestTimeout: Duration = 90.seconds
|
||||
) : LightWalletService {
|
||||
|
||||
lateinit var connectionInfo: ConnectionInfo
|
||||
|
||||
constructor(
|
||||
appContext: Context,
|
||||
network: ZcashNetwork,
|
||||
usePlaintext: Boolean =
|
||||
appContext.resources.getBoolean(R.bool.lightwalletd_allow_very_insecure_connections)
|
||||
) : this(appContext, network.defaultHost, network.defaultPort, usePlaintext)
|
||||
|
||||
/**
|
||||
* Construct an instance that corresponds to the given host and port.
|
||||
*
|
||||
* @param appContext the application context used to check whether TLS is required by this build
|
||||
* flavor.
|
||||
* @param host the host of the server to use.
|
||||
* @param port the port of the server to use.
|
||||
* @param usePlaintext whether to use TLS or plaintext for requests. Plaintext is dangerous so
|
||||
* it requires jumping through a few more hoops.
|
||||
*/
|
||||
constructor(
|
||||
appContext: Context,
|
||||
host: String,
|
||||
port: Int = ZcashNetwork.Mainnet.defaultPort,
|
||||
usePlaintext: Boolean =
|
||||
appContext.resources.getBoolean(R.bool.lightwalletd_allow_very_insecure_connections)
|
||||
) : this(createDefaultChannel(appContext, host, port, usePlaintext)) {
|
||||
connectionInfo = ConnectionInfo(appContext.applicationContext, host, port, usePlaintext)
|
||||
}
|
||||
private val applicationContext = context.applicationContext
|
||||
|
||||
/* LightWalletService implementation */
|
||||
|
||||
|
@ -141,22 +114,14 @@ class LightWalletGrpcService private constructor(
|
|||
}
|
||||
|
||||
override fun reconnect() {
|
||||
twig(
|
||||
"closing existing channel and then reconnecting to ${connectionInfo.host}:" +
|
||||
"${connectionInfo.port}?usePlaintext=${connectionInfo.usePlaintext}"
|
||||
)
|
||||
twig("closing existing channel and then reconnecting")
|
||||
channel.shutdown()
|
||||
channel = createDefaultChannel(
|
||||
connectionInfo.appContext,
|
||||
connectionInfo.host,
|
||||
connectionInfo.port,
|
||||
connectionInfo.usePlaintext
|
||||
)
|
||||
channel = createDefaultChannel(applicationContext, lightWalletEndpoint)
|
||||
}
|
||||
|
||||
// test code
|
||||
var stateCount = 0
|
||||
var state: ConnectivityState? = null
|
||||
internal var stateCount = 0
|
||||
internal var state: ConnectivityState? = null
|
||||
private fun requireChannel(): ManagedChannel {
|
||||
state = channel.getState(false).let { new ->
|
||||
if (state == new) stateCount++ else stateCount = 0
|
||||
|
@ -172,37 +137,13 @@ class LightWalletGrpcService private constructor(
|
|||
return channel
|
||||
}
|
||||
|
||||
//
|
||||
// Utilities
|
||||
//
|
||||
|
||||
private fun Channel.createStub(timeoutSec: Duration = 60.seconds) = CompactTxStreamerGrpc
|
||||
.newBlockingStub(this)
|
||||
.withDeadlineAfter(timeoutSec.inWholeSeconds, TimeUnit.SECONDS)
|
||||
|
||||
/**
|
||||
* This function effectively parses streaming responses. Each call to next(), on the iterators
|
||||
* returned from grpc, triggers a network call.
|
||||
*/
|
||||
private fun <T> Iterator<T>.toList(): List<T> =
|
||||
mutableListOf<T>().apply {
|
||||
while (hasNext()) {
|
||||
this@apply += next()
|
||||
}
|
||||
}
|
||||
|
||||
inner class ConnectionInfo(
|
||||
val appContext: Context,
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val usePlaintext: Boolean
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "$host:$port?usePlaintext=$usePlaintext"
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun new(context: Context, lightWalletEndpoint: LightWalletEndpoint): LightWalletGrpcService {
|
||||
val channel = createDefaultChannel(context, lightWalletEndpoint)
|
||||
|
||||
return LightWalletGrpcService(context, lightWalletEndpoint, channel)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for creating the default channel to be used for all connections. It
|
||||
* is important that this channel can handle transitioning from WiFi to Cellular connections
|
||||
|
@ -210,24 +151,23 @@ class LightWalletGrpcService private constructor(
|
|||
*/
|
||||
fun createDefaultChannel(
|
||||
appContext: Context,
|
||||
host: String,
|
||||
port: Int,
|
||||
usePlaintext: Boolean
|
||||
lightWalletEndpoint: LightWalletEndpoint
|
||||
): ManagedChannel {
|
||||
twig("Creating channel that will connect to $host:$port?usePlaintext=$usePlaintext")
|
||||
twig(
|
||||
"Creating channel that will connect to " +
|
||||
"${lightWalletEndpoint.host}:${lightWalletEndpoint.port}" +
|
||||
"/?usePlaintext=${!lightWalletEndpoint.isSecure}"
|
||||
)
|
||||
return AndroidChannelBuilder
|
||||
.forAddress(host, port)
|
||||
.forAddress(lightWalletEndpoint.host, lightWalletEndpoint.port)
|
||||
.context(appContext)
|
||||
.enableFullStreamDecompression()
|
||||
.apply {
|
||||
if (usePlaintext) {
|
||||
if (!appContext.resources.getBoolean(
|
||||
R.bool.lightwalletd_allow_very_insecure_connections
|
||||
)
|
||||
) throw LightWalletException.InsecureConnection
|
||||
usePlaintext()
|
||||
} else {
|
||||
if (lightWalletEndpoint.isSecure) {
|
||||
useTransportSecurity()
|
||||
} else {
|
||||
twig("WARNING: Using insecure channel")
|
||||
usePlaintext()
|
||||
}
|
||||
}
|
||||
.build()
|
||||
|
@ -235,6 +175,10 @@ class LightWalletGrpcService private constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun Channel.createStub(timeoutSec: Duration = 60.seconds) = CompactTxStreamerGrpc
|
||||
.newBlockingStub(this)
|
||||
.withDeadlineAfter(timeoutSec.inWholeSeconds, TimeUnit.SECONDS)
|
||||
|
||||
private fun BlockHeight.toBlockHeight(): Service.BlockID =
|
||||
Service.BlockID.newBuilder().setHeight(value).build()
|
||||
|
||||
|
@ -243,3 +187,14 @@ private fun ClosedRange<BlockHeight>.toBlockRange(): Service.BlockRange =
|
|||
.setStart(start.toBlockHeight())
|
||||
.setEnd(endInclusive.toBlockHeight())
|
||||
.build()
|
||||
|
||||
/**
|
||||
* This function effectively parses streaming responses. Each call to next(), on the iterators
|
||||
* returned from grpc, triggers a network call.
|
||||
*/
|
||||
private fun <T> Iterator<T>.toList(): List<T> =
|
||||
mutableListOf<T>().apply {
|
||||
while (hasNext()) {
|
||||
this@apply += next()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
|||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.jni.RustBackend
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
|
@ -9,9 +9,9 @@ import cash.z.ecc.android.sdk.internal.twig
|
|||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
|||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.model.WalletBalance
|
||||
import cash.z.ecc.android.sdk.model.Zatoshi
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
|
||||
/**
|
||||
* Contract defining the exposed capabilities of the Rust backend.
|
||||
|
|
|
@ -2,7 +2,6 @@ package cash.z.ecc.android.sdk.model
|
|||
|
||||
import android.content.Context
|
||||
import cash.z.ecc.android.sdk.tool.CheckpointTool
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
|
||||
/**
|
||||
* Represents a block height, which is a UInt32. SDK clients use this class to represent the "birthday" of a wallet.
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package cash.z.ecc.android.sdk.model
|
||||
|
||||
data class LightWalletEndpoint(val host: String, val port: Int, val isSecure: Boolean) {
|
||||
companion object
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
@file:Suppress("ktlint:filename")
|
||||
|
||||
package cash.z.ecc.android.sdk.model
|
||||
|
||||
/*
|
||||
* This is a set of extension functions currently, because we expect them to change in the future.
|
||||
*/
|
||||
|
||||
fun LightWalletEndpoint.Companion.defaultForNetwork(zcashNetwork: ZcashNetwork): LightWalletEndpoint {
|
||||
return when (zcashNetwork.id) {
|
||||
ZcashNetwork.Mainnet.id -> LightWalletEndpoint.Mainnet
|
||||
ZcashNetwork.Testnet.id -> LightWalletEndpoint.Testnet
|
||||
else -> error("Unknown network id: ${zcashNetwork.id}")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a special localhost value on the Android emulator, which allows it to contact
|
||||
* the localhost of the computer running the emulator.
|
||||
*/
|
||||
private const val COMPUTER_LOCALHOST = "10.0.2.2"
|
||||
|
||||
private const val DEFAULT_PORT = 9067
|
||||
|
||||
val LightWalletEndpoint.Companion.Mainnet
|
||||
get() = LightWalletEndpoint(
|
||||
"mainnet.lightwalletd.com",
|
||||
DEFAULT_PORT,
|
||||
isSecure = true
|
||||
)
|
||||
|
||||
val LightWalletEndpoint.Companion.Testnet
|
||||
get() = LightWalletEndpoint(
|
||||
"testnet.lightwalletd.com",
|
||||
DEFAULT_PORT,
|
||||
isSecure = true
|
||||
)
|
||||
|
||||
val LightWalletEndpoint.Companion.Darkside
|
||||
get() = LightWalletEndpoint(
|
||||
COMPUTER_LOCALHOST,
|
||||
DEFAULT_PORT,
|
||||
isSecure = false
|
||||
)
|
|
@ -0,0 +1,43 @@
|
|||
package cash.z.ecc.android.sdk.model
|
||||
|
||||
/**
|
||||
* The Zcash network. Should be one of [ZcashNetwork.Testnet] or [ZcashNetwork.Mainnet].
|
||||
*
|
||||
* The constructor for the network is public to allow for certain test cases to use a custom "darkside" network.
|
||||
*/
|
||||
data class ZcashNetwork(
|
||||
val id: Int,
|
||||
val networkName: String,
|
||||
val saplingActivationHeight: BlockHeight,
|
||||
val orchardActivationHeight: BlockHeight
|
||||
) {
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
companion object {
|
||||
const val ID_TESTNET = 0
|
||||
const val ID_MAINNET = 1
|
||||
|
||||
// You may notice there are extra checkpoints bundled in the SDK that match the
|
||||
// sapling/orchard activation heights.
|
||||
|
||||
val Testnet = ZcashNetwork(
|
||||
ID_TESTNET,
|
||||
"testnet",
|
||||
saplingActivationHeight = BlockHeight(280_000),
|
||||
orchardActivationHeight = BlockHeight(1_842_420)
|
||||
)
|
||||
|
||||
val Mainnet = ZcashNetwork(
|
||||
ID_MAINNET,
|
||||
"mainnet",
|
||||
saplingActivationHeight = BlockHeight(419_200),
|
||||
orchardActivationHeight = BlockHeight(1_687_104)
|
||||
)
|
||||
|
||||
fun from(id: Int) = when (id) {
|
||||
0 -> Testnet
|
||||
1 -> Mainnet
|
||||
else -> throw IllegalArgumentException("Unknown network id: $id")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,7 +7,7 @@ import cash.z.ecc.android.sdk.internal.from
|
|||
import cash.z.ecc.android.sdk.internal.model.Checkpoint
|
||||
import cash.z.ecc.android.sdk.internal.twig
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.BufferedReader
|
||||
|
|
|
@ -2,8 +2,8 @@ package cash.z.ecc.android.sdk.tool
|
|||
|
||||
import cash.z.ecc.android.sdk.jni.RustBackend
|
||||
import cash.z.ecc.android.sdk.jni.RustBackendWelding
|
||||
import cash.z.ecc.android.sdk.model.ZcashNetwork
|
||||
import cash.z.ecc.android.sdk.type.UnifiedViewingKey
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
|
||||
class DerivationTool {
|
||||
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
package cash.z.ecc.android.sdk.type
|
||||
|
||||
import cash.z.ecc.android.sdk.model.BlockHeight
|
||||
|
||||
enum class ZcashNetwork(
|
||||
val id: Int,
|
||||
val networkName: String,
|
||||
val saplingActivationHeight: BlockHeight,
|
||||
val defaultHost: String,
|
||||
val defaultPort: Int
|
||||
) {
|
||||
Testnet(0, "testnet", BlockHeight(280_000), "testnet.lightwalletd.com", 9067),
|
||||
Mainnet(1, "mainnet", BlockHeight(419_200), "mainnet.lightwalletd.com", 9067);
|
||||
|
||||
companion object {
|
||||
fun from(id: Int) = values().first { it.id == id }
|
||||
}
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<bool name="lightwalletd_allow_very_insecure_connections">false</bool>
|
||||
</resources>
|
|
@ -1,3 +0,0 @@
|
|||
<resources>
|
||||
<string name="sdk_test_message">Library linking is working!</string>
|
||||
</resources>
|
|
@ -1,6 +1,5 @@
|
|||
package cash.z.ecc.android.sdk.model
|
||||
|
||||
import cash.z.ecc.android.sdk.type.ZcashNetwork
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package cash.z.ecc.android.sdk.model
|
||||
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class LightWalletEndpointTest {
|
||||
@Test
|
||||
fun requireSecureMainnet() {
|
||||
assertTrue(LightWalletEndpoint.Mainnet.isSecure)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun requireSecureTestnet() {
|
||||
assertTrue(LightWalletEndpoint.Testnet.isSecure)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue