zcash-android-wallet-sdk/sdk-lib/src/androidTest/java/cash/z/ecc/android/sdk/sample/TransparentRestoreSample.kt

248 lines
9.0 KiB
Kotlin

@file:Suppress("MaxLineLength")
package cash.z.ecc.android.sdk.sample
import androidx.test.filters.LargeTest
import cash.z.ecc.android.sdk.ext.ZcashSdk
import cash.z.ecc.android.sdk.model.BlockHeight
import cash.z.ecc.android.sdk.model.Zatoshi
import cash.z.ecc.android.sdk.model.ZcashNetwork
import cash.z.ecc.android.sdk.util.TestWallet
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import org.junit.Assert
import org.junit.Ignore
import org.junit.Test
/**
* Sample tests are used to demonstrate functionality. This one attempts to setup a scenario where
* one wallet shields funds and the other restores from the blockchain. Ultimately, they should have
* the same data.
*/
class TransparentRestoreSample {
val TX_VALUE = Zatoshi(ZcashSdk.MINERS_FEE.value / 2)
// val walletA = SimpleWallet(SEED_PHRASE, "WalletA")
// the wallet that only restores what everyone else did
// val walletB = SimpleWallet(SEED_PHRASE, "WalletB")
// // the wallet that sends Z2T transactions
//
// // sandbox wallet
// val walletSandbox = SimpleWallet(SEED_PHRASE, "WalletC")
// val walletZ2T = SimpleWallet(SEED_PHRASE, "WalletZ2T")
// val externalTransparentAddress =
// DerivationTool.deriveTransparentAddress(Mnemonics.MnemonicCode(RANDOM_PHRASE).toSeed(), Testnet)
// @Test
fun sendZ2Texternal() = runBlocking {
val extWallet = TestWallet(TestWallet.Backups.ALICE, alias = "WalletE")
extWallet.sync()
// extWallet.send(542, walletSandbox.transparentAddress, "External funds memo is lost, though")
delay(1000)
}
// @Test
fun sendZ2T() = runBlocking {
// walletSandbox.sync()
// walletZ2T.send(543, externalTransparentAddress, "External funds memo is lost, though")
delay(1000)
}
// @Test
fun autoShield() = runBlocking<Unit> {
val wallet = TestWallet(TestWallet.Backups.SAMPLE_WALLET, alias = "WalletC")
wallet.sync()
val tbalance = wallet.transparentBalance()
val address = wallet.transparentAddress
Assert.assertTrue(
"Not enough funds to run sample. Expected some Zatoshi but found ${tbalance.available}. " +
"Try adding funds to $address",
tbalance.available.value > 0
)
// wallet.shieldFunds()
}
// @Test
fun cli() = runBlocking<Unit> {
// val wallet = SimpleWallet(SEED_PHRASE, "WalletCli")
// wallet.sync()
// wallet.rewindToHeight(1343500).join(45_000)
val wallet = TestWallet(TestWallet.Backups.SAMPLE_WALLET, alias = "WalletC")
// wallet.sync().rewindToHeight(1339178).join(10000)
wallet.sync().rewindToHeight(BlockHeight.new(ZcashNetwork.Testnet, 1339178)).send(
"ztestsapling17zazsl8rryl8kjaqxnr2r29rw9d9a2mud37ugapm0s8gmyv0ue43h9lqwmhdsp3nu9dazeqfs6l",
"is send broken?"
).join(5)
}
// This test is extremely slow and doesn't assert anything, so the benefit of this test is unclear
// It is disabled to allow moving forward with configuring CI.
@Test
@LargeTest
@Ignore("This test is extremely slow")
fun kris() = runBlocking<Unit> {
val wallet0 = TestWallet(
TestWallet.Backups.SAMPLE_WALLET.seedPhrase,
"tmpabc",
ZcashNetwork.Testnet,
startHeight = BlockHeight.new(
ZcashNetwork.Testnet,
1330190
)
)
// val wallet1 = SimpleWallet(WALLET0_PHRASE, "Wallet1")
wallet0.sync() // .shieldFunds()
// .send(amount = 1543L, memo = "")
.join()
// wallet1.sync().join(5_000L)
}
/*
*/
/**
* Sanity check that the wallet has enough funds for the test
*/
// @Test
fun hasFunds() = runBlocking<Unit> {
val walletSandbox = TestWallet(
TestWallet.Backups.SAMPLE_WALLET.seedPhrase,
"WalletC",
ZcashNetwork.Testnet,
startHeight = BlockHeight.new(
ZcashNetwork.Testnet,
1330190
)
)
// val job = walletA.walletScope.launch {
// walletA.sync()
// }
walletSandbox.sync()
// job.join()
delay(500)
// val value = walletA.available
// val address = walletA.shieldedAddress
// Assert.assertTrue("Not enough funds to run sample. Expected at least $TX_VALUE Zatoshi but found $value. Try adding funds to $address", value >= TX_VALUE)
// send z->t
// walletA.send(TX_VALUE, walletA.transparentAddress, "${TransparentRestoreSample::class.java.simpleName} z->t")
walletSandbox.rewindToHeight(BlockHeight.new(ZcashNetwork.Testnet, 1339178))
delay(500)
// walletB.sync()
// rewind database B to height then rescan
}
// // when startHeight is null, it will use the latest checkpoint
// class SimpleWallet(
// seedPhrase: String,
// alias: String = ZcashSdk.DEFAULT_ALIAS,
// startHeight: Int? = null
// ) {
// val walletScope = CoroutineScope(
// SupervisorJob() + newFixedThreadPoolContext(3, this.javaClass.simpleName)
// )
// private val context = InstrumentationRegistry.getInstrumentation().context
// private val seed: ByteArray = Mnemonics.MnemonicCode(seedPhrase).toSeed()
// private val shieldedSpendingKey = DerivationTool.deriveSpendingKeys(seed, Testnet)[0]
// private val transparentAccountPrivateKey = DerivationTool.deriveTransparentAccountPrivateKey(seed, Testnet)
// private val host = "lightwalletd.testnet.electriccoin.co"
// private val initializer = Initializer(context) { config ->
// config.importWallet(seed, startHeight)
// config.setNetwork(Testnet, host)
// config.alias = alias
// }
//
// val synchronizer = Synchronizer(initializer)
// val available get() = synchronizer.latestBalance.availableZatoshi
// val shieldedAddress = DerivationTool.deriveShieldedAddress(seed, Testnet)
// val transparentAddress = DerivationTool.deriveTransparentAddress(seed, Testnet)
// val birthdayHeight get() = synchronizer.latestBirthdayHeight
//
// suspend fun transparentBalance(): WalletBalance {
// synchronizer.refreshUtxos(transparentAddress, synchronizer.latestBirthdayHeight)
// return synchronizer.getTransparentBalance(transparentAddress)
// }
//
// suspend fun sync(): SimpleWallet {
// if (!synchronizer.isStarted) {
// twig("Starting sync")
// synchronizer.start(walletScope)
// } else {
// twig("Awaiting next SYNCED status")
// }
//
// // block until synced
// synchronizer.status.first { it == SYNCED }
// twig("Synced!")
// return this
// }
//
// suspend fun send(address: String = transparentAddress, memo: String = "", amount: Long = 500L): SimpleWallet {
// synchronizer.sendToAddress(shieldedSpendingKey, amount, address, memo)
// .takeWhile { it.isPending() }
// .collect {
// twig("Updated transaction: $it")
// }
// return this
// }
//
// suspend fun rewindToHeight(height: Int): SimpleWallet {
// synchronizer.rewindToHeight(height, false)
// return this
// }
//
// suspend fun shieldFunds(): SimpleWallet {
// twig("checking $transparentAddress for transactions!")
// synchronizer.refreshUtxos(transparentAddress, 935000).let { count ->
// twig("FOUND $count new UTXOs")
// }
//
// synchronizer.getTransparentBalance(transparentAddress).let { walletBalance ->
// twig("FOUND utxo balance of total: ${walletBalance.totalZatoshi} available: ${walletBalance.availableZatoshi}")
//
// if (walletBalance.availableZatoshi > 0L) {
// synchronizer.shieldFunds(shieldedSpendingKey, transparentAccountPrivateKey)
// .onCompletion { twig("done shielding funds") }
// .catch { twig("Failed with $it") }
// .collect()
// }
// }
//
// return this
// }
//
// suspend fun join(timeout: Long? = null): SimpleWallet {
// // block until stopped
// twig("Staying alive until synchronizer is stopped!")
// if (timeout != null) {
// twig("Scheduling a stop in ${timeout}ms")
// walletScope.launch {
// delay(timeout)
// synchronizer.stop()
// }
// }
// synchronizer.status.first { it == Synchronizer.Status.STOPPED }
// twig("Stopped!")
// return this
// }
//
// companion object {
// init {
// Twig.plant(TroubleshootingTwig())
// }
// }
// }
}