[#283] Kotlin API for Zcash URI parser

- Includes Zip321UriBuildFixture for the toUri() method from the Rust layer.
- Includes Zip321UriParseFixture for the fromUri() method from the Rust layer.
- Added ZecRequestTest class for testing ZecRequest methods.
- Align Zip321UriBuildFixture and Zip321UriParseFixture parameters.
- Added comments to the new() methods of Zip321BuildFixture and Zip321ParseFixture.
This commit is contained in:
Honza Rychnovsky 2022-03-30 14:16:57 +02:00 committed by GitHub
parent fb5fc153a5
commit 39949d8632
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 195 additions and 15 deletions

View File

@ -0,0 +1,129 @@
package cash.z.ecc.sdk.model
import androidx.test.filters.SmallTest
import cash.z.ecc.sdk.fixture.Zip321UriBuildFixture
import cash.z.ecc.sdk.fixture.Zip321UriParseFixture
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.runTest
import org.junit.Ignore
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue
class ZecRequestTest {
companion object {
private const val URI: String = "zcash:tmXuTnE11JojToagTqxXUn6KvdxDE3iLKbp?amount=1&message=Hello%20world!"
@Suppress("MagicNumber")
private val AMOUNT = Zatoshi(1)
private val MESSAGE = ZecRequestMessage("Hello world!")
private const val ADDRESS_STRING = "tmXuTnE11JojToagTqxXUn6KvdxDE3iLKbp"
private val ADDRESS: WalletAddress.Unified = runBlocking {
WalletAddress.Unified.new(ADDRESS_STRING)
}
val REQUEST = ZecRequest(ADDRESS, AMOUNT, MESSAGE)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun parse_uri_not_null() = runTest {
val parsed = ZecRequest.fromUri(Zip321UriParseFixture.URI)
assertNotNull(parsed)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun parse_uri_valid_result() = runTest {
val parsed = ZecRequest.fromUri(Zip321UriParseFixture.URI)
assertTrue(parsed.message.value.length <= ZecRequestMessage.MAX_MESSAGE_LENGTH)
assertTrue(parsed.address.address.isNotEmpty())
assertTrue(parsed.amount.value >= 0)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun parse_uri_correct_result() = runTest {
val parsed = ZecRequest.fromUri(Zip321UriParseFixture.URI)
val expected = ZecRequest(
WalletAddress.Unified.new(Zip321UriParseFixture.ADDRESS),
Zip321UriParseFixture.AMOUNT,
Zip321UriParseFixture.MESSAGE
)
assertEquals(parsed, expected)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
@Ignore("Waiting for an implementation of Uri parser in SDK project")
fun parse_uri_incorrect_result() = runTest {
val parsed = ZecRequest.fromUri(URI)
val expected = REQUEST
val actual = ZecRequest(
WalletAddress.Unified.new(Zip321UriParseFixture.ADDRESS),
Zip321UriParseFixture.AMOUNT,
Zip321UriParseFixture.MESSAGE
)
assertNotEquals(parsed, expected)
assertEquals(parsed, actual)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun build_uri_not_null() = runTest {
val request = Zip321UriBuildFixture.REQUEST
val built = request.toUri()
assertNotNull(built)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun build_uri_valid_result() = runTest {
val request = Zip321UriBuildFixture.REQUEST
val built = request.toUri()
assertTrue(built.isNotEmpty())
assertTrue(built.startsWith("zcash"))
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
fun built_uri_correct_result() = runTest {
val request = Zip321UriBuildFixture.REQUEST
val built = request.toUri()
val expected = Zip321UriBuildFixture.URI
assertEquals(built, expected)
}
@Test
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
@Ignore("Waiting for an implementation of Uri parser in SDK project")
fun build_uri_incorrect_result() = runTest {
val request = Zip321UriBuildFixture.REQUEST
val built = request.toUri()
val expected = URI
val actual = Zip321UriBuildFixture.URI
assertNotEquals(built, expected)
assertEquals(built, actual)
}
}

View File

@ -0,0 +1,26 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
import kotlinx.coroutines.runBlocking
object Zip321UriBuildFixture {
// TODO [#161]: Pending SDK support
const val URI: String = "zcash:Unified%20GitHub%20Issue%20#161?amount=123&message=Thank%20you%20" +
"for%20your%20purchase"
@Suppress("MagicNumber")
val AMOUNT = Zatoshi(123)
val MESSAGE = ZecRequestMessage("Thank you for your purchase")
val ADDRESS: WalletAddress.Unified = runBlocking {
WalletAddress.Unified.new(WalletAddressFixture.UNIFIED_ADDRESS_STRING)
}
val REQUEST = ZecRequest(ADDRESS, AMOUNT, MESSAGE)
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
// Should return ZecRequest.toUri(request) ideally, but it'd end up with an infinite loop for now.
@Suppress("UNUSED_PARAMETER")
suspend fun new(request: ZecRequest = REQUEST) = URI
}

View File

@ -0,0 +1,24 @@
package cash.z.ecc.sdk.fixture
import cash.z.ecc.sdk.model.WalletAddress
import cash.z.ecc.sdk.model.Zatoshi
import cash.z.ecc.sdk.model.ZecRequest
import cash.z.ecc.sdk.model.ZecRequestMessage
object Zip321UriParseFixture {
// TODO [#161]: Pending SDK support
const val URI: String = "zcash:Unified%20GitHub%20Issue%20#161?amount=123&message=Thank%20you%20" +
"for%20your%20purchase"
const val ADDRESS: String = WalletAddressFixture.UNIFIED_ADDRESS_STRING
@Suppress("MagicNumber")
val AMOUNT = Zatoshi(123)
val MESSAGE = ZecRequestMessage("Thank you for your purchase")
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
// Should return ZecRequest.fromUri(toParse) ideally, but it'd end up with an infinite loop for now.
@Suppress("UNUSED_PARAMETER")
suspend fun new(
toParse: String = URI,
) = ZecRequest(WalletAddress.Unified.new(ADDRESS), AMOUNT, MESSAGE)
}

View File

@ -1,21 +1,19 @@
package cash.z.ecc.sdk.model
import cash.z.ecc.sdk.fixture.ZecRequestFixture
import kotlinx.coroutines.runBlocking
import cash.z.ecc.sdk.fixture.Zip321UriBuildFixture
import cash.z.ecc.sdk.fixture.Zip321UriParseFixture
data class ZecRequest(val address: WalletAddress.Unified, val amount: Zatoshi, val message: ZecRequestMessage) {
// https://github.com/zcash/zcash-android-wallet-sdk/issues/397
// TODO [#397]: There's an issue in the SDK to implement the parser
@Suppress("FunctionOnlyReturningConstant")
fun toUri(): String = ""
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
suspend fun toUri(): String {
return Zip321UriBuildFixture.new(this)
}
companion object {
@Suppress("UNUSED_PARAMETER")
suspend fun fromUri(uriString: String) {
// TODO [#397]: Use URI parser
runBlocking { ZecRequestFixture.new() }
// TODO [#397]: Waiting for an implementation of Uri parser in SDK project
suspend fun fromUri(uriString: String): ZecRequest {
return Zip321UriParseFixture.new(uriString)
}
}
}

View File

@ -48,6 +48,7 @@ import co.electriccoin.zcash.ui.screen.send.view.Send
import co.electriccoin.zcash.ui.screen.settings.view.Settings
import co.electriccoin.zcash.ui.screen.wallet_address.view.WalletAddresses
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@ -459,8 +460,10 @@ private fun copyToClipboard(context: Context, persistableWallet: PersistableWall
clipboardManager.setPrimaryClip(data)
}
private fun ZecRequest.newShareIntent(context: Context) = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, context.getString(R.string.request_template_format, toUri()))
type = "text/plain"
private fun ZecRequest.newShareIntent(context: Context) = runBlocking {
Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, context.getString(R.string.request_template_format, toUri()))
type = "text/plain"
}
}