New: Sample test for auto-shielding.
Trying a new approach to writing sample tests that can serve as code examples.
This commit is contained in:
parent
71ac92e77a
commit
7214850abf
|
@ -0,0 +1,69 @@
|
|||
package cash.z.ecc.android.sdk.jni
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import cash.z.ecc.android.bip39.Mnemonics.MnemonicCode
|
||||
import cash.z.ecc.android.bip39.Mnemonics.WordCount.COUNT_24
|
||||
import cash.z.ecc.android.bip39.toSeed
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class TransparentTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deriveTransparentSecretKeyTest() {
|
||||
assertEquals(Expected.tskCompressed, DerivationTool.deriveTransparentSecretKey(SEED))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deriveTransparentAddressTest() {
|
||||
assertEquals(Expected.tAddr, DerivationTool.deriveTransparentAddress(SEED))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun deriveTransparentAddressFromSecretKeyTest() {
|
||||
assertEquals(Expected.tAddr, DerivationTool.deriveTransparentAddress(Expected.tskCompressed))
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun deriveTransparentAddressFromSecretKeyTest2() {
|
||||
// while(false) {
|
||||
// MnemonicCode(COUNT_24).let { phrase ->
|
||||
// val addr = DerivationTool.deriveShieldedAddress(phrase.toSeed())
|
||||
// twig("$addr${String(phrase.chars)}\t")
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
companion object {
|
||||
const val PHRASE = "deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"
|
||||
val MNEMONIC = MnemonicCode(PHRASE)
|
||||
val SEED = MNEMONIC.toSeed()
|
||||
|
||||
object Expected {
|
||||
val tAddr = "t1PKtYdJJHhc3Pxowmznkg7vdTwnhEsCvR4"
|
||||
|
||||
// private key in compressed Wallet Import Format (WIF)
|
||||
val tskCompressed = "L4BvDC33yLjMRxipZvdiUmdYeRfZmR8viziwsVwe72zJdGbiJPv2"
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun startup() {
|
||||
Twig.plant(TroubleshootingTwig(formatter = {"@TWIG $it"}))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package cash.z.ecc.android.sdk.sample
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import cash.z.ecc.android.bip39.Mnemonics
|
||||
import cash.z.ecc.android.bip39.toSeed
|
||||
import cash.z.ecc.android.sdk.Initializer
|
||||
import cash.z.ecc.android.sdk.Synchronizer
|
||||
import cash.z.ecc.android.sdk.Synchronizer.Status.SYNCED
|
||||
import cash.z.ecc.android.sdk.ext.TroubleshootingTwig
|
||||
import cash.z.ecc.android.sdk.ext.Twig
|
||||
import cash.z.ecc.android.sdk.ext.twig
|
||||
import cash.z.ecc.android.sdk.tool.DerivationTool
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.newFixedThreadPoolContext
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Samples related to shielding funds.
|
||||
*/
|
||||
class ShieldFundsSample {
|
||||
|
||||
val SEED_PHRASE = "wish puppy smile loan doll curve hole maze file ginger hair nose key relax knife witness cannon grab despair throw review deal slush frame"//\"still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread\"//\"deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"//"deputy visa gentle among clean scout farm drive comfort patch skin salt ranch cool ramp warrior drink narrow normal lunch behind salt deal person"
|
||||
|
||||
// simple flag to turn off actually spending funds
|
||||
val IS_DRY_RUN = true
|
||||
|
||||
/**
|
||||
* This test will construct a t2z transaction. It is safe to run this repeatedly, because
|
||||
* nothing is submitted to the network (because the keys don't match the address so the encoding
|
||||
* fails). Originally, it's intent is just to exercise the code and troubleshoot any issues but
|
||||
* then it became clear that this would be a cool Sample Test and PoC for writing a SimpleWallet
|
||||
* class.
|
||||
*/
|
||||
@Test
|
||||
fun constructT2Z() = runBlocking {
|
||||
Twig.sprout("ShieldFundsSample")
|
||||
|
||||
val wallet = SimpleWallet(SEED_PHRASE).sync()
|
||||
wallet.shieldFunds()
|
||||
|
||||
Twig.clip("ShieldFundsSample")
|
||||
Assert.assertEquals(5, wallet.synchronizer.latestBalance.availableZatoshi)
|
||||
}
|
||||
|
||||
|
||||
// when startHeight is null, it will use the latest checkpoint
|
||||
class SimpleWallet(seedPhrase: String, 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)[0]
|
||||
private val transparentSecretKey = DerivationTool.deriveTransparentSecretKey(seed)
|
||||
private val shieldedAddress = DerivationTool.deriveShieldedAddress(seed)
|
||||
|
||||
// t1b9Y6PESSGavavgge3ruTtX9X83817V29s
|
||||
private val transparentAddress = DerivationTool.deriveTransparentAddress(seed)
|
||||
|
||||
private val config = Initializer.Config {
|
||||
it.setSeed(seed)
|
||||
it.setBirthdayHeight(startHeight, false)
|
||||
it.server("lightwalletd.electriccoin.co", 9067)
|
||||
}
|
||||
|
||||
val synchronizer = Synchronizer(Initializer(context, config))
|
||||
|
||||
suspend fun sync(): SimpleWallet {
|
||||
twig("Starting sync")
|
||||
synchronizer.start(walletScope)
|
||||
// block until synced
|
||||
synchronizer.status.first { it == SYNCED }
|
||||
twig("Synced!")
|
||||
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 && !IS_DRY_RUN) {
|
||||
synchronizer.shieldFunds(shieldedSpendingKey, transparentSecretKey)
|
||||
.onCompletion { twig("done shielding funds") }
|
||||
.catch { twig("Failed with $it") }
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue