mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-06 19:33:01 +00:00
Merge pull request #389 from greenart7c3/claude/mnemonic-account-path-option-fnVSY
Add mnemonic account index support for BIP-39 key derivation
This commit is contained in:
@@ -74,7 +74,7 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
|
||||
tryLoginExistingAccount(route, npub)
|
||||
}
|
||||
|
||||
fun isValidKey(key: String, password: String): Pair<KeyPair?, String> {
|
||||
fun isValidKey(key: String, password: String, accountIndex: Long = 0): Pair<KeyPair?, String> {
|
||||
try {
|
||||
val signer =
|
||||
if (key.startsWith("ncryptsec")) {
|
||||
@@ -83,7 +83,7 @@ class AccountStateViewModel(npub: String?) : ViewModel() {
|
||||
} else if (key.startsWith("nsec")) {
|
||||
NostrSignerInternal(KeyPair(privKey = key.bechToBytes()))
|
||||
} else if (key.contains(" ") && Nip06().isValidMnemonic(key)) {
|
||||
val keyPair = KeyPair(privKey = Nip06().privateKeyFromMnemonic(key))
|
||||
val keyPair = KeyPair(privKey = Nip06().privateKeyFromMnemonic(key, accountIndex))
|
||||
NostrSignerInternal(keyPair)
|
||||
} else {
|
||||
NostrSignerInternal(KeyPair(Hex.decode(key)))
|
||||
|
||||
@@ -833,6 +833,7 @@ fun LoginPage(
|
||||
var isMnemonicMode by rememberSaveable { mutableStateOf(false) }
|
||||
var mnemonicWordCount by rememberSaveable { mutableIntStateOf(12) }
|
||||
var mnemonicWords by remember { mutableStateOf(List(12) { "" }) }
|
||||
var mnemonicAccountIndex by rememberSaveable { mutableIntStateOf(0) }
|
||||
val clipboardManager = LocalClipboard.current
|
||||
|
||||
Scaffold(
|
||||
@@ -957,6 +958,28 @@ fun LoginPage(
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
OutlinedTextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
shape = RoundedCornerShape(18.dp),
|
||||
value = if (mnemonicAccountIndex == 0) "" else mnemonicAccountIndex.toString(),
|
||||
onValueChange = { value ->
|
||||
mnemonicAccountIndex = value.filter { it.isDigit() }.toIntOrNull() ?: 0
|
||||
if (errorMessage.isNotEmpty()) errorMessage = ""
|
||||
},
|
||||
label = { Text(stringResource(R.string.mnemonic_account_index)) },
|
||||
placeholder = { Text("0") },
|
||||
supportingText = {
|
||||
Text(stringResource(R.string.mnemonic_account_index_description, mnemonicAccountIndex))
|
||||
},
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Number,
|
||||
imeAction = ImeAction.Done,
|
||||
),
|
||||
singleLine = true,
|
||||
)
|
||||
} else {
|
||||
Text(
|
||||
stringResource(R.string.setup_amber_with_your_nostr_private_key_you_can_enter_different_versions_nsec_ncryptsec_or_hex_you_can_also_scan_it_from_a_qr_code),
|
||||
@@ -1161,7 +1184,7 @@ fun LoginPage(
|
||||
Amber.instance.applicationIOScope.launch {
|
||||
isLoading = true
|
||||
try {
|
||||
val isValid = accountViewModel.isValidKey(mnemonicStr, "")
|
||||
val isValid = accountViewModel.isValidKey(mnemonicStr, "", mnemonicAccountIndex.toLong())
|
||||
isLoading = false
|
||||
if (isValid.first != null) {
|
||||
keyPair = isValid.first!!
|
||||
|
||||
@@ -149,10 +149,12 @@ private fun WordField(
|
||||
nextFocusRequester: FocusRequester?,
|
||||
imeAction: ImeAction,
|
||||
) {
|
||||
// Tracks the last word that was chosen from the dropdown so we can suppress
|
||||
// the menu after selection (selecting changes `word`, which would otherwise
|
||||
// re-open the menu immediately).
|
||||
var selectedWord by remember { mutableStateOf("") }
|
||||
// `remember(word)` resets this state synchronously whenever `word` changes.
|
||||
// Initialising to `word` when it is already a complete BIP-39 entry
|
||||
// suppresses the dropdown immediately — no async gap — covering both the
|
||||
// paste case (word set externally, onValueChange never called) and the
|
||||
// case where the user finishes typing a valid word.
|
||||
var selectedWord by remember(word) { mutableStateOf(if (word in wordList) word else "") }
|
||||
|
||||
val suggestions = remember(word) {
|
||||
if (word.length >= 2) {
|
||||
|
||||
@@ -385,6 +385,8 @@
|
||||
<string name="mnemonic_12_words">12 words</string>
|
||||
<string name="mnemonic_24_words">24 words</string>
|
||||
<string name="mnemonic_words_entered">%1$d of %2$d words entered</string>
|
||||
<string name="mnemonic_account_index">Account index</string>
|
||||
<string name="mnemonic_account_index_description">Use a different index if this mnemonic was used to create multiple accounts (m/44\'/1237\'/%1$d\'/0/0)</string>
|
||||
<string name="sign_policy">Sign policy</string>
|
||||
<string name="handle_application_permissions">How to handle this application permissions?</string>
|
||||
<string name="sign_policy_manual_new_app">Manually approve each permission</string>
|
||||
|
||||
Reference in New Issue
Block a user