248 lines
9.0 KiB
Kotlin
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())
|
|
// }
|
|
// }
|
|
// }
|
|
}
|