Consolidate old sample apps into new demo app.
|
@ -1 +0,0 @@
|
|||
/build
|
|
@ -1,37 +0,0 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
applicationId "cash.z.wallet.sdk.sample.address"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
missingDimensionStrategy "network", "zcashtestnet"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
matchingFallbacks = ['zcashtestnetRelease']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation project(path: ':sdk')
|
||||
// api project(path: ':sdk', configuration: 'default')
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${versions.kotlin}"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:${versions.coroutines}"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:${versions.coroutines}"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cash.z.wallet.sdk.sample.address">
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,34 +0,0 @@
|
|||
package cash.z.wallet.sdk.sample.address
|
||||
|
||||
import cash.z.wallet.sdk.jni.RustBackend
|
||||
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
|
||||
object Injection {
|
||||
private val rustBackend: RustBackendWelding = RustBackend()
|
||||
private const val dataDbName = "AddressSampleData.db"
|
||||
|
||||
fun provideWallet(
|
||||
seedProvider: ReadOnlyProperty<Any?, ByteArray>,
|
||||
spendingKeyProvider: ReadWriteProperty<Any?, String>
|
||||
): Wallet {
|
||||
// simulate new session for each call
|
||||
App.instance.getDatabasePath(dataDbName).absoluteFile.delete()
|
||||
|
||||
return Wallet(
|
||||
context = App.instance,
|
||||
birthday = Wallet.loadBirthdayFromAssets(App.instance, 421720),
|
||||
rustBackend = provideRustBackend(),
|
||||
dataDbName = dataDbName,
|
||||
seedProvider = seedProvider,
|
||||
spendingKeyProvider = spendingKeyProvider
|
||||
)
|
||||
}
|
||||
|
||||
fun provideRustBackend(): RustBackendWelding {
|
||||
return rustBackend
|
||||
}
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
package cash.z.wallet.sdk.sample.address
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import cash.z.wallet.sdk.data.TroubleshootingTwig
|
||||
import cash.z.wallet.sdk.data.Twig
|
||||
import cash.z.wallet.sdk.ext.SampleSeedProvider
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
/**
|
||||
* Sample app that shows how to access the address and spending key.
|
||||
*/
|
||||
class MainActivity : AppCompatActivity() {
|
||||
private lateinit var wallet: Wallet
|
||||
private lateinit var addressInfo: TextView
|
||||
|
||||
// Secure storage is out of scope for this example (wallet makers know how to securely store things)
|
||||
// However, any class can implement the required interface for these dependencies. The expectation is that a wallet
|
||||
// maker would wrap an existing class with something that implements the property interface to access data. These
|
||||
// dependencies would then point to those wrappers.
|
||||
private val mockSecureStorage = Delegates.notNull<String>()
|
||||
private val mockSecureSeedProvider = SampleSeedProvider("testreferencealice")
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
|
||||
addressInfo = findViewById(R.id.text_address_info)
|
||||
|
||||
wallet = Injection.provideWallet(mockSecureSeedProvider, mockSecureStorage).also { it.initialize() }
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
addressInfo.text = createAddressInfo()
|
||||
}
|
||||
|
||||
private fun createAddressInfo(): String {
|
||||
val address = wallet.getAddress()
|
||||
val key by mockSecureStorage
|
||||
val info = """
|
||||
seed:
|
||||
${mockSecureSeedProvider.seedValue}
|
||||
--------------------------------------
|
||||
address:
|
||||
$address
|
||||
--------------------------------------
|
||||
spendingKey:
|
||||
$key
|
||||
""".trimIndent()
|
||||
return info
|
||||
}
|
||||
|
||||
fun onTestThings(view: View) {
|
||||
// This is a good place to insert some test behavior to try out the SDK in response to a click
|
||||
// it may help to add objects to the Injection.kt file
|
||||
Toast.makeText(this, "Test SDK behavior", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package cash.z.wallet.sdk.sample.address
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
open class ScopedActivity : AppCompatActivity(), CoroutineScope {
|
||||
private lateinit var job: Job
|
||||
|
||||
override val coroutineContext: CoroutineContext
|
||||
get() = job + Dispatchers.Main
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
job = Job()
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0"/>
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0"/>
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1"/>
|
||||
</vector>
|
|
@ -1,74 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="108dp"
|
||||
android:width="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path android:fillColor="#008577"
|
||||
android:pathData="M0,0h108v108h-108z"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||
</vector>
|
|
@ -1,29 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_address_info"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="60dp"
|
||||
android:onClick="onTestThings"
|
||||
android:text="Test Something"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 15 KiB |
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#008577</color>
|
||||
<color name="colorPrimaryDark">#00574B</color>
|
||||
<color name="colorAccent">#D81B60</color>
|
||||
</resources>
|
|
@ -1,3 +0,0 @@
|
|||
<resources>
|
||||
<string name="app_name">Zcash Address</string>
|
||||
</resources>
|
|
@ -1,25 +0,0 @@
|
|||
buildscript {
|
||||
ext.versions = [
|
||||
'kotlin': '1.3.50',
|
||||
'coroutines': '1.3.0-M1'
|
||||
]
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.6.0-alpha11'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
|
@ -1,3 +0,0 @@
|
|||
include ':app', ":sdk"
|
||||
project(":sdk").projectDir = file("../../../zcash-android-wallet-sdk")
|
||||
rootProject.name='Zcash Address'
|
|
@ -0,0 +1,67 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
apply plugin: 'kotlin-kapt'
|
||||
apply plugin: 'androidx.navigation.safeargs'
|
||||
|
||||
android {
|
||||
compileSdkVersion 29
|
||||
buildToolsVersion "29.0.2"
|
||||
viewBinding.enabled = true
|
||||
defaultConfig {
|
||||
applicationId "cash.z.wallet.sdk.demoapp"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
missingDimensionStrategy "network", "zcashtestnet"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// SDK
|
||||
implementation project(path: ':sdk')
|
||||
// implementation "cash.z.android.wallet:zcash-android-testnet:$sdk_version@aar"
|
||||
|
||||
// SDK: grpc
|
||||
implementation "io.grpc:grpc-okhttp:1.21.0"
|
||||
implementation "io.grpc:grpc-protobuf-lite:1.21.0"
|
||||
implementation "io.grpc:grpc-stub:1.21.0"
|
||||
implementation "io.grpc:grpc-android:1.21.0"
|
||||
implementation 'javax.annotation:javax.annotation-api:1.3.2'
|
||||
// SDK: Room
|
||||
implementation "androidx.room:room-runtime:2.2.0"
|
||||
implementation "androidx.room:room-common:2.2.0"
|
||||
implementation "androidx.paging:paging-runtime-ktx:2.1.0"
|
||||
implementation 'com.google.guava:guava:27.0.1-android'
|
||||
kapt "androidx.room:room-compiler:2.2.0"
|
||||
// SDK: Other
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
|
||||
|
||||
// Android
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||
implementation 'androidx.core:core-ktx:1.1.0'
|
||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.navigation:navigation-fragment:2.0.0'
|
||||
implementation 'androidx.navigation:navigation-ui:2.0.0'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.0.0'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.0.0'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
|
||||
implementation "androidx.lifecycle:lifecycle-common-java8:2.2.0-beta01"
|
||||
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-beta01" // provides lifecycleScope!
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package cash.z.wallet.sdk.sample.demoapp
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* See [testing documentation](http://d.android.com/tools/testing).
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ExampleInstrumentedTest {
|
||||
@Test
|
||||
fun useAppContext() {
|
||||
// Context of the app under test.
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
assertEquals("cash.z.wallet.sdk.sample.demoapp", appContext.packageName)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
package cash.z.wallet.sdk.sample.demoapp
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import cash.z.wallet.sdk.data.*
|
||||
import cash.z.wallet.sdk.demoapp.util.SampleStorageBridge
|
||||
import cash.z.wallet.sdk.ext.ZcashSdk
|
||||
import cash.z.wallet.sdk.ext.convertZecToZatoshi
|
||||
import cash.z.wallet.sdk.ext.toZec
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import cash.z.wallet.sdk.service.LightWalletGrpcService
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertNotNull
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
/**
|
||||
* Sample code to demonstrate key functionality without UI, inspired by:
|
||||
* https://github.com/EdgeApp/eosjs-node-cli/blob/paul/cleanup/app.js
|
||||
*/
|
||||
class SampleCodeTest {
|
||||
|
||||
private val seed = "Insert seed for testing".toByteArray()
|
||||
private val lightwalletdHost: String = "34.68.177.238"
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Seed derivation
|
||||
@Ignore @Test fun createBip39Seed_fromSeedPhrase() {
|
||||
// TODO: log(seedPhrase.asRawEntropy().asBip39seed())
|
||||
}
|
||||
|
||||
@Ignore @Test fun createRawEntropy() {
|
||||
// TODO: call: Mnemonic::from_phrase(seed_phrase, Language::English).unwrap().entropy()
|
||||
// log(seedPhrase.asRawEntropy())
|
||||
}
|
||||
|
||||
@Ignore @Test fun createBip39Seed_fromRawEntropy() {
|
||||
// get the 64 byte bip39 entropy
|
||||
// TODO: call: bip39::Seed::new(&Mnemonic::from_entropy(&seed_bytes, Language::English).unwrap(), "")
|
||||
// log(rawEntropy.asBip39Seed())
|
||||
}
|
||||
|
||||
@Ignore @Test fun deriveSeedPhraseFrom() {
|
||||
// TODO: let mnemonic = Mnemonic::from_entropy(entropy, Language::English).unwrap();
|
||||
// log(entropy.asSeedPhrase())
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Derive Extended Spending Key
|
||||
@Test fun deriveSpendingKey() {
|
||||
val wallet = Wallet()
|
||||
val privateKeys = wallet.initialize(context, seed)
|
||||
assertNotNull("Wallet already existed.", privateKeys)
|
||||
|
||||
log("Spending Key: ${privateKeys?.get(0)}")
|
||||
log("Address: ${wallet.getAddress()}")
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Derive address from Extended Spending Key
|
||||
@Test fun getAddressFromSpendingKey() {
|
||||
// TODO: turn spending key into viewing key via:
|
||||
// let extfvks: Vec<_> = extsks.iter().map(ExtendedFullViewingKey::from).collect();
|
||||
// val viewingKey = spendingKey //.asViewingKey()
|
||||
// return getAddressFromViewingKey(viewingKey)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////
|
||||
// Derive address from Extended Full Viewing Key
|
||||
@Test fun getAddressFromViewingKey() {
|
||||
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Query latest block height
|
||||
@Test fun getLatestBlockHeightTest() {
|
||||
val lightwalletService = LightWalletGrpcService(context, lightwalletdHost)
|
||||
log("Latest Block: ${lightwalletService.getLatestBlockHeight()}")
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Download compact block range
|
||||
@Test fun getBlockRange() {
|
||||
val blockRange = 500_000..500_009
|
||||
val lightwalletService = LightWalletGrpcService(context, lightwalletdHost)
|
||||
val blocks = lightwalletService.getBlockRange(blockRange)
|
||||
assertEquals(blockRange.count(), blocks.size)
|
||||
|
||||
blocks.forEachIndexed { i, block ->
|
||||
log("Block #$i: height:${block.height} hash:${block.hash.toByteArray().toHex()}")
|
||||
}
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Query account outgoing transactions
|
||||
@Test fun queryOutgoingTransactions() {
|
||||
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Query account incoming transactions
|
||||
@Test fun queryIncomingTransactions() {
|
||||
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Create a signed transaction (with memo)
|
||||
@Test fun createTransaction() = runBlocking {
|
||||
val wallet = Wallet()
|
||||
val repository = PagedTransactionRepository(context)
|
||||
val keyManager = SampleStorageBridge().securelyStoreSeed(seed)
|
||||
val encoder = WalletTransactionEncoder(wallet, repository, keyManager)
|
||||
val amount = 0.123.toZec().convertZecToZatoshi()
|
||||
val address = "ztestsapling1tklsjr0wyw0d58f3p7wufvrj2cyfv6q6caumyueadq8qvqt8lda6v6tpx474rfru9y6u75u7qnw"
|
||||
val memo = "Test Transaction"
|
||||
val encodedTx = encoder.create(amount, address, memo ?: "")
|
||||
}
|
||||
|
||||
// ///////////////////////////////////////////////////
|
||||
// Create a signed transaction (with memo) and broadcast
|
||||
@Test fun submitTransaction() = runBlocking {
|
||||
val amount = 0.123.toZec().convertZecToZatoshi()
|
||||
val address = "ztestsapling1tklsjr0wyw0d58f3p7wufvrj2cyfv6q6caumyueadq8qvqt8lda6v6tpx474rfru9y6u75u7qnw"
|
||||
val memo = "Test Transaction"
|
||||
val transaction = synchronizer.sendToAddress(amount, address, memo)
|
||||
log("transaction: $transaction")
|
||||
}
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// Utility Functions
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
companion object {
|
||||
private val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
private lateinit var synchronizer: SdkSynchronizer
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun init() {
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
reset()
|
||||
}
|
||||
|
||||
fun log(message: String?) = twig(message ?: "null")
|
||||
|
||||
private fun reset() {
|
||||
context.getDatabasePath(ZcashSdk.DB_DATA_NAME).absoluteFile.delete()
|
||||
context.getDatabasePath(ZcashSdk.DB_CACHE_NAME).absoluteFile.delete()
|
||||
}
|
||||
|
||||
|
||||
private fun ByteArray.toHex(): String {
|
||||
val sb = StringBuilder(size * 2)
|
||||
for (b in this)
|
||||
sb.append(String.format("%02x", b))
|
||||
return sb.toString()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="cash.z.wallet.sdk.demoapp">
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/AppTheme.NoActionBar">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,4 +1,4 @@
|
|||
package cash.z.wallet.sdk.sample.address
|
||||
package cash.z.wallet.sdk.demoapp
|
||||
|
||||
import android.app.Application
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package cash.z.wallet.sdk.demoapp
|
||||
|
||||
import cash.z.wallet.sdk.jni.RustBackend
|
||||
import cash.z.wallet.sdk.jni.RustBackendWelding
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* This file represents the dependencies that are specific to this demo. Normally, a dependency
|
||||
* injection framework like Dagger would provide these objects. For the sake of simplicity, we // TODO finish explaining
|
||||
*/
|
||||
object AppInjection {
|
||||
|
||||
fun provideRustBackend(prefix: String): RustBackendWelding {
|
||||
return RustBackend.create(App.instance, "${prefix}_Cache.db", "${prefix}_Data.db")
|
||||
}
|
||||
|
||||
/**
|
||||
* A sample class that pretends to securely accept a value, store it and return it later. In
|
||||
* practice, a wallet maker may have a way of securely storing data.
|
||||
*/
|
||||
class Vault(var value: String = "") : ReadWriteProperty<Any?, String> {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): String = value
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
||||
this.value = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
package cash.z.wallet.sdk.demoapp
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import cash.z.wallet.sdk.data.TroubleshootingTwig
|
||||
import cash.z.wallet.sdk.data.Twig
|
||||
import kotlinx.coroutines.Dispatchers.IO
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
abstract class BaseDemoFragment<T : ViewBinding> : Fragment() {
|
||||
|
||||
lateinit var binding: T
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
Twig.plant(TroubleshootingTwig())
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
binding = inflateBinding(layoutInflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// just a quick way of enforcing the following for each demo:
|
||||
// - wait until the fragment is created, then run `initInBackground` on a background thread
|
||||
// - wait until init is finished
|
||||
// - and then run `onInitComplete` on the Main thread
|
||||
// - but only once the fragment is resumed
|
||||
// - and if the fragment/activity/app is stopped during any of this, exit cleanly
|
||||
//
|
||||
// Why?
|
||||
// Because this is a demo. In a full-blown app, there would be other appropriate times to
|
||||
// load things. Also, we want each demo to stand alone. It is abnormal for a fragment to
|
||||
// always recreate application state but that's the behavior we want for the demos.
|
||||
// So we use this approach to coordinate two sets of logic and ensure they run sequentially
|
||||
// while also respecting the lifecycle. If we didn't do this, the `initInBackground` would
|
||||
// freeze the UI while the fragment is created and `onInitComplete` would have no way of
|
||||
// knowing when the background thread work is done and thereby could run in the wrong order.
|
||||
lifecycleScope.launchWhenCreated {
|
||||
withContext(IO) {
|
||||
resetInBackground()
|
||||
lifecycleScope.launchWhenResumed {
|
||||
onResetComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
onClear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflate the ViewBinding. Unfortunately, the `inflate` function is not part of the ViewBinding
|
||||
* interface so the base class cannot take care of this behavior without some help.
|
||||
*/
|
||||
abstract fun inflateBinding(layoutInflater: LayoutInflater): T
|
||||
abstract fun resetInBackground()
|
||||
abstract fun onResetComplete()
|
||||
abstract fun onClear()
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package cash.z.wallet.sdk.demoapp
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.android.material.navigation.NavigationView
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.ui.AppBarConfiguration
|
||||
import androidx.navigation.ui.navigateUp
|
||||
import androidx.navigation.ui.setupActionBarWithNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_main)
|
||||
val toolbar: Toolbar = findViewById(R.id.toolbar)
|
||||
setSupportActionBar(toolbar)
|
||||
|
||||
val fab: FloatingActionButton = findViewById(R.id.fab)
|
||||
fab.setOnClickListener { view ->
|
||||
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
|
||||
.setAction("Action", null).show()
|
||||
}
|
||||
val drawerLayout: DrawerLayout = findViewById(R.id.drawer_layout)
|
||||
val navView: NavigationView = findViewById(R.id.nav_view)
|
||||
val navController = findNavController(R.id.nav_host_fragment)
|
||||
// Passing each menu ID as a set of Ids because each
|
||||
// menu should be considered as top level destinations.
|
||||
appBarConfiguration = AppBarConfiguration(
|
||||
setOf(
|
||||
R.id.nav_home, R.id.nav_address, R.id.nav_block, R.id.nav_private_key,
|
||||
R.id.nav_latest_height, R.id.nav_block_range,
|
||||
R.id.nav_transactions, R.id.nav_send
|
||||
), drawerLayout
|
||||
)
|
||||
setupActionBarWithNavController(navController, appBarConfiguration)
|
||||
navView.setupWithNavController(navController)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.main, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSupportNavigateUp(): Boolean {
|
||||
val navController = findNavController(R.id.nav_host_fragment)
|
||||
return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.getaddress
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentGetAddressBinding
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
|
||||
class GetAddressFragment : BaseDemoFragment<FragmentGetAddressBinding>() {
|
||||
|
||||
private var seed: ByteArray = App.instance.defaultConfig.seed
|
||||
private lateinit var wallet: Wallet
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetAddressBinding
|
||||
= FragmentGetAddressBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
/**
|
||||
* Create and initialize the wallet. Initialization will return the private keys but for the
|
||||
* purposes of this demo we don't need them.
|
||||
*/
|
||||
wallet = Wallet().also {
|
||||
it.initialize(App.instance, seed)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
binding.textInfo.text = wallet.getAddress()
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
wallet.clear()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.getblock
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentGetBlockBinding
|
||||
import cash.z.wallet.sdk.service.LightWalletGrpcService
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
|
||||
class GetBlockFragment : BaseDemoFragment<FragmentGetBlockBinding>() {
|
||||
private val host = App.instance.defaultConfig.host
|
||||
|
||||
private lateinit var lightwalletService: LightWalletService
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetBlockBinding =
|
||||
FragmentGetBlockBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
lightwalletService = LightWalletGrpcService(App.instance, host)
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
binding.buttonApply.setOnClickListener(::onApply)
|
||||
onApply(binding.textBlockHeight)
|
||||
}
|
||||
|
||||
private fun onApply(_unused: View) {
|
||||
setBlockHeight(binding.textBlockHeight.text.toString().toInt())
|
||||
}
|
||||
|
||||
private fun setBlockHeight(blockHeight: Int) {
|
||||
val blocks =
|
||||
lightwalletService.getBlockRange(blockHeight..blockHeight)
|
||||
val block = blocks.firstOrNull()
|
||||
binding.textInfo.text = """
|
||||
block height: ${block?.height}
|
||||
block vtxCount: ${block?.vtxCount}
|
||||
block time: ${block?.time}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
lightwalletService.shutdown()
|
||||
}
|
||||
}
|
||||
//
|
||||
//for block range, put them in a table and show a list of block heights and vtx count sorted by time
|
||||
//
|
||||
// and for this, allow input
|
|
@ -0,0 +1,61 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.getblockrange
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentGetBlockRangeBinding
|
||||
import cash.z.wallet.sdk.service.LightWalletGrpcService
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
|
||||
class GetBlockRangeFragment : BaseDemoFragment<FragmentGetBlockRangeBinding>() {
|
||||
|
||||
private val host = App.instance.defaultConfig.host
|
||||
|
||||
private lateinit var lightwalletService: LightWalletService
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetBlockRangeBinding =
|
||||
FragmentGetBlockRangeBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
lightwalletService = LightWalletGrpcService(App.instance, host)
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
binding.buttonApply.setOnClickListener(::onApply)
|
||||
onApply(binding.textInfo)
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
lightwalletService.shutdown()
|
||||
}
|
||||
|
||||
private fun onApply(_unused: View) {
|
||||
val start = binding.textStartHeight.text.toString().toInt()
|
||||
val end = binding.textEndHeight.text.toString().toInt()
|
||||
if (start <= end) {
|
||||
setBlockRange(start..end)
|
||||
} else {
|
||||
setError("Invalid range")
|
||||
}
|
||||
}
|
||||
|
||||
private fun setBlockRange(blockRange: IntRange) {
|
||||
val blocks =
|
||||
lightwalletService.getBlockRange(blockRange)
|
||||
val block = blocks.firstOrNull()
|
||||
binding.textInfo.text = """
|
||||
block height: ${block?.height}
|
||||
block vtxCount: ${block?.vtxCount}
|
||||
block time: ${block?.time}
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun setError(message: String) {
|
||||
binding.textInfo.text = "Error: $message"
|
||||
}
|
||||
}
|
||||
//
|
||||
//for block range, put them in a table and show a list of block heights and vtx count sorted by time
|
||||
//
|
||||
// and for this, allow input
|
|
@ -0,0 +1,30 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.getlatestheight
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentGetLatestHeightBinding
|
||||
import cash.z.wallet.sdk.service.LightWalletGrpcService
|
||||
import cash.z.wallet.sdk.service.LightWalletService
|
||||
|
||||
class GetLatestHeightFragment : BaseDemoFragment<FragmentGetLatestHeightBinding>() {
|
||||
private val host = App.instance.defaultConfig.host
|
||||
|
||||
private lateinit var lightwalletService: LightWalletService
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetLatestHeightBinding =
|
||||
FragmentGetLatestHeightBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
lightwalletService = LightWalletGrpcService(App.instance, host)
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
binding.textInfo.text = lightwalletService.getLatestBlockHeight().toString()
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
lightwalletService.shutdown()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.getprivatekey
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentGetPrivateKeyBinding
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
|
||||
class GetPrivateKeyFragment : BaseDemoFragment<FragmentGetPrivateKeyBinding>() {
|
||||
private var seed: ByteArray = App.instance.defaultConfig.seed
|
||||
private lateinit var wallet: Wallet
|
||||
private lateinit var privateKeys: Array<String>
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentGetPrivateKeyBinding =
|
||||
FragmentGetPrivateKeyBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
wallet = Wallet()
|
||||
|
||||
/*
|
||||
* Initialize with the seed and retrieve one private key for each account specified (by
|
||||
* default, only 1 account is created). In a normal circumstance, a wallet app would then
|
||||
* store these keys in its secure storage for retrieval, later. Private keys are only needed
|
||||
* for sending funds.
|
||||
*
|
||||
* Since we always clear the wallet, this function call will never return null. Otherwise, we
|
||||
* would interpret the null case to mean that the wallet data files already exist and
|
||||
* the private keys were stored externally (i.e. stored securely by the app, not the SDK).
|
||||
*/
|
||||
privateKeys = wallet.initialize(App.instance, seed)!!
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
binding.textInfo.text = privateKeys[0]
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
wallet.clear()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.home
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProviders
|
||||
import androidx.navigation.fragment.NavHostFragment
|
||||
import cash.z.wallet.sdk.data.twig
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.R
|
||||
import cash.z.wallet.sdk.ext.ZcashSdk
|
||||
|
||||
class HomeFragment : Fragment() {
|
||||
|
||||
private lateinit var homeViewModel: HomeViewModel
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
homeViewModel =
|
||||
ViewModelProviders.of(this).get(HomeViewModel::class.java)
|
||||
val root = inflater.inflate(R.layout.fragment_home, container, false)
|
||||
val textView: TextView = root.findViewById(R.id.text_home)
|
||||
homeViewModel.text.observe(viewLifecycleOwner, Observer {
|
||||
textView.text = it
|
||||
})
|
||||
return root
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
twig("Visiting the home screen clears the default databases, for sanity sake, because " +
|
||||
"each demo is intended to be self-contained.")
|
||||
App.instance.getDatabasePath(ZcashSdk.DB_DATA_NAME).absoluteFile.delete()
|
||||
App.instance.getDatabasePath(ZcashSdk.DB_CACHE_NAME).absoluteFile.delete()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.home
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
||||
class HomeViewModel : ViewModel() {
|
||||
|
||||
private val _text = MutableLiveData<String>().apply {
|
||||
value = "\u25c4\tSelect a demo"
|
||||
}
|
||||
val text: LiveData<String> = _text
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.listtransactions
|
||||
|
||||
import cash.z.wallet.sdk.data.PagedTransactionRepository
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.data.TransactionRepository
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.util.SampleStorageBridge
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
|
||||
object Injector {
|
||||
private val appContext = App.instance
|
||||
private val sampleSeed = App.instance.defaultConfig.seed
|
||||
private val birthdayHeight: Int = App.instance.defaultConfig.birthdayHeight
|
||||
private val host: String = App.instance.defaultConfig.host
|
||||
|
||||
private fun provideKeyManager(): Wallet.KeyManager {
|
||||
return SampleStorageBridge().securelyStoreSeed(sampleSeed)
|
||||
}
|
||||
|
||||
private fun provideWallet(keyManager: Wallet.KeyManager): Wallet {
|
||||
return Wallet().apply {
|
||||
initialize(appContext, keyManager.seed, birthdayHeight)?.let { privateKeys ->
|
||||
keyManager.key = privateKeys.first()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun provideLedger(): PagedTransactionRepository {
|
||||
return PagedTransactionRepository(appContext, 2)
|
||||
}
|
||||
|
||||
fun provideSynchronizer(ledger: TransactionRepository): Synchronizer {
|
||||
val keyManager = provideKeyManager()
|
||||
return Synchronizer(
|
||||
appContext, provideWallet(keyManager), host, keyManager,
|
||||
ledger = ledger
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.listtransactions
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.paging.PagedList
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import cash.z.wallet.sdk.data.PagedTransactionRepository
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentListTransactionsBinding
|
||||
import cash.z.wallet.sdk.entity.ReceivedTransaction
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* List all transactions from a given seed and birthdate, defined in the Injector class which is
|
||||
* intended to mimic dependency injection.
|
||||
*/
|
||||
class ListTransactionsFragment : BaseDemoFragment<FragmentListTransactionsBinding>() {
|
||||
private lateinit var ledger: PagedTransactionRepository
|
||||
private lateinit var synchronizer: Synchronizer
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater) =
|
||||
FragmentListTransactionsBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
ledger = Injector.provideLedger()
|
||||
synchronizer = Injector.provideSynchronizer(ledger)
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
initTransactionUI()
|
||||
startSynchronizer()
|
||||
monitorStatus()
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
ledger.close()
|
||||
synchronizer.stop()
|
||||
}
|
||||
|
||||
private fun monitorStatus() {
|
||||
lifecycleScope.launch {
|
||||
synchronizer.status.collect { onStatus(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun initTransactionUI() {
|
||||
binding.recyclerTransactions.layoutManager =
|
||||
LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
|
||||
binding.recyclerTransactions.adapter = TransactionAdapter()
|
||||
}
|
||||
|
||||
private fun startSynchronizer() {
|
||||
lifecycleScope.apply {
|
||||
synchronizer.start(this)
|
||||
launchProgressMonitor(synchronizer.progress())
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||
for (i in channel) {
|
||||
onProgress(i)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onProgress(i: Int) {
|
||||
val message = when (i) {
|
||||
100 -> "Scanning blocks..."
|
||||
else -> "Downloading blocks...$i%"
|
||||
}
|
||||
binding.textInfo.text = message
|
||||
}
|
||||
|
||||
private fun onStatus(status: Synchronizer.Status) {
|
||||
binding.textStatus.text = "Status: $status"
|
||||
if (status == Synchronizer.Status.SYNCED) onSyncComplete()
|
||||
}
|
||||
|
||||
private fun onSyncComplete() {
|
||||
binding.textInfo.visibility = View.INVISIBLE
|
||||
ledger.setTransactionPageListener(this) { t ->
|
||||
val adapter = binding.recyclerTransactions.adapter as TransactionAdapter
|
||||
adapter.submitList(t as PagedList<ReceivedTransaction>)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.listtransactions
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.paging.PagedListAdapter
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import cash.z.wallet.sdk.demoapp.R
|
||||
import cash.z.wallet.sdk.entity.ReceivedTransaction
|
||||
|
||||
class TransactionAdapter :
|
||||
PagedListAdapter<ReceivedTransaction, TransactionViewHolder>(
|
||||
DIFF_CALLBACK
|
||||
) {
|
||||
override fun onCreateViewHolder(
|
||||
parent: ViewGroup,
|
||||
viewType: Int
|
||||
) = TransactionViewHolder(
|
||||
LayoutInflater.from(parent.context).inflate(R.layout.item_transaction, parent, false)
|
||||
)
|
||||
|
||||
override fun onBindViewHolder(
|
||||
holder: TransactionViewHolder,
|
||||
position: Int
|
||||
) = holder.bindTo(getItem(position))
|
||||
|
||||
companion object {
|
||||
private val DIFF_CALLBACK = object : DiffUtil.ItemCallback<ReceivedTransaction>() {
|
||||
override fun areItemsTheSame(
|
||||
oldItem: ReceivedTransaction,
|
||||
newItem: ReceivedTransaction
|
||||
) = oldItem.minedHeight == newItem.minedHeight
|
||||
|
||||
override fun areContentsTheSame(
|
||||
oldItem: ReceivedTransaction,
|
||||
newItem: ReceivedTransaction
|
||||
) = oldItem.equals(newItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.listtransactions
|
||||
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import cash.z.wallet.sdk.demoapp.R
|
||||
import cash.z.wallet.sdk.entity.ReceivedTransaction
|
||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
class TransactionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||
private val amountText = itemView.findViewById<TextView>(R.id.text_transaction_amount)
|
||||
private val timeText = itemView.findViewById<TextView>(R.id.text_transaction_timestamp)
|
||||
private val formatter = SimpleDateFormat("M/d h:mma", Locale.getDefault())
|
||||
|
||||
fun bindTo(transaction: ReceivedTransaction?) {
|
||||
amountText.text = transaction?.value.convertZatoshiToZecString()
|
||||
timeText.text =
|
||||
if (transaction == null || transaction?.blockTimeInSeconds == 0L) "Pending"
|
||||
else formatter.format(transaction.blockTimeInSeconds * 1000L)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package cash.z.wallet.sdk.demoapp.demos.send
|
||||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.lifecycle.coroutineScope
|
||||
import cash.z.wallet.sdk.data.SdkSynchronizer
|
||||
import cash.z.wallet.sdk.data.Synchronizer
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.demoapp.BaseDemoFragment
|
||||
import cash.z.wallet.sdk.demoapp.databinding.FragmentSendBinding
|
||||
import cash.z.wallet.sdk.demoapp.util.SampleStorageBridge
|
||||
import cash.z.wallet.sdk.ext.convertZatoshiToZecString
|
||||
import cash.z.wallet.sdk.ext.convertZecToZatoshi
|
||||
import cash.z.wallet.sdk.ext.toZec
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import kotlinx.coroutines.channels.filterNot
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class SendFragment : BaseDemoFragment<FragmentSendBinding>() {
|
||||
private val sampleSeed = App.instance.defaultConfig.seed
|
||||
private val birthdayHeight: Int = App.instance.defaultConfig.birthdayHeight
|
||||
private val host: String = App.instance.defaultConfig.host
|
||||
|
||||
private lateinit var synchronizer: Synchronizer
|
||||
|
||||
override fun inflateBinding(layoutInflater: LayoutInflater): FragmentSendBinding =
|
||||
FragmentSendBinding.inflate(layoutInflater)
|
||||
|
||||
override fun resetInBackground() {
|
||||
val keyManager = SampleStorageBridge().securelyStoreSeed(sampleSeed)
|
||||
synchronizer =
|
||||
Synchronizer(App.instance, host, keyManager, birthdayHeight)
|
||||
}
|
||||
|
||||
override fun onResetComplete() {
|
||||
lifecycle.coroutineScope.apply {
|
||||
synchronizer.start(this)
|
||||
launchProgressMonitor(synchronizer.progress())
|
||||
launchBalanceMonitor(synchronizer.balances())
|
||||
}
|
||||
|
||||
binding.buttonSend.setOnClickListener(::onSend)
|
||||
}
|
||||
|
||||
override fun onClear() {
|
||||
// remove the stored databases
|
||||
(synchronizer as SdkSynchronizer).clearData()
|
||||
synchronizer.stop()
|
||||
}
|
||||
|
||||
private fun CoroutineScope.launchProgressMonitor(channel: ReceiveChannel<Int>) = launch {
|
||||
for (i in channel) {
|
||||
onProgress(i)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.launchBalanceMonitor(
|
||||
channel: ReceiveChannel<Wallet.WalletBalance>
|
||||
) = launch {
|
||||
val positiveBalances = channel.filterNot { it.total < 0 }
|
||||
for (i in positiveBalances) {
|
||||
onBalance(i)
|
||||
}
|
||||
}
|
||||
|
||||
private fun onProgress(i: Int) {
|
||||
val message = when (i) {
|
||||
100 -> "Scanning blocks..."
|
||||
else -> "Downloading blocks...$i%"
|
||||
}
|
||||
binding.textStatus.text = message
|
||||
}
|
||||
|
||||
private fun onBalance(balance: Wallet.WalletBalance) {
|
||||
binding.textBalances.text = """
|
||||
Available balance: ${balance.available.convertZatoshiToZecString()}
|
||||
Total balance: ${balance.total.convertZatoshiToZecString()}
|
||||
""".trimIndent()
|
||||
binding.buttonSend.isEnabled = balance.available > 0
|
||||
binding.textStatus.text = "Synced!"
|
||||
}
|
||||
|
||||
private fun onSend(unused: View) {
|
||||
// TODO: add input fields to the UI. Possibly, including a scanner for the address input
|
||||
lifecycleScope.launch {
|
||||
synchronizer.sendToAddress(0.001.toZec().convertZecToZatoshi(), "ztestsapling1fg82ar8y8whjfd52l0xcq0w3n7nn7cask2scp9rp27njeurr72ychvud57s9tu90fdqgwdt07lg", "Demo App Funds")
|
||||
}
|
||||
Toast.makeText(App.instance, "Sending funds...", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package cash.z.wallet.sdk.demoapp.util
|
||||
|
||||
import android.content.Context
|
||||
import cash.z.wallet.sdk.demoapp.App
|
||||
import cash.z.wallet.sdk.secure.Wallet
|
||||
|
||||
|
||||
@Deprecated(
|
||||
message = "Do not use this! It is insecure and only intended for demo purposes to " +
|
||||
"show how to bridge to an existing key storage mechanism. Instead, use the Android " +
|
||||
"Keystore system or a 3rd party library that leverages it."
|
||||
)
|
||||
class SampleStorage {
|
||||
|
||||
private val prefs =
|
||||
App.instance.getSharedPreferences("ExtremelyInsecureStorage", Context.MODE_PRIVATE)
|
||||
|
||||
fun saveSensitiveString(key: String, value: String) {
|
||||
prefs.edit().putString(key, value).apply()
|
||||
}
|
||||
|
||||
fun loadSensitiveString(key: String): String? = prefs.getString(key, null)
|
||||
|
||||
fun saveSensitiveBytes(key: String, value: ByteArray) {
|
||||
saveSensitiveString(key, value.toString(Charsets.ISO_8859_1))
|
||||
}
|
||||
|
||||
fun loadSensitiveBytes(key: String): ByteArray? =
|
||||
prefs.getString(key, null)?.toByteArray(Charsets.ISO_8859_1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple demonstration of how to take existing code that securely stores data and bridge it into
|
||||
* the KeyManager interface. This class implements the interface by delegating to the storage
|
||||
* object. For demo purposes, we're using an insecure SampleStorage implementation but this can
|
||||
* easily be swapped for a true storage solution.
|
||||
*/
|
||||
class SampleStorageBridge(): Wallet.KeyManager {
|
||||
private val KEY_SEED = "cash.z.wallet.sdk.demoapp.SEED"
|
||||
private val KEY_PK = "cash.z.wallet.sdk.demoapp.PK"
|
||||
private val delegate = SampleStorage()
|
||||
|
||||
constructor(seed: ByteArray) : this() {
|
||||
securelyStoreSeed(seed)
|
||||
}
|
||||
|
||||
fun securelyStoreSeed(seed: ByteArray): SampleStorageBridge {
|
||||
delegate.saveSensitiveBytes(KEY_SEED, seed)
|
||||
return this
|
||||
}
|
||||
|
||||
override val seed: ByteArray get() = delegate.loadSensitiveBytes(KEY_SEED)!!
|
||||
override var key: String
|
||||
get() = delegate.loadSensitiveString(KEY_PK)!!
|
||||
set(value) {
|
||||
delegate.saveSensitiveString(KEY_PK, value)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108"
|
||||
android:width="108dp">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z"/>
|
||||
</vector>
|
|
@ -0,0 +1,171 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108"
|
||||
android:width="108dp">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3,13h2v-2L3,11v2zM3,17h2v-2L3,15v2zM3,9h2L5,7L3,7v2zM7,13h14v-2L7,11v2zM7,17h14v-2L7,15v2zM7,7v2h14L21,7L7,7z"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3,11H5V13H3V11M11,5H13V9H11V5M9,11H13V15H11V13H9V11M15,11H17V13H19V11H21V13H19V15H21V19H19V21H17V19H13V21H11V17H15V15H17V13H15V11M19,19V15H17V19H19M15,3H21V9H15V3M17,5V7H19V5H17M3,3H9V9H3V3M5,5V7H7V5H5M3,15H9V21H3V15M5,17V19H7V17H5Z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M6,6h12v12H6z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M4,11h5L9,5L4,5v6zM4,18h5v-6L4,12v6zM10,18h5v-6h-5v6zM16,18h5v-6h-5v6zM10,11h5L15,5h-5v6zM16,5v6h5L21,5h-5z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M9.4,16.6L4.8,12l4.6,-4.6L8,6l-6,6 6,6 1.4,-1.4zM14.6,16.6l4.6,-4.6 -4.6,-4.6L16,6l6,6 -6,6 -1.4,-1.4z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7.77,6.76L6.23,5.48 0.82,12l5.41,6.52 1.54,-1.28L3.42,12l4.35,-5.24zM7,13h2v-2L7,11v2zM17,11h-2v2h2v-2zM11,13h2v-2h-2v2zM17.77,5.48l-1.54,1.28L20.58,12l-4.35,5.24 1.54,1.28L23.18,12l-5.41,-6.52z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19,8l-4,4h3c0,3.31 -2.69,6 -6,6 -1.01,0 -1.97,-0.25 -2.8,-0.7l-1.46,1.46C8.97,19.54 10.43,20 12,20c4.42,0 8,-3.58 8,-8h3l-4,-4zM6,12c0,-3.31 2.69,-6 6,-6 1.01,0 1.97,0.25 2.8,0.7l1.46,-1.46C15.03,4.46 13.57,4 12,4c-4.42,0 -8,3.58 -8,8H1l4,4 4,-4H6z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13,12h7v1.5h-7zM13,9.5h7L20,11h-7zM13,14.5h7L20,16h-7zM21,4L3,4c-1.1,0 -2,0.9 -2,2v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,6c0,-1.1 -0.9,-2 -2,-2zM21,19h-9L12,6h9v13z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12.65,10C11.83,7.67 9.61,6 7,6c-3.31,0 -6,2.69 -6,6s2.69,6 6,6c2.61,0 4.83,-1.67 5.65,-4H17v4h4v-4h2v-4H12.65zM7,14c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||
</vector>
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF66BB6A" android:pathData="M20,5.41L18.59,4 7,15.59V9H5v10h10v-2H8.41z"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FFEF5350" android:pathData="M9,5v2h6.59L4,18.59 5.41,20 17,8.41V15h2V5z"/>
|
||||
</vector>
|
|
@ -0,0 +1,10 @@
|
|||
<shape
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<gradient
|
||||
android:angle="135"
|
||||
android:centerColor="#009688"
|
||||
android:endColor="#00695C"
|
||||
android:startColor="#4DB6AC"
|
||||
android:type="linear" />
|
||||
</shape>
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.drawerlayout.widget.DrawerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:openDrawer="start">
|
||||
|
||||
<include
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
layout="@layout/app_bar_main" />
|
||||
|
||||
<com.google.android.material.navigation.NavigationView
|
||||
android:id="@+id/nav_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:fitsSystemWindows="true"
|
||||
app:headerLayout="@layout/nav_header_main"
|
||||
app:menu="@menu/activity_main_drawer" />
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="cash.z.wallet.sdk.demoapp.MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/AppTheme.AppBarOverlay">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
app:popupTheme="@style/AppTheme.PopupOverlay" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<include layout="@layout/content_main" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="@dimen/fab_margin"
|
||||
app:srcCompat="@drawable/ic_floating_action" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
tools:showIn="@layout/app_bar_main">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_host_fragment"
|
||||
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:defaultNavHost="true"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:navGraph="@navigation/mobile_navigation" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="cash.z.wallet.sdk.demoapp.demos.gallery.GalleryFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_gallery"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textSize="20sp"
|
||||
android:text="loading address..."
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_block_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_apply"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/text_block_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="8"
|
||||
android:hint="block height"
|
||||
android:inputType="number"
|
||||
android:text="500000"
|
||||
android:textSize="20sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_apply"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="apply"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_block_height"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/text_layout_block_height"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_block_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="loading block..."
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_block_height" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_start_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/text_layout_end_height"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/text_start_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="start height"
|
||||
android:inputType="number"
|
||||
android:maxLength="7"
|
||||
android:text="500000"
|
||||
android:textSize="20sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_end_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_apply"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/text_layout_start_height"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/text_end_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="end height"
|
||||
android:inputType="number"
|
||||
android:maxLength="7"
|
||||
android:text="500000"
|
||||
android:textSize="20sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_apply"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:text="apply"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_end_height"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/text_layout_end_height"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_end_height" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:text="loading blocks..."
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_end_height" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textSize="20sp"
|
||||
android:text="loading latest height..."
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textSize="20sp"
|
||||
android:text="loading keys soon..."
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="cash.z.wallet.sdk.demoapp.demos.home.HomeFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_home"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_home"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_home"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/next"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_home" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="cash.z.wallet.sdk.demoapp.demos.home.HomeSecondFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textview_home_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/button_home_second"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_home_second"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/previous"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/textview_home_second" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_start_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/text_layout_end_height"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2"/>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_end_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toEndOf="@id/text_layout_start_height"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
android:padding="8dp"
|
||||
android:text="Initializing..."
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_info"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="loading blocks..."
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_status"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_transactions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_info"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:itemCount="15"
|
||||
tools:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
tools:listitem="@layout/item_transaction"
|
||||
tools:orientation="vertical" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/text_layout_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/button_send"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.2">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/text_block_height"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="8"
|
||||
android:hint="amount"
|
||||
android:inputType="number"
|
||||
android:textSize="20sp" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_send"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:enabled="false"
|
||||
android:text="Send"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_layout_amount"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/text_layout_amount"
|
||||
app:layout_constraintTop_toTopOf="@id/text_layout_amount" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="Initializing wallet..."
|
||||
app:layout_constraintStart_toStartOf="@id/text_layout_amount"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_layout_amount" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_balances"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintStart_toStartOf="@id/text_status"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_status"
|
||||
android:text="Available balance: --\nTotal balance: --" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context="cash.z.wallet.sdk.demoapp.demos.slideshow.SlideshowFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_slideshow"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/container_transaction"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#F0F0F0"
|
||||
android:elevation="1dp"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingEnd="10dp"
|
||||
android:paddingStart="8dp"
|
||||
android:layout_marginTop="4dp"
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_transaction_type"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
app:srcCompat="@drawable/ic_receive"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_timestamp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintBottom_toTopOf="@id/text_transaction_address"
|
||||
app:layout_constraintStart_toEndOf="@id/image_transaction_type"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
tools:text="8/23 3:24pm" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="12sp"
|
||||
android:paddingEnd="16dp"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
app:layout_constraintEnd_toStartOf="@id/text_transaction_amount"
|
||||
app:layout_constraintStart_toStartOf="@id/text_transaction_timestamp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_transaction_timestamp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:text="funds received" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_transaction_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="+ 4.244"
|
||||
android:textColor="@color/colorPrimary"
|
||||
android:textSize="20sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -0,0 +1,37 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/nav_header_height"
|
||||
android:background="@drawable/side_nav_bar"
|
||||
android:gravity="bottom"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/nav_header_desc"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
app:srcCompat="@mipmap/ic_launcher_round" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/nav_header_vertical_spacing"
|
||||
android:text="@string/nav_header_title"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/nav_header_subtitle" />
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:showIn="navigation_view">
|
||||
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/nav_home"
|
||||
android:icon="@drawable/ic_menu_home"
|
||||
android:title="@string/menu_home" />
|
||||
<item
|
||||
android:id="@+id/nav_private_key"
|
||||
android:icon="@drawable/ic_menu_private_key"
|
||||
android:title="@string/menu_private_key" />
|
||||
<item
|
||||
android:id="@+id/nav_address"
|
||||
android:icon="@drawable/ic_menu_address"
|
||||
android:title="@string/menu_address" />
|
||||
<item
|
||||
android:id="@+id/nav_latest_height"
|
||||
android:icon="@drawable/ic_menu_latest_height"
|
||||
android:title="@string/menu_latest_height" />
|
||||
<item
|
||||
android:id="@+id/nav_block"
|
||||
android:icon="@drawable/ic_menu_block"
|
||||
android:title="@string/menu_block" />
|
||||
<item
|
||||
android:id="@+id/nav_block_range"
|
||||
android:icon="@drawable/ic_menu_block_range"
|
||||
android:title="@string/menu_block_range" />
|
||||
<item
|
||||
android:id="@+id/nav_transactions"
|
||||
android:icon="@drawable/ic_list"
|
||||
android:title="@string/menu_transactions" />
|
||||
<item
|
||||
android:id="@+id/nav_send"
|
||||
android:icon="@drawable/ic_menu_send"
|
||||
android:title="@string/menu_send" />
|
||||
</group>
|
||||
</menu>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<item
|
||||
android:id="@+id/action_settings"
|
||||
android:orderInCategory="100"
|
||||
android:title="@string/action_settings"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<adaptive-icon
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
|
@ -1,5 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||
<adaptive-icon
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 7.3 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 16 KiB |
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<navigation
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/mobile_navigation"
|
||||
app:startDestination="@+id/nav_home">
|
||||
|
||||
<fragment
|
||||
android:id="@+id/nav_home"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.home.HomeFragment"
|
||||
android:label="@string/menu_home"
|
||||
tools:layout="@layout/fragment_home">
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/nav_address"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.getaddress.GetAddressFragment"
|
||||
android:label="@string/menu_address"
|
||||
tools:layout="@layout/fragment_get_address" />
|
||||
<fragment
|
||||
android:id="@+id/nav_private_key"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.getprivatekey.GetPrivateKeyFragment"
|
||||
android:label="@string/menu_private_key"
|
||||
tools:layout="@layout/fragment_get_private_key" />
|
||||
<fragment
|
||||
android:id="@+id/nav_latest_height"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.getlatestheight.GetLatestHeightFragment"
|
||||
android:label="@string/menu_latest_height"
|
||||
tools:layout="@layout/fragment_get_latest_height" />
|
||||
<fragment
|
||||
android:id="@+id/nav_block"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.getblock.GetBlockFragment"
|
||||
android:label="@string/menu_block"
|
||||
tools:layout="@layout/fragment_get_block" />
|
||||
<fragment
|
||||
android:id="@+id/nav_block_range"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.getblockrange.GetBlockRangeFragment"
|
||||
android:label="@string/menu_block_range"
|
||||
tools:layout="@layout/fragment_get_block_range" />
|
||||
<fragment
|
||||
android:id="@+id/nav_transactions"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.listtransactions.ListTransactionsFragment"
|
||||
android:label="@string/menu_transactions"
|
||||
tools:layout="@layout/fragment_list_transactions" />
|
||||
<fragment
|
||||
android:id="@+id/nav_send"
|
||||
android:name="cash.z.wallet.sdk.demoapp.demos.send.SendFragment"
|
||||
android:label="@string/menu_send"
|
||||
tools:layout="@layout/fragment_send" />
|
||||
</navigation>
|
|
@ -0,0 +1,8 @@
|
|||
<resources>
|
||||
|
||||
<style name="AppTheme.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
</style>
|
||||
</resources>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#6200EE</color>
|
||||
<color name="colorPrimaryDark">#3700B3</color>
|
||||
<color name="colorAccent">#03DAC5</color>
|
||||
</resources>
|
|
@ -0,0 +1,8 @@
|
|||
<resources>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||
<dimen name="nav_header_height">176dp</dimen>
|
||||
<dimen name="fab_margin">16dp</dimen>
|
||||
</resources>
|
|
@ -0,0 +1,24 @@
|
|||
<resources>
|
||||
<string name="app_name">Demo App</string>
|
||||
<string name="navigation_drawer_open">Open navigation drawer</string>
|
||||
<string name="navigation_drawer_close">Close navigation drawer</string>
|
||||
<string name="nav_header_title">Android SDK Demo</string>
|
||||
<string name="nav_header_subtitle">v1.0.0-alpha02</string>
|
||||
<string name="nav_header_desc">Navigation header</string>
|
||||
<string name="action_settings">Settings</string>
|
||||
|
||||
<!-- Drawer Menu -->
|
||||
<string name="menu_home">Home</string>
|
||||
<string name="menu_private_key">Get Private Key</string>
|
||||
<string name="menu_address">Get Address</string>
|
||||
<string name="menu_latest_height">Get Latest Height</string>
|
||||
<string name="menu_block">Get Block</string>
|
||||
<string name="menu_block_range">Get Block Range</string>
|
||||
<string name="menu_decrypt">Decrypt Block</string>
|
||||
<string name="menu_transactions">List Transactions</string>
|
||||
<string name="menu_send">Send</string>
|
||||
|
||||
<string name="home_second">Home Second</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="previous">Previous</string>
|
||||
</resources>
|