Skip to content

Commit

Permalink
ระบบสร้าง Mnemonic Phrase เสร็จ
Browse files Browse the repository at this point in the history
  • Loading branch information
rushmi0 committed Mar 10, 2024
1 parent ede6998 commit f250829
Show file tree
Hide file tree
Showing 13 changed files with 173 additions and 332 deletions.
12 changes: 10 additions & 2 deletions app/src/main/java/win/notoshi/genesec/model/MnemonicModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,21 @@ class MnemonicModel @Inject constructor(val context: Context) : ViewModel() {

private val _SEED = MutableStateFlow(
BIP32Record(
""
null
)
)

val SEED: StateFlow<BIP32Record> = _SEED

fun mnemonicPhrase() : String {
private fun notifyMnemonicPhraseChanged() {
_SEED.value = BIP32Record(
newMnemonic()
)
}

fun mnemonicPhrase() = notifyMnemonicPhraseChanged()

private fun newMnemonic(): String {
return SecretWord(128).generateMnemonic()
}

Expand Down
9 changes: 4 additions & 5 deletions app/src/main/java/win/notoshi/genesec/model/NostrKeyModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import win.notoshi.genesec.securekey.ECKeyFactory
import win.notoshi.genesec.securekey.ECKeyProvider
import win.notoshi.genesec.securekey.ECKeyProvider.toXPoint
import win.notoshi.genesec.securekey.Secp256K1
import win.notoshi.genesec.utils.ShiftTo.bech32Encode
import win.notoshi.genesec.utils.ShiftTo.npub
import win.notoshi.genesec.utils.ShiftTo.nsec
import kotlin.random.Random
Expand All @@ -33,8 +32,8 @@ class NostrKeyModel @Inject constructor(val context: Context) : ViewModel() {

private val _NOSTR_KEY = MutableStateFlow(
NostrKeyRecord(
"",
"",
null,
null,
)
)

Expand All @@ -53,12 +52,12 @@ class NostrKeyModel @Inject constructor(val context: Context) : ViewModel() {
return Random.nextBytes(32).joinToString("") { "%02x".format(it) }
}

fun privateKey(): String {
private fun privateKey(): String {
priv = randomBytes()
return priv
}

fun publicKey(): String {
private fun publicKey(): String {
pub = priv.toXPoint()
return pub
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package win.notoshi.genesec.model.record

data class BIP32Record(
val seed: String
val seed: String?
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package win.notoshi.genesec.model.record

data class NostrKeyRecord(
val nsec: String,
val npub: String
val nsec: String?,
val npub: String?
)

Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class SecretWord @Inject constructor(private val Strength: Int) {
//val entropy = "10101010111110011011000111010000011111001000100010100100111100100110110001011001010100101011011011000111101010010101101111101101"
val byteArray: ByteArray = entropy.BinaryToByteArray()

println("Generated Binary: ${byteArray.ByteArrayToBinary()}")
println("Entropy Bytes [${byteArray.size}]: ${byteArray.contentToString()}")
//println("Generated Binary: ${byteArray.ByteArrayToBinary()}")
//println("Entropy Bytes [${byteArray.size}]: ${byteArray.contentToString()}")
return byteArray
}

Expand All @@ -43,11 +43,3 @@ class SecretWord @Inject constructor(private val Strength: Int) {
}

}


fun main() {
val generator = SecretWord(128)
val mnemonic = generator.generateMnemonic()
println("\nMnemonic Word [${mnemonic.split(" ").size}]")
println("> $mnemonic")
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,69 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import com.thekhaeng.pushdownanim.PushDownAnim
import kotlinx.coroutines.launch
import win.notoshi.genesec.R
import win.notoshi.genesec.databinding.FragmentMnemonicBinding
import win.notoshi.genesec.model.MnemonicModel
import win.notoshi.genesec.model.record.BIP32Record
import win.notoshi.genesec.viewmodel.AppViewModelFactory

class MnemonicFragment : Fragment(R.layout.fragment_mnemonic) {

private lateinit var binding: FragmentMnemonicBinding
private lateinit var viewModel: MnemonicModel

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val factory = AppViewModelFactory(requireActivity())
viewModel = ViewModelProvider(this, factory)[MnemonicModel::class.java]
binding = FragmentMnemonicBinding.inflate(layoutInflater)
toHomePage()
setupViews()
return binding.root
}

private fun setupViews() {
toHomePage()
newSeed()
observeNewSeed()
}

private fun toHomePage() {
binding.goHome.setOnClickListener {
setupPushDownAnim(binding.closeBTN)
binding.closeBTN.setOnClickListener {
findNavController().navigateUp()
}
}

private fun newSeed() {
setupPushDownAnim(binding.genBTN)
binding.genBTN.setOnClickListener {
viewModel.mnemonicPhrase()
}
}

private fun observeNewSeed() {
lifecycleScope.launch {
viewModel.SEED.collect { seed ->
updateBIP32Record(seed)
}
}
}

private fun updateBIP32Record(record: BIP32Record) {
binding.seedView.text = record.seed
}

private fun setupPushDownAnim(view: View) {
PushDownAnim.setPushDownAnimTo(view)
.setScale(PushDownAnim.MODE_SCALE, 0.70f)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,12 @@ class NostrFragment : Fragment(R.layout.fragment_nostr) {
}

private fun setupViews() {
toHomePage()
newKeyPair()
goHome()
observeNostrKeyPair()
}

private fun goHome() {
private fun toHomePage() {
setupPushDownAnim(binding.goHome)
binding.goHome.setOnClickListener {
findNavController().navigateUp()
Expand Down Expand Up @@ -75,32 +75,14 @@ class NostrFragment : Fragment(R.layout.fragment_nostr) {
}
}

private fun copyToClipboard(data: String?, label: String) {
try {
if (!data.isNullOrEmpty()) {
val clipboardManager =
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText(label, data)
clipboardManager.setPrimaryClip(clipData)

Toast.makeText(context, "$label copied to clipboard", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "No $label data available", Toast.LENGTH_SHORT).show()
}
Log.d("Clipboard [DEBUG] ", "Data: $data, Label: $label")
} catch (e: Exception) {
Log.e("Clipboard [ERROR] ", "Error copying to clipboard: ${e.message}")
}
}

private fun observeNostrKeyPair() {
lifecycleScope.launch {
viewModel.NOSTR_KEY.collect { keyData ->
Log.d("NostrFragment", "Nostr Key Pair Observed: $keyData")
updateNostrKeyRecord(keyData)

val nsec = keyData.nsec
val npub = keyData.npub
val nsec = keyData.nsec ?: ""
val npub = keyData.npub ?: ""

copyNsec(nsec)
copyNpub(npub)
Expand All @@ -111,6 +93,11 @@ class NostrFragment : Fragment(R.layout.fragment_nostr) {
}
}

private fun updateNostrKeyRecord(record: NostrKeyRecord) {
binding.nsecView.text = record.nsec?.shortenString()
binding.npubView.text = record.npub?.shortenString()
}

private fun qrcodeNsec(nsec: String?) {
setupPushDownAnim(binding.qrcodeNsec)
binding.qrcodeNsec.setOnClickListener {
Expand All @@ -135,6 +122,25 @@ class NostrFragment : Fragment(R.layout.fragment_nostr) {
}
}


private fun copyToClipboard(data: String?, label: String) {
try {
if (!data.isNullOrEmpty()) {
val clipboardManager =
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
val clipData = ClipData.newPlainText(label, data)
clipboardManager.setPrimaryClip(clipData)

Toast.makeText(context, "$label copied to clipboard", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(context, "No $label data available", Toast.LENGTH_SHORT).show()
}
Log.d("Clipboard [DEBUG] ", "Data: $data, Label: $label")
} catch (e: Exception) {
Log.e("Clipboard [ERROR] ", "Error copying to clipboard: ${e.message}")
}
}

private fun showQRDialog(data: String) {
qrDialogBinding = QrDialogBinding.inflate(layoutInflater)
val dialog = AlertDialog.Builder(requireContext()).apply {
Expand All @@ -152,11 +158,6 @@ class NostrFragment : Fragment(R.layout.fragment_nostr) {
dialog.show()
}

private fun updateNostrKeyRecord(record: NostrKeyRecord) {
binding.nsecView.text = record.nsec.shortenString()
binding.npubView.text = record.npub.shortenString()
}

private fun String.shortenString(): String {
val prefixLength = 10
val suffixLength = 10
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/ic_close.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="45dp" android:tint="#98A8F8" android:viewportHeight="24" android:viewportWidth="24" android:width="45dp">

<path android:fillColor="@android:color/white" android:pathData="M19,6.41L17.59,5 12,10.59 6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 12,13.41 17.59,19 19,17.59 13.41,12z"/>

</vector>
2 changes: 1 addition & 1 deletion app/src/main/res/drawable/qrcode_nostr_stroke.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<stroke
android:width="4dp"
android:width="3dp"
android:color="@color/lavender" />
<corners android:radius="20dp" />
</shape>
103 changes: 76 additions & 27 deletions app/src/main/res/layout/fragment_mnemonic.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,84 @@
<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=".viewmodel.fragments.MnemonicFragment">

<Button
android:id="@+id/goHome"
android:layout_width="150dp"
android:layout_height="63dp"
android:text="Home"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.505"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.562" />

<TextView
android:id="@+id/mnemonicText"
android:layout_width="203dp"
android:layout_height="59dp"
android:gravity="center"
android:text="Mnemonic Page"
android:textSize="24sp"
android:layout_width="350dp"
android:layout_gravity="center"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
android:layout_width="348dp"
android:layout_height="357dp"
app:cardCornerRadius="23dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.39" />
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qrcode_nostr_stroke">


<TextView
android:id="@+id/closeBTN"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginTop="16dp"
android:background="@drawable/ic_close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.915"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/textView2"
android:layout_width="62dp"
android:layout_height="54dp"
android:layout_marginTop="16dp"
android:background="@drawable/seed"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<ImageView
android:id="@+id/ImageView"
android:layout_width="293dp"
android:layout_height="206dp"
android:layout_marginTop="12dp"
android:background="@drawable/qrcode_nostr_stroke"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.509"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />

<TextView
android:id="@+id/seedView"
android:layout_width="269dp"
android:layout_height="172dp"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="@+id/ImageView"
app:layout_constraintEnd_toEndOf="@+id/ImageView"
app:layout_constraintHorizontal_bias="0.458"
app:layout_constraintStart_toStartOf="@+id/ImageView"
app:layout_constraintTop_toTopOf="@+id/ImageView"
app:layout_constraintVertical_bias="0.558" />

<Button
android:id="@+id/genBTN"
android:layout_width="153dp"
android:layout_height="52dp"
android:layout_marginBottom="8dp"
android:text="NEW SEED"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.502"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ImageView" />

</androidx.constraintlayout.widget.ConstraintLayout>


</androidx.cardview.widget.CardView>

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Loading

0 comments on commit f250829

Please sign in to comment.