mirror of
https://github.com/greenart7c3/Amber.git
synced 2026-10-06 11:28:22 +00:00
add support for sign messages
This commit is contained in:
@@ -2,6 +2,7 @@ package com.greenart7c3.nostrsigner.models
|
||||
|
||||
enum class SignerType {
|
||||
CONNECT,
|
||||
SIGN,
|
||||
SIGN_EVENT,
|
||||
NIP04_ENCRYPT,
|
||||
NIP04_DECRYPT,
|
||||
|
||||
@@ -77,6 +77,7 @@ object IntentUtils {
|
||||
if (parameter == "type") {
|
||||
type =
|
||||
when (parameterData) {
|
||||
"sign" -> SignerType.SIGN
|
||||
"sign_event" -> SignerType.SIGN_EVENT
|
||||
"get_public_key" -> SignerType.GET_PUBLIC_KEY
|
||||
"nip04_encrypt" -> SignerType.NIP04_ENCRYPT
|
||||
@@ -197,6 +198,28 @@ object IntentUtils {
|
||||
),
|
||||
)
|
||||
}
|
||||
SignerType.SIGN -> {
|
||||
onReady(
|
||||
IntentData(
|
||||
localData,
|
||||
"",
|
||||
type,
|
||||
pubKey,
|
||||
"",
|
||||
callbackUrl,
|
||||
compressionType,
|
||||
returnType,
|
||||
listOf(),
|
||||
"",
|
||||
mutableStateOf(true),
|
||||
mutableStateOf(false),
|
||||
null,
|
||||
route,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
)
|
||||
}
|
||||
else -> onReady(null)
|
||||
}
|
||||
}
|
||||
@@ -204,6 +227,7 @@ object IntentUtils {
|
||||
|
||||
fun getTypeFromBunker(bunkerRequest: BunkerRequest): SignerType {
|
||||
return when (bunkerRequest.method) {
|
||||
"sign" -> SignerType.SIGN
|
||||
"connect" -> SignerType.CONNECT
|
||||
"sign_event" -> SignerType.SIGN_EVENT
|
||||
"get_public_key" -> SignerType.GET_PUBLIC_KEY
|
||||
@@ -217,6 +241,7 @@ object IntentUtils {
|
||||
|
||||
fun getDataFromBunker(bunkerRequest: BunkerRequest): String {
|
||||
return when (bunkerRequest.method) {
|
||||
"sign" -> bunkerRequest.params.first()
|
||||
"connect" -> "ack"
|
||||
"sign_event" -> {
|
||||
val amberEvent = AmberEvent.fromJson(bunkerRequest.params.first())
|
||||
@@ -425,6 +450,28 @@ object IntentUtils {
|
||||
),
|
||||
)
|
||||
}
|
||||
SignerType.SIGN -> {
|
||||
onReady(
|
||||
IntentData(
|
||||
data,
|
||||
"",
|
||||
type,
|
||||
pubKey,
|
||||
id,
|
||||
intent.extras?.getString("callbackUrl"),
|
||||
CompressionType.NONE,
|
||||
ReturnType.EVENT,
|
||||
permissions,
|
||||
bunkerRequest.currentAccount,
|
||||
mutableStateOf(true),
|
||||
mutableStateOf(false),
|
||||
bunkerRequest,
|
||||
route,
|
||||
null,
|
||||
null,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,6 +484,7 @@ object IntentUtils {
|
||||
) {
|
||||
val type =
|
||||
when (intent.extras?.getString("type")) {
|
||||
"sign" -> SignerType.SIGN
|
||||
"sign_event" -> SignerType.SIGN_EVENT
|
||||
"nip04_encrypt" -> SignerType.NIP04_ENCRYPT
|
||||
"nip04_decrypt" -> SignerType.NIP04_DECRYPT
|
||||
|
||||
@@ -1,4 +1,133 @@
|
||||
package com.greenart7c3.nostrsigner.ui.components
|
||||
|
||||
class SignMessage {
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalClipboardManager
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.AnnotatedString
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.greenart7c3.nostrsigner.R
|
||||
import com.greenart7c3.nostrsigner.models.SignerType
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun SignMessage(
|
||||
content: String,
|
||||
shouldRunOnAccept: Boolean,
|
||||
remember: MutableState<Boolean>,
|
||||
packageName: String?,
|
||||
applicationName: String?,
|
||||
appName: String,
|
||||
type: SignerType,
|
||||
onAccept: () -> Unit,
|
||||
onReject: () -> Unit,
|
||||
) {
|
||||
var showMore by androidx.compose.runtime.remember {
|
||||
mutableStateOf(false)
|
||||
}
|
||||
val clipboardManager = LocalClipboardManager.current
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val context = LocalContext.current
|
||||
|
||||
Column(
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.padding(8.dp),
|
||||
) {
|
||||
val message = stringResource(R.string.sign_message)
|
||||
Text(
|
||||
buildAnnotatedString {
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(applicationName ?: appName)
|
||||
}
|
||||
append(" requests $message")
|
||||
},
|
||||
fontSize = 18.sp,
|
||||
)
|
||||
Spacer(Modifier.size(4.dp))
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
) {
|
||||
Column(Modifier.padding(6.dp)) {
|
||||
Text(
|
||||
"Event content",
|
||||
fontWeight = FontWeight.Bold,
|
||||
)
|
||||
|
||||
Text(
|
||||
content,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(top = 8.dp),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
RawJsonButton(
|
||||
onCLick = {
|
||||
showMore = !showMore
|
||||
},
|
||||
if (!showMore) stringResource(R.string.show_details) else stringResource(R.string.hide_details),
|
||||
)
|
||||
if (showMore) {
|
||||
RawJson(
|
||||
content,
|
||||
"",
|
||||
Modifier.weight(1f),
|
||||
stringResource(R.string.content),
|
||||
type,
|
||||
) {
|
||||
clipboardManager.setText(AnnotatedString(content))
|
||||
|
||||
coroutineScope.launch {
|
||||
Toast.makeText(
|
||||
context,
|
||||
context.getString(R.string.data_copied_to_the_clipboard),
|
||||
Toast.LENGTH_SHORT,
|
||||
).show()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
|
||||
RememberMyChoice(
|
||||
shouldRunOnAccept,
|
||||
remember.value,
|
||||
packageName,
|
||||
onAccept,
|
||||
) {
|
||||
remember.value = !remember.value
|
||||
}
|
||||
|
||||
AcceptRejectButtons(
|
||||
onAccept,
|
||||
onReject,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.greenart7c3.nostrsigner.service.AmberUtils
|
||||
import com.greenart7c3.nostrsigner.service.getAppCompatActivity
|
||||
import com.greenart7c3.nostrsigner.service.toShortenHex
|
||||
import com.greenart7c3.nostrsigner.ui.sendResult
|
||||
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||
import com.vitorpamplona.quartz.encoders.bechToBytes
|
||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||
import com.vitorpamplona.quartz.encoders.toNpub
|
||||
@@ -190,6 +191,119 @@ fun SingleEventHomeScreen(
|
||||
)
|
||||
}
|
||||
|
||||
SignerType.SIGN -> {
|
||||
val permission =
|
||||
applicationEntity?.permissions?.firstOrNull {
|
||||
it.pkKey == key && it.type == intentData.type.toString()
|
||||
}
|
||||
val remember =
|
||||
remember {
|
||||
mutableStateOf(permission?.acceptable == true)
|
||||
}
|
||||
|
||||
val shouldRunOnAccept = permission?.acceptable == true
|
||||
val localPackageName =
|
||||
if (intentData.bunkerRequest != null) {
|
||||
intentData.bunkerRequest.localKey
|
||||
} else {
|
||||
packageName
|
||||
}
|
||||
SignMessage(
|
||||
intentData.data,
|
||||
shouldRunOnAccept,
|
||||
remember,
|
||||
localPackageName,
|
||||
applicationName,
|
||||
appName,
|
||||
intentData.type,
|
||||
{
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
val result = CryptoUtils.signString(intentData.data, account.keyPair.privKey!!).toHexKey()
|
||||
|
||||
sendResult(
|
||||
context,
|
||||
packageName,
|
||||
account,
|
||||
key,
|
||||
remember.value,
|
||||
clipboardManager,
|
||||
result,
|
||||
result,
|
||||
intentData,
|
||||
null,
|
||||
database,
|
||||
onLoading,
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
if (key == "null") {
|
||||
return@launch
|
||||
}
|
||||
|
||||
if (remember.value) {
|
||||
AmberUtils.acceptOrRejectPermission(
|
||||
key,
|
||||
intentData,
|
||||
null,
|
||||
false,
|
||||
applicationName ?: appName,
|
||||
account,
|
||||
database,
|
||||
)
|
||||
}
|
||||
|
||||
val savedApplication = database.applicationDao().getByKey(key)
|
||||
val relays = intentData.bunkerRequest?.relays ?: listOf()
|
||||
val application =
|
||||
savedApplication ?: ApplicationWithPermissions(
|
||||
application = ApplicationEntity(
|
||||
key,
|
||||
appName,
|
||||
relays,
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
account.keyPair.pubKey.toHexKey(),
|
||||
true,
|
||||
intentData.bunkerRequest?.secret ?: "",
|
||||
intentData.bunkerRequest?.secret != null,
|
||||
),
|
||||
permissions = mutableListOf(),
|
||||
)
|
||||
|
||||
database.applicationDao().insertApplicationWithPermissions(application)
|
||||
|
||||
database.applicationDao().addHistory(
|
||||
HistoryEntity(
|
||||
0,
|
||||
key,
|
||||
intentData.type.toString(),
|
||||
null,
|
||||
TimeUtils.now(),
|
||||
false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
if (intentData.bunkerRequest != null) {
|
||||
AmberUtils.sendBunkerError(
|
||||
account,
|
||||
intentData.bunkerRequest,
|
||||
applicationEntity?.application?.relays?.map { url -> Relay(url) }
|
||||
?: emptyList(),
|
||||
context,
|
||||
onLoading,
|
||||
)
|
||||
} else {
|
||||
context.getAppCompatActivity()?.intent = null
|
||||
context.getAppCompatActivity()?.finish()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
SignerType.NIP04_DECRYPT, SignerType.NIP04_ENCRYPT, SignerType.NIP44_ENCRYPT, SignerType.NIP44_DECRYPT, SignerType.DECRYPT_ZAP_EVENT -> {
|
||||
val permission =
|
||||
applicationEntity?.permissions?.firstOrNull {
|
||||
|
||||
@@ -224,4 +224,7 @@
|
||||
<string name="wants_you_to_sign_a">wants you to sign a %1$s</string>
|
||||
<string name="wants_you_to">wants you to %1$s</string>
|
||||
<string name="sign">Sign %1$s</string>
|
||||
<string name="sign_message">sign message</string>
|
||||
<string name="content">content</string>
|
||||
<string name="signature">signature</string>
|
||||
</resources>
|
||||
|
||||
@@ -17,7 +17,7 @@ lifecycle_version = "2.7.0"
|
||||
material3 = "1.2.1"
|
||||
mockk = "1.13.10"
|
||||
nav_version = "2.7.7"
|
||||
quartz = "0.86.5"
|
||||
quartz = "main-SNAPSHOT"
|
||||
compose_ui = "1.6.7"
|
||||
richtextUi = "077a2cde64"
|
||||
roomKtx = "2.6.1"
|
||||
|
||||
Reference in New Issue
Block a user