Rewrites NIP-55 to start offering better error handling.
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.core
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.EventManualSerializer
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
|
||||
@@ -58,6 +59,14 @@ open class Event(
|
||||
companion object {
|
||||
fun fromJson(json: String): Event = JsonMapper.fromJson(json)
|
||||
|
||||
fun fromJsonOrNull(json: String) =
|
||||
try {
|
||||
fromJson(json)
|
||||
} catch (e: Exception) {
|
||||
Log.e("Event", "Unable to parse event JSON: $json", e)
|
||||
null
|
||||
}
|
||||
|
||||
fun build(
|
||||
kind: Int,
|
||||
content: String = "",
|
||||
|
||||
@@ -35,9 +35,13 @@ import com.vitorpamplona.quartz.nip47WalletConnect.Request
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.RequestDeserializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.ResponseDeserializer
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.Permission
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.PermissionDeserializer
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.PermissionSerializer
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorDeserializer
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.RumorSerializer
|
||||
import kotlin.jvm.java
|
||||
|
||||
class JsonMapper {
|
||||
companion object Companion {
|
||||
@@ -60,7 +64,9 @@ class JsonMapper {
|
||||
.addSerializer(BunkerRequest::class.java, BunkerRequest.BunkerRequestSerializer())
|
||||
.addDeserializer(BunkerRequest::class.java, BunkerRequest.BunkerRequestDeserializer())
|
||||
.addSerializer(BunkerResponse::class.java, BunkerResponse.BunkerResponseSerializer())
|
||||
.addDeserializer(BunkerResponse::class.java, BunkerResponse.BunkerResponseDeserializer()),
|
||||
.addDeserializer(BunkerResponse::class.java, BunkerResponse.BunkerResponseDeserializer())
|
||||
.addDeserializer(Permission::class.java, PermissionDeserializer())
|
||||
.addSerializer(Permission::class.java, PermissionSerializer()),
|
||||
)
|
||||
|
||||
fun fromJson(json: String): Event = mapper.readValue(json, Event::class.java)
|
||||
|
||||
@@ -47,25 +47,25 @@ abstract class NostrSigner(
|
||||
)
|
||||
|
||||
abstract fun nip04Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
)
|
||||
|
||||
abstract fun nip04Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
)
|
||||
|
||||
abstract fun nip44Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
)
|
||||
|
||||
abstract fun nip44Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
)
|
||||
|
||||
+8
-8
@@ -45,35 +45,35 @@ class NostrSignerInternal(
|
||||
}
|
||||
|
||||
override fun nip04Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
signerSync.nip04Encrypt(decryptedContent, toPublicKey)?.let { onReady(it) }
|
||||
signerSync.nip04Encrypt(plaintext, toPublicKey)?.let { onReady(it) }
|
||||
}
|
||||
|
||||
override fun nip04Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
signerSync.nip04Decrypt(encryptedContent, fromPublicKey)?.let { onReady(it) }
|
||||
signerSync.nip04Decrypt(ciphertext, fromPublicKey)?.let { onReady(it) }
|
||||
}
|
||||
|
||||
override fun nip44Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
signerSync.nip44Encrypt(decryptedContent, toPublicKey)?.let { onReady(it) }
|
||||
signerSync.nip44Encrypt(plaintext, toPublicKey)?.let { onReady(it) }
|
||||
}
|
||||
|
||||
override fun nip44Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
signerSync.nip44Decrypt(encryptedContent, fromPublicKey)?.let { onReady(it) }
|
||||
signerSync.nip44Decrypt(ciphertext, fromPublicKey)?.let { onReady(it) }
|
||||
}
|
||||
|
||||
override fun decryptZapEvent(
|
||||
|
||||
-438
@@ -1,438 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.util.LruCache
|
||||
import androidx.core.net.toUri
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
|
||||
enum class SignerType {
|
||||
SIGN_EVENT,
|
||||
NIP04_ENCRYPT,
|
||||
NIP04_DECRYPT,
|
||||
NIP44_ENCRYPT,
|
||||
NIP44_DECRYPT,
|
||||
GET_PUBLIC_KEY,
|
||||
DECRYPT_ZAP_EVENT,
|
||||
DERIVE_KEY,
|
||||
}
|
||||
|
||||
class Permission(
|
||||
val type: String,
|
||||
val kind: Int? = null,
|
||||
) {
|
||||
fun toJson(): String = "{\"type\":\"${type}\",\"kind\":$kind}"
|
||||
}
|
||||
|
||||
class Result(
|
||||
@JsonProperty("package") val `package`: String?,
|
||||
@JsonProperty("signature") val signature: String?,
|
||||
@JsonProperty("result") val result: String?,
|
||||
@JsonProperty("id") val id: String?,
|
||||
) {
|
||||
companion object {
|
||||
val mapper: ObjectMapper =
|
||||
jacksonObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
.registerModule(
|
||||
SimpleModule().addDeserializer(Result::class.java, ResultDeserializer()),
|
||||
)
|
||||
|
||||
private class ResultDeserializer : StdDeserializer<Result>(Result::class.java) {
|
||||
override fun deserialize(
|
||||
jp: JsonParser,
|
||||
ctxt: DeserializationContext,
|
||||
): Result {
|
||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||
return Result(
|
||||
jsonObject.get("package").asText().intern(),
|
||||
jsonObject.get("signature")?.asText()?.intern(),
|
||||
jsonObject.get("result")?.asText()?.intern(),
|
||||
jsonObject.get("id").asText().intern(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun fromJson(json: String): Result = mapper.readValue(json, Result::class.java)
|
||||
|
||||
/**
|
||||
* Parses the json with a string of events to an Array of Event objects.
|
||||
*/
|
||||
fun fromJsonArray(json: String): Array<Result> = mapper.readValue(json)
|
||||
}
|
||||
}
|
||||
|
||||
class ExternalSignerLauncher(
|
||||
private val currentUserPubKeyHex: String,
|
||||
val signerPackageName: String,
|
||||
) {
|
||||
private val contentCache = LruCache<String, (String) -> Unit>(50)
|
||||
|
||||
private var signerAppLauncher: ((Intent) -> Unit)? = null
|
||||
private var contentResolver: (() -> ContentResolver)? = null
|
||||
|
||||
/** Call this function when the launcher becomes available on activity, fragment or compose */
|
||||
fun registerLauncher(
|
||||
launcher: ((Intent) -> Unit),
|
||||
contentResolver: (() -> ContentResolver),
|
||||
) {
|
||||
this.signerAppLauncher = launcher
|
||||
this.contentResolver = contentResolver
|
||||
}
|
||||
|
||||
/** Call this function when the activity is destroyed or is about to be replaced. */
|
||||
fun clearLauncherIf(launcher: ((Intent) -> Unit)) {
|
||||
if (signerAppLauncher == launcher) {
|
||||
this.signerAppLauncher = null
|
||||
this.contentResolver = null
|
||||
}
|
||||
}
|
||||
|
||||
fun newResult(data: Intent) {
|
||||
val results = data.getStringExtra("results")
|
||||
if (results != null) {
|
||||
val localResults: Array<Result> = Result.fromJsonArray(results)
|
||||
localResults.forEach {
|
||||
val signature = it.result ?: it.signature ?: ""
|
||||
val packageName = it.`package`?.let { "-$it" } ?: ""
|
||||
val id = it.id ?: ""
|
||||
if (id.isNotBlank()) {
|
||||
val result = if (packageName.isNotBlank()) "$signature$packageName" else signature
|
||||
val contentCache = contentCache.get(id)
|
||||
contentCache?.invoke(result)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val signature = data.getStringExtra("result") ?: data.getStringExtra("signature") ?: ""
|
||||
val packageName = data.getStringExtra("package")?.let { "-$it" } ?: ""
|
||||
val id = data.getStringExtra("id") ?: ""
|
||||
if (id.isNotBlank()) {
|
||||
val result = if (packageName.isNotBlank()) "$signature$packageName" else signature
|
||||
val contentCache = contentCache.get(id)
|
||||
contentCache?.invoke(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun openSignerApp(
|
||||
data: String,
|
||||
type: SignerType,
|
||||
pubKey: HexKey,
|
||||
id: String,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
signerAppLauncher?.let {
|
||||
openSignerApp(
|
||||
data,
|
||||
type,
|
||||
it,
|
||||
pubKey,
|
||||
id,
|
||||
onReady,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun defaultPermissions(): String {
|
||||
val permissions =
|
||||
listOf(
|
||||
Permission(
|
||||
"sign_event",
|
||||
22242,
|
||||
),
|
||||
Permission(
|
||||
"sign_event",
|
||||
31234,
|
||||
),
|
||||
Permission(
|
||||
"nip04_encrypt",
|
||||
),
|
||||
Permission(
|
||||
"nip04_decrypt",
|
||||
),
|
||||
Permission(
|
||||
"nip44_encrypt",
|
||||
),
|
||||
Permission(
|
||||
"nip44_decrypt",
|
||||
),
|
||||
Permission(
|
||||
"decrypt_zap_event",
|
||||
),
|
||||
)
|
||||
val jsonArray = StringBuilder("[")
|
||||
permissions.forEachIndexed { index, permission ->
|
||||
jsonArray.append(permission.toJson())
|
||||
if (index < permissions.size - 1) {
|
||||
jsonArray.append(",")
|
||||
}
|
||||
}
|
||||
jsonArray.append("]")
|
||||
|
||||
return jsonArray.toString()
|
||||
}
|
||||
|
||||
private fun openSignerApp(
|
||||
data: String,
|
||||
type: SignerType,
|
||||
intentLauncher: (Intent) -> Unit,
|
||||
pubKey: HexKey,
|
||||
id: String,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$data".toUri())
|
||||
val signerType =
|
||||
when (type) {
|
||||
SignerType.SIGN_EVENT -> "sign_event"
|
||||
SignerType.NIP04_ENCRYPT -> "nip04_encrypt"
|
||||
SignerType.NIP04_DECRYPT -> "nip04_decrypt"
|
||||
SignerType.NIP44_ENCRYPT -> "nip44_encrypt"
|
||||
SignerType.NIP44_DECRYPT -> "nip44_decrypt"
|
||||
SignerType.GET_PUBLIC_KEY -> "get_public_key"
|
||||
SignerType.DECRYPT_ZAP_EVENT -> "decrypt_zap_event"
|
||||
SignerType.DERIVE_KEY -> "derive_key"
|
||||
}
|
||||
intent.putExtra("type", signerType)
|
||||
intent.putExtra("pubKey", pubKey)
|
||||
intent.putExtra("id", id)
|
||||
if (type !== SignerType.GET_PUBLIC_KEY) {
|
||||
intent.putExtra("current_user", currentUserPubKeyHex)
|
||||
} else {
|
||||
intent.putExtra("permissions", defaultPermissions())
|
||||
}
|
||||
if (signerPackageName.isNotBlank()) {
|
||||
intent.`package` = signerPackageName
|
||||
}
|
||||
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
|
||||
contentCache.put(id, onReady)
|
||||
|
||||
intentLauncher(intent)
|
||||
}
|
||||
|
||||
fun openSigner(
|
||||
event: Event,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
getDataFromResolver(
|
||||
SignerType.SIGN_EVENT,
|
||||
arrayOf(event.toJson(), event.pubKey),
|
||||
).fold(
|
||||
onFailure = { },
|
||||
onSuccess = {
|
||||
if (it == null) {
|
||||
openSignerApp(
|
||||
event.toJson(),
|
||||
SignerType.SIGN_EVENT,
|
||||
"",
|
||||
event.id,
|
||||
onReady,
|
||||
)
|
||||
} else {
|
||||
onReady(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private fun getDataFromResolver(
|
||||
signerType: SignerType,
|
||||
data: Array<out String>,
|
||||
): kotlin.Result<String?> = getDataFromResolver(signerType, data, contentResolver)
|
||||
|
||||
private fun getDataFromResolver(
|
||||
signerType: SignerType,
|
||||
data: Array<out String>,
|
||||
contentResolver: (() -> ContentResolver)? = null,
|
||||
): kotlin.Result<String?> {
|
||||
val localData =
|
||||
if (signerType !== SignerType.GET_PUBLIC_KEY) {
|
||||
arrayOf(*data, currentUserPubKeyHex)
|
||||
} else {
|
||||
data
|
||||
}
|
||||
|
||||
try {
|
||||
contentResolver
|
||||
?.let { it() }
|
||||
?.query(
|
||||
"content://$signerPackageName.$signerType".toUri(),
|
||||
localData,
|
||||
"1",
|
||||
null,
|
||||
null,
|
||||
).use {
|
||||
if (it == null) {
|
||||
return kotlin.Result.success(null)
|
||||
}
|
||||
if (it.moveToFirst()) {
|
||||
if (it.getColumnIndex("rejected") > -1) {
|
||||
Log.d("getDataFromResolver", "Permission denied")
|
||||
return kotlin.Result.failure(Exception("Permission denied"))
|
||||
}
|
||||
var index = it.getColumnIndex("result")
|
||||
if (index < 0) {
|
||||
index = it.getColumnIndex("signature")
|
||||
}
|
||||
if (index < 0) {
|
||||
Log.d("getDataFromResolver", "column 'signature' not found")
|
||||
return kotlin.Result.success(null)
|
||||
}
|
||||
return kotlin.Result.success(it.getString(index))
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("ExternalSignerLauncher", "Failed to query the Signer app in the background", e)
|
||||
return kotlin.Result.success(null)
|
||||
}
|
||||
|
||||
return kotlin.Result.success(null)
|
||||
}
|
||||
|
||||
fun hashCodeFields(
|
||||
str1: String,
|
||||
onReady: (String) -> Unit,
|
||||
): Int {
|
||||
var result = str1.hashCode()
|
||||
result = 31 * result + onReady.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
fun hashCodeFields(
|
||||
str1: String,
|
||||
str2: String,
|
||||
onReady: (String) -> Unit,
|
||||
): Int {
|
||||
var result = str1.hashCode()
|
||||
result = 31 * result + str2.hashCode()
|
||||
result = 31 * result + onReady.hashCode()
|
||||
return result
|
||||
}
|
||||
|
||||
fun decrypt(
|
||||
encryptedContent: String,
|
||||
pubKey: HexKey,
|
||||
signerType: SignerType = SignerType.NIP04_DECRYPT,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
getDataFromResolver(signerType, arrayOf(encryptedContent, pubKey)).fold(
|
||||
onFailure = { },
|
||||
onSuccess = {
|
||||
if (it == null) {
|
||||
openSignerApp(
|
||||
encryptedContent,
|
||||
signerType,
|
||||
pubKey,
|
||||
hashCodeFields(encryptedContent, pubKey, onReady).toString(),
|
||||
onReady,
|
||||
)
|
||||
} else {
|
||||
onReady(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun encrypt(
|
||||
decryptedContent: String,
|
||||
pubKey: HexKey,
|
||||
signerType: SignerType = SignerType.NIP04_ENCRYPT,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
getDataFromResolver(signerType, arrayOf(decryptedContent, pubKey)).fold(
|
||||
onFailure = { },
|
||||
onSuccess = {
|
||||
if (it == null) {
|
||||
openSignerApp(
|
||||
decryptedContent,
|
||||
signerType,
|
||||
pubKey,
|
||||
hashCodeFields(decryptedContent, pubKey, onReady).toString(),
|
||||
onReady,
|
||||
)
|
||||
} else {
|
||||
onReady(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun decryptZapEvent(
|
||||
event: LnZapRequestEvent,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
getDataFromResolver(SignerType.DECRYPT_ZAP_EVENT, arrayOf(event.toJson(), event.pubKey)).fold(
|
||||
onFailure = { },
|
||||
onSuccess = {
|
||||
if (it == null) {
|
||||
openSignerApp(
|
||||
event.toJson(),
|
||||
SignerType.DECRYPT_ZAP_EVENT,
|
||||
event.pubKey,
|
||||
event.id,
|
||||
onReady,
|
||||
)
|
||||
} else {
|
||||
onReady(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fun deriveKey(
|
||||
nonce: HexKey,
|
||||
signerType: SignerType = SignerType.DERIVE_KEY,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
getDataFromResolver(signerType, arrayOf(nonce)).fold(
|
||||
onFailure = { },
|
||||
onSuccess = {
|
||||
if (it == null) {
|
||||
openSignerApp(
|
||||
nonce,
|
||||
signerType,
|
||||
"",
|
||||
hashCodeFields(nonce, onReady).toString(),
|
||||
onReady,
|
||||
)
|
||||
} else {
|
||||
onReady(it)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api
|
||||
|
||||
enum class CommandType(
|
||||
val code: String,
|
||||
) {
|
||||
SIGN_EVENT("sign_event"),
|
||||
NIP04_ENCRYPT("nip04_encrypt"),
|
||||
NIP04_DECRYPT("nip04_decrypt"),
|
||||
NIP44_ENCRYPT("nip44_encrypt"),
|
||||
NIP44_DECRYPT("nip44_decrypt"),
|
||||
GET_PUBLIC_KEY("get_public_key"),
|
||||
DECRYPT_ZAP_EVENT("decrypt_zap_event"),
|
||||
DERIVE_KEY("derive_key"),
|
||||
;
|
||||
|
||||
companion object Companion {
|
||||
fun parse(code: String): CommandType? =
|
||||
when (code) {
|
||||
SIGN_EVENT.code -> SIGN_EVENT
|
||||
NIP04_ENCRYPT.code -> NIP04_ENCRYPT
|
||||
NIP04_DECRYPT.code -> NIP04_DECRYPT
|
||||
NIP44_ENCRYPT.code -> NIP44_ENCRYPT
|
||||
NIP44_DECRYPT.code -> NIP44_DECRYPT
|
||||
GET_PUBLIC_KEY.code -> GET_PUBLIC_KEY
|
||||
DECRYPT_ZAP_EVENT.code -> DECRYPT_ZAP_EVENT
|
||||
DERIVE_KEY.code -> DERIVE_KEY
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
|
||||
interface RequestAddressed
|
||||
|
||||
sealed class SignerResult<T : IResult> {
|
||||
class Successful<T : IResult>(
|
||||
val result: T,
|
||||
) : SignerResult<T>(),
|
||||
RequestAddressed
|
||||
|
||||
class Rejected<T : IResult> :
|
||||
SignerResult<T>(),
|
||||
RequestAddressed
|
||||
|
||||
class ReceivedButCouldNotPerform<T : IResult>(
|
||||
message: String? = null,
|
||||
) : SignerResult<T>(),
|
||||
RequestAddressed
|
||||
|
||||
class ReceivedButCouldNotParseEventFromResult<T : IResult>(
|
||||
val eventJson: String,
|
||||
) : SignerResult<T>(),
|
||||
RequestAddressed
|
||||
|
||||
class ReceivedButCouldNotVerifyResultingEvent<T : IResult>(
|
||||
val invalidEvent: Event,
|
||||
) : SignerResult<T>(),
|
||||
RequestAddressed
|
||||
|
||||
class ErrorExceptionCallingContentResolver<T : IResult>(
|
||||
val e: Exception? = null,
|
||||
) : SignerResult<T>()
|
||||
|
||||
class RequiresManualApproval<T : IResult> : SignerResult<T>()
|
||||
}
|
||||
|
||||
interface IResult
|
||||
|
||||
data class PubKeyResult(
|
||||
val pubkey: HexKey,
|
||||
val packageName: String,
|
||||
) : IResult
|
||||
|
||||
data class SignResult(
|
||||
val event: Event,
|
||||
) : IResult
|
||||
|
||||
data class EncryptionResult(
|
||||
val ciphertext: String,
|
||||
) : IResult
|
||||
|
||||
data class DecryptionResult(
|
||||
val plaintext: String,
|
||||
) : IResult
|
||||
|
||||
data class ZapEventDecryptionResult(
|
||||
val privateEvent: LnZapPrivateEvent,
|
||||
) : IResult
|
||||
|
||||
data class DerivationResult(
|
||||
val newPrivKey: HexKey,
|
||||
) : IResult
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.verify
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.ZapEventDecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
import kotlin.text.isNullOrBlank
|
||||
|
||||
class DecryptZapQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
fun query(event: Event): SignerResult<ZapEventDecryptionResult> =
|
||||
contentResolver.query(
|
||||
"content://$packageName.${CommandType.DECRYPT_ZAP_EVENT}".toUri(),
|
||||
arrayOf(event.toJson(), event.pubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val decryptedEventAsJson = cursor.getStringByName("result")
|
||||
if (!decryptedEventAsJson.isNullOrBlank()) {
|
||||
if (decryptedEventAsJson.startsWith("{")) {
|
||||
val event = Event.fromJsonOrNull(decryptedEventAsJson) as? LnZapPrivateEvent
|
||||
if (event != null) {
|
||||
if (event.verify()) {
|
||||
SignerResult.Successful(ZapEventDecryptionResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotVerifyResultingEvent(event)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotParseEventFromResult(decryptedEventAsJson)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform(decryptedEventAsJson)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform(decryptedEventAsJson)
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DerivationResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class DeriveKeyQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.DERIVE_KEY}".toUri()
|
||||
|
||||
fun query(nonce: HexKey): SignerResult<DerivationResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(nonce, loggedInUser),
|
||||
) { cursor ->
|
||||
val newPrivateKey = cursor.getStringByName("result")
|
||||
if (!newPrivateKey.isNullOrBlank()) {
|
||||
SignerResult.Successful(DerivationResult(newPrivateKey))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class LoginQuery(
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
companion object {
|
||||
val LOGIN = arrayOf("login")
|
||||
}
|
||||
|
||||
val uri = "content://$packageName.${CommandType.GET_PUBLIC_KEY}".toUri()
|
||||
|
||||
fun query(): SignerResult<PubKeyResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
LOGIN,
|
||||
) { cursor ->
|
||||
val pubkeyHex = cursor.getStringByName("result")
|
||||
if (!pubkeyHex.isNullOrBlank()) {
|
||||
SignerResult.Successful(PubKeyResult(pubkeyHex, packageName))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class Nip04DecryptQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.NIP04_DECRYPT}".toUri()
|
||||
|
||||
fun query(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
): SignerResult<DecryptionResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(ciphertext, fromPubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val plaintext = cursor.getStringByName("result")
|
||||
if (!plaintext.isNullOrBlank()) {
|
||||
SignerResult.Successful(DecryptionResult(plaintext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class Nip04EncryptQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.NIP04_ENCRYPT}".toUri()
|
||||
|
||||
fun query(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
): SignerResult<EncryptionResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(plaintext, toPubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val ciphertext = cursor.getStringByName("result")
|
||||
if (!ciphertext.isNullOrBlank()) {
|
||||
SignerResult.Successful(EncryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class Nip44DecryptQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.NIP44_DECRYPT}".toUri()
|
||||
|
||||
fun query(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
): SignerResult<DecryptionResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(ciphertext, fromPubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val plaintext = cursor.getStringByName("result")
|
||||
if (!plaintext.isNullOrBlank()) {
|
||||
SignerResult.Successful(DecryptionResult(plaintext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class Nip44EncryptQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.NIP44_ENCRYPT}".toUri()
|
||||
|
||||
fun query(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
): SignerResult<EncryptionResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(plaintext, toPubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val ciphertext = cursor.getStringByName("result")
|
||||
if (!ciphertext.isNullOrBlank()) {
|
||||
SignerResult.Successful(EncryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries
|
||||
|
||||
import android.content.ContentResolver
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.EventFactory
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.verify
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.getStringByName
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils.query
|
||||
|
||||
class SignQuery(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
val contentResolver: ContentResolver,
|
||||
) {
|
||||
val uri = "content://$packageName.${CommandType.SIGN_EVENT}".toUri()
|
||||
|
||||
fun query(unsignedEvent: Event): SignerResult<SignResult> =
|
||||
contentResolver.query(
|
||||
uri,
|
||||
arrayOf(unsignedEvent.toJson(), unsignedEvent.pubKey, loggedInUser),
|
||||
) { cursor ->
|
||||
val eventJson = cursor.getStringByName("event")
|
||||
if (!eventJson.isNullOrBlank()) {
|
||||
if (eventJson.startsWith("{")) {
|
||||
val event = Event.fromJsonOrNull(eventJson)
|
||||
if (event != null) {
|
||||
if (event.verify()) {
|
||||
SignerResult.Successful(SignResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotVerifyResultingEvent(event)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotParseEventFromResult(eventJson)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotParseEventFromResult(eventJson)
|
||||
}
|
||||
} else {
|
||||
val signature = cursor.getStringByName("result")
|
||||
if (!signature.isNullOrBlank()) {
|
||||
val event =
|
||||
EventFactory.create(
|
||||
id = unsignedEvent.id,
|
||||
pubKey = unsignedEvent.pubKey,
|
||||
createdAt = unsignedEvent.createdAt,
|
||||
kind = unsignedEvent.kind,
|
||||
tags = unsignedEvent.tags,
|
||||
content = unsignedEvent.content,
|
||||
sig = signature,
|
||||
)
|
||||
if (event.verify()) {
|
||||
SignerResult.Successful(SignResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotVerifyResultingEvent(event)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils
|
||||
|
||||
import android.content.ContentResolver
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.IResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
fun <T : IResult> ContentResolver.query(
|
||||
uri: Uri,
|
||||
projection: Array<out String>,
|
||||
map: (cursor: Cursor) -> SignerResult<T>,
|
||||
): SignerResult<T> =
|
||||
try {
|
||||
query(
|
||||
uri,
|
||||
projection,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
).use {
|
||||
if (it != null && it.moveToFirst()) {
|
||||
if (it.getColumnIndex("rejected") > -1) {
|
||||
SignerResult.Rejected()
|
||||
} else {
|
||||
map(it)
|
||||
}
|
||||
} else {
|
||||
SignerResult.RequiresManualApproval()
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e("ExternalSignerLauncher", "Failed to query the Signer app in the background", e)
|
||||
SignerResult.ErrorExceptionCallingContentResolver(e)
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.background.utils
|
||||
|
||||
import android.database.Cursor
|
||||
|
||||
fun Cursor.getStringByName(name: String): String? {
|
||||
val index = getColumnIndex(name)
|
||||
return if (index >= 0) {
|
||||
val result = getString(index)
|
||||
result.ifBlank { null }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.collection.LruCache
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.utils.RandomInstance
|
||||
|
||||
class IntentRequestDatabase {
|
||||
private val awaitingRequests = LruCache<String, NewResultProcessor>(2000)
|
||||
private var appLauncher: ((Intent) -> Unit)? = null
|
||||
|
||||
/** Call this function when the launcher becomes available on activity, fragment or compose */
|
||||
fun registerForegroundLauncher(launcher: ((Intent) -> Unit)) {
|
||||
this.appLauncher = launcher
|
||||
}
|
||||
|
||||
/** Call this function when the activity is destroyed or is about to be replaced. */
|
||||
fun unregisterForegroundLauncher(launcher: ((Intent) -> Unit)) {
|
||||
if (this.appLauncher == launcher) {
|
||||
this.appLauncher = null
|
||||
}
|
||||
}
|
||||
|
||||
fun newResponse(data: Intent) {
|
||||
val callId = data.getStringExtra("id")
|
||||
if (callId != null) {
|
||||
awaitingRequests[callId]?.process(data)
|
||||
awaitingRequests.remove(callId)
|
||||
}
|
||||
}
|
||||
|
||||
fun launch(
|
||||
requestIntent: Intent,
|
||||
responseProcessor: NewResultProcessor,
|
||||
) {
|
||||
appLauncher?.let {
|
||||
val callId = RandomInstance.randomChars(32)
|
||||
awaitingRequests.put(callId, responseProcessor)
|
||||
|
||||
requestIntent.putExtra("id", callId)
|
||||
requestIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
it.invoke(requestIntent)
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
interface NewResultProcessor {
|
||||
fun process(intent: Intent)
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
|
||||
class DecryptZapRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
event: LnZapRequestEvent,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:${event.toJson()}".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.NIP44_DECRYPT.code)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class DeriveKeyRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
nonce: HexKey,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$nonce".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.DERIVE_KEY.code)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
|
||||
import com.vitorpamplona.quartz.nip42RelayAuth.RelayAuthEvent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.Permission
|
||||
|
||||
class LoginRequest {
|
||||
companion object {
|
||||
val DefaultPermissions =
|
||||
listOf(
|
||||
Permission(CommandType.SIGN_EVENT, RelayAuthEvent.KIND),
|
||||
Permission(CommandType.NIP04_ENCRYPT),
|
||||
Permission(CommandType.NIP04_DECRYPT),
|
||||
Permission(CommandType.NIP44_DECRYPT),
|
||||
Permission(CommandType.NIP44_DECRYPT),
|
||||
Permission(CommandType.DECRYPT_ZAP_EVENT),
|
||||
)
|
||||
|
||||
fun assemble(permissions: List<Permission> = DefaultPermissions): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:".toUri())
|
||||
intent.putExtra("type", CommandType.GET_PUBLIC_KEY.code)
|
||||
intent.putExtra("permissions", JsonMapper.mapper.writeValueAsString(permissions))
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class Nip04DecryptRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$ciphertext".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.NIP04_DECRYPT.code)
|
||||
intent.putExtra("pubKey", fromPubKey)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class Nip04EncryptRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$plaintext".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.NIP04_ENCRYPT.code)
|
||||
intent.putExtra("pubKey", toPubKey)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class Nip44DecryptRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$ciphertext".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.NIP44_DECRYPT.code)
|
||||
intent.putExtra("pubKey", fromPubKey)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class Nip44EncryptRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:$plaintext".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.NIP44_ENCRYPT.code)
|
||||
intent.putExtra("pubKey", toPubKey)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class SignRequest {
|
||||
companion object {
|
||||
fun assemble(
|
||||
event: Event,
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
): Intent {
|
||||
val intent = Intent(Intent.ACTION_VIEW, "nostrsigner:${event.toJson()}".toUri())
|
||||
intent.`package` = packageName
|
||||
intent.putExtra("type", CommandType.SIGN_EVENT.code)
|
||||
intent.putExtra("current_user", loggedInUser)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.ZapEventDecryptionResult
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
|
||||
class DecryptZapResponse {
|
||||
companion object {
|
||||
fun assemble(event: LnZapPrivateEvent): Intent {
|
||||
val intent = Intent()
|
||||
intent.putExtra("result", event.toJson())
|
||||
return intent
|
||||
}
|
||||
|
||||
fun parse(intent: Intent): SignerResult<ZapEventDecryptionResult> {
|
||||
val eventJson = intent.getStringExtra("result")
|
||||
return if (!eventJson.isNullOrBlank()) {
|
||||
if (eventJson.startsWith("{")) {
|
||||
val event = Event.fromJsonOrNull(eventJson) as? LnZapPrivateEvent
|
||||
if (event != null) {
|
||||
SignerResult.Successful(ZapEventDecryptionResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotParseEventFromResult(eventJson)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DerivationResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class DeriveKeyResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<DerivationResult> {
|
||||
val newPrivateKey = intent.getStringExtra("result")
|
||||
return if (newPrivateKey != null) {
|
||||
SignerResult.Successful(DerivationResult(newPrivateKey))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class LoginResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<PubKeyResult> {
|
||||
val pubkey = intent.getStringExtra("result")
|
||||
val packageName = intent.getStringExtra("package")
|
||||
|
||||
return if (pubkey != null && packageName != null) {
|
||||
SignerResult.Successful(
|
||||
PubKeyResult(
|
||||
pubkey = pubkey,
|
||||
packageName = packageName,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class Nip04DecryptResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<DecryptionResult> {
|
||||
val ciphertext = intent.getStringExtra("result")
|
||||
return if (ciphertext != null) {
|
||||
SignerResult.Successful(DecryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class Nip04EncryptResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<EncryptionResult> {
|
||||
val ciphertext = intent.getStringExtra("result")
|
||||
return if (ciphertext != null) {
|
||||
SignerResult.Successful(EncryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class Nip44DecryptResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<DecryptionResult> {
|
||||
val ciphertext = intent.getStringExtra("result")
|
||||
return if (ciphertext != null) {
|
||||
SignerResult.Successful(DecryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class Nip44EncryptResponse {
|
||||
companion object {
|
||||
fun parse(intent: Intent): SignerResult<EncryptionResult> {
|
||||
val ciphertext = intent.getStringExtra("result")
|
||||
return if (ciphertext != null) {
|
||||
SignerResult.Successful(EncryptionResult(ciphertext))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.EventFactory
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.verify
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
|
||||
class SignResponse {
|
||||
companion object {
|
||||
fun parse(
|
||||
intent: Intent,
|
||||
unsignedEvent: Event,
|
||||
): SignerResult<SignResult> {
|
||||
val eventJson = intent.getStringExtra("event")
|
||||
return if (eventJson != null) {
|
||||
if (eventJson.startsWith("{")) {
|
||||
val event = Event.fromJsonOrNull(eventJson)
|
||||
if (event != null) {
|
||||
if (event.verify()) {
|
||||
SignerResult.Successful(SignResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotVerifyResultingEvent(event)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotParseEventFromResult(eventJson)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform(eventJson)
|
||||
}
|
||||
} else {
|
||||
val signature = intent.getStringExtra("result")
|
||||
if (signature != null && signature.length == 128) {
|
||||
val event =
|
||||
EventFactory.create(
|
||||
id = unsignedEvent.id,
|
||||
pubKey = unsignedEvent.pubKey,
|
||||
createdAt = unsignedEvent.createdAt,
|
||||
kind = unsignedEvent.kind,
|
||||
tags = unsignedEvent.tags,
|
||||
content = unsignedEvent.content,
|
||||
sig = signature,
|
||||
)
|
||||
if (event.verify()) {
|
||||
SignerResult.Successful(SignResult(event))
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotVerifyResultingEvent(event)
|
||||
}
|
||||
} else {
|
||||
SignerResult.ReceivedButCouldNotPerform(signature)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.ZapEventDecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.DecryptZapResponse
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
|
||||
class DecryptZapResultProcessor(
|
||||
val onReady: (LnZapPrivateEvent) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = DecryptZapResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<ZapEventDecryptionResult>) {
|
||||
onReady(foregroundResult.result.privateEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DerivationResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.DeriveKeyResponse
|
||||
|
||||
class DeriveKeyResultProcessor(
|
||||
val onReady: (String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = DeriveKeyResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<DerivationResult>) {
|
||||
onReady(foregroundResult.result.newPrivKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.LoginResponse
|
||||
|
||||
class LoginResultProcessor(
|
||||
val onReady: (HexKey, String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = LoginResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<PubKeyResult>) {
|
||||
onReady(foregroundResult.result.pubkey, foregroundResult.result.packageName)
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.Nip04DecryptResponse
|
||||
|
||||
class Nip04DecryptResultProcessor(
|
||||
val onReady: (String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = Nip04DecryptResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<DecryptionResult>) {
|
||||
onReady(foregroundResult.result.plaintext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.Nip04EncryptResponse
|
||||
|
||||
class Nip04EncryptResultProcessor(
|
||||
val onReady: (String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = Nip04EncryptResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<EncryptionResult>) {
|
||||
onReady(foregroundResult.result.ciphertext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.Nip44DecryptResponse
|
||||
|
||||
class Nip44DecryptResultProcessor(
|
||||
val onReady: (String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = Nip44DecryptResponse.parse(intent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<DecryptionResult>) {
|
||||
onReady(foregroundResult.result.plaintext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.Nip44EncryptResponse
|
||||
|
||||
class Nip44EncryptResultProcessor(
|
||||
val onReady: (String) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = Nip44EncryptResponse.parse(intent)
|
||||
if (foregroundResult is SignerResult.Successful<EncryptionResult>) {
|
||||
onReady(foregroundResult.result.ciphertext)
|
||||
}
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.NewResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.SignResponse
|
||||
|
||||
class SignResultProcessor(
|
||||
val unsignedEvent: Event,
|
||||
val onReady: (Event) -> Unit,
|
||||
) : NewResultProcessor {
|
||||
override fun process(intent: Intent) {
|
||||
val foregroundResult = SignResponse.parse(intent, unsignedEvent)
|
||||
|
||||
if (foregroundResult is SignerResult.Successful<SignResult>) {
|
||||
onReady(foregroundResult.result.event)
|
||||
}
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.permission
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.jackson.JsonMapper
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class Permission(
|
||||
val type: CommandType?,
|
||||
val kind: Int? = null,
|
||||
) {
|
||||
fun toJson(): String = JsonMapper.mapper.writeValueAsString(this)
|
||||
|
||||
companion object {
|
||||
fun fromJson(json: String): Permission = JsonMapper.mapper.readValue(json, Permission::class.java)
|
||||
|
||||
fun fromJsonArray(json: String): Array<Permission> = JsonMapper.mapper.readValue(json, Array<Permission>::class.java)
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.permission
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.CommandType
|
||||
|
||||
class PermissionDeserializer : StdDeserializer<Permission>(Permission::class.java) {
|
||||
override fun deserialize(
|
||||
jp: JsonParser,
|
||||
ctxt: DeserializationContext,
|
||||
): Permission {
|
||||
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||
return Permission(
|
||||
type = CommandType.parse(jsonObject.get("type").asText()),
|
||||
kind = jsonObject.get("kind")?.asInt(),
|
||||
)
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.api.permission
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.databind.SerializerProvider
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||
|
||||
class PermissionSerializer : StdSerializer<Permission>(Permission::class.java) {
|
||||
override fun serialize(
|
||||
permission: Permission,
|
||||
gen: JsonGenerator,
|
||||
provider: SerializerProvider,
|
||||
) {
|
||||
gen.writeStartObject()
|
||||
permission.type.let { gen.writeStringField("type", it?.code) }
|
||||
if (permission.kind != null) {
|
||||
gen.writeNumberField("kind", permission.kind)
|
||||
} else {
|
||||
gen.writeNullField("kind")
|
||||
}
|
||||
gen.writeEndObject()
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client
|
||||
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.LoginRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.responses.LoginResponse
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.permission.Permission
|
||||
|
||||
object ExternalSignerLogin {
|
||||
fun createIntent(permissions: List<Permission> = LoginRequest.DefaultPermissions): Intent {
|
||||
val intent = LoginRequest.assemble(permissions)
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
return intent
|
||||
}
|
||||
|
||||
fun parseResult(data: Intent): SignerResult<PubKeyResult> = LoginResponse.parse(data)
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
interface IActivityLauncher {
|
||||
fun registerForegroundLauncher(launcher: ((Intent) -> Unit))
|
||||
|
||||
fun unregisterForegroundLauncher(launcher: ((Intent) -> Unit))
|
||||
|
||||
fun newResponse(data: Intent)
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import androidx.core.net.toUri
|
||||
|
||||
@SuppressLint("QueryPermissionsNeeded")
|
||||
fun isExternalSignerInstalled(context: Context): Boolean =
|
||||
context.packageManager
|
||||
.queryIntentActivities(
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_VIEW
|
||||
data = "nostrsigner:".toUri()
|
||||
},
|
||||
0,
|
||||
).isNotEmpty()
|
||||
+52
-72
@@ -18,23 +18,42 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client
|
||||
|
||||
import android.util.Log
|
||||
import com.vitorpamplona.quartz.EventFactory
|
||||
import android.content.ContentResolver
|
||||
import android.content.Intent
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.EventHasher
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSigner
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers.BackgroundRequestHandler
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers.ForegroundRequestHandler
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
|
||||
class NostrSignerExternal(
|
||||
pubKey: HexKey,
|
||||
val launcher: ExternalSignerLauncher,
|
||||
) : NostrSigner(pubKey) {
|
||||
packageName: String,
|
||||
contentResolver: ContentResolver,
|
||||
) : NostrSigner(pubKey),
|
||||
IActivityLauncher {
|
||||
override fun isWriteable(): Boolean = true
|
||||
|
||||
val backgroundQuery = BackgroundRequestHandler(pubKey, packageName, contentResolver)
|
||||
val foregroundQuery = ForegroundRequestHandler(pubKey, packageName)
|
||||
|
||||
override fun registerForegroundLauncher(launcher: ((Intent) -> Unit)) {
|
||||
this.foregroundQuery.launcher.registerForegroundLauncher(launcher)
|
||||
}
|
||||
|
||||
override fun unregisterForegroundLauncher(launcher: ((Intent) -> Unit)) {
|
||||
this.foregroundQuery.launcher.unregisterForegroundLauncher(launcher)
|
||||
}
|
||||
|
||||
override fun newResponse(data: Intent) {
|
||||
this.foregroundQuery.launcher.newResponse(data)
|
||||
}
|
||||
|
||||
override fun <T : Event> sign(
|
||||
createdAt: Long,
|
||||
kind: Int,
|
||||
@@ -42,7 +61,7 @@ class NostrSignerExternal(
|
||||
content: String,
|
||||
onReady: (T) -> Unit,
|
||||
) {
|
||||
val event =
|
||||
val unsignedEvent =
|
||||
Event(
|
||||
id = EventHasher.hashId(pubKey, createdAt, kind, tags, content),
|
||||
pubKey = pubKey,
|
||||
@@ -53,109 +72,70 @@ class NostrSignerExternal(
|
||||
sig = "",
|
||||
)
|
||||
|
||||
launcher.openSigner(event) { signature ->
|
||||
if (signature.startsWith("{")) {
|
||||
val localEvent = Event.fromJson(signature)
|
||||
(
|
||||
EventFactory.create(
|
||||
localEvent.id,
|
||||
localEvent.pubKey,
|
||||
localEvent.createdAt,
|
||||
localEvent.kind,
|
||||
localEvent.tags,
|
||||
localEvent.content,
|
||||
localEvent.sig,
|
||||
) as? T?
|
||||
)?.let { onReady(it) }
|
||||
} else {
|
||||
(
|
||||
EventFactory.create(
|
||||
event.id,
|
||||
event.pubKey,
|
||||
event.createdAt,
|
||||
event.kind,
|
||||
event.tags,
|
||||
event.content,
|
||||
signature.split("-")[0],
|
||||
) as? T?
|
||||
)?.let { onReady(it) }
|
||||
}
|
||||
val newOnReady: (Event) -> Unit = { result ->
|
||||
(result as? T)?.let(onReady)
|
||||
}
|
||||
|
||||
if (!backgroundQuery.sign(unsignedEvent, newOnReady)) {
|
||||
foregroundQuery.sign(unsignedEvent, newOnReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun nip04Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
launcher.encrypt(
|
||||
decryptedContent,
|
||||
toPublicKey,
|
||||
SignerType.NIP04_ENCRYPT,
|
||||
onReady,
|
||||
)
|
||||
if (!backgroundQuery.nip04Encrypt(plaintext, toPublicKey, onReady)) {
|
||||
foregroundQuery.nip04Encrypt(plaintext, toPublicKey, onReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun nip04Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
launcher.decrypt(
|
||||
encryptedContent,
|
||||
fromPublicKey,
|
||||
SignerType.NIP04_DECRYPT,
|
||||
onReady,
|
||||
)
|
||||
if (!backgroundQuery.nip04Decrypt(ciphertext, fromPublicKey, onReady)) {
|
||||
foregroundQuery.nip04Decrypt(ciphertext, fromPublicKey, onReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun nip44Encrypt(
|
||||
decryptedContent: String,
|
||||
plaintext: String,
|
||||
toPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
launcher.encrypt(
|
||||
decryptedContent,
|
||||
toPublicKey,
|
||||
SignerType.NIP44_ENCRYPT,
|
||||
onReady,
|
||||
)
|
||||
if (!backgroundQuery.nip44Encrypt(plaintext, toPublicKey, onReady)) {
|
||||
foregroundQuery.nip44Encrypt(plaintext, toPublicKey, onReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun nip44Decrypt(
|
||||
encryptedContent: String,
|
||||
ciphertext: String,
|
||||
fromPublicKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) {
|
||||
launcher.decrypt(
|
||||
encryptedContent,
|
||||
fromPublicKey,
|
||||
SignerType.NIP44_DECRYPT,
|
||||
onReady,
|
||||
)
|
||||
if (!backgroundQuery.nip44Decrypt(ciphertext, fromPublicKey, onReady)) {
|
||||
foregroundQuery.nip44Decrypt(ciphertext, fromPublicKey, onReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun deriveKey(
|
||||
nonce: HexKey,
|
||||
onReady: (HexKey) -> Unit,
|
||||
) {
|
||||
launcher.deriveKey(
|
||||
nonce,
|
||||
SignerType.DERIVE_KEY,
|
||||
onReady,
|
||||
)
|
||||
if (!backgroundQuery.deriveKey(nonce, onReady)) {
|
||||
foregroundQuery.deriveKey(nonce, onReady)
|
||||
}
|
||||
}
|
||||
|
||||
override fun decryptZapEvent(
|
||||
event: LnZapRequestEvent,
|
||||
onReady: (LnZapPrivateEvent) -> Unit,
|
||||
) {
|
||||
launcher.decryptZapEvent(event) { jsonEvent ->
|
||||
try {
|
||||
(Event.fromJson(jsonEvent) as? LnZapPrivateEvent)?.let { onReady(it) }
|
||||
} catch (e: Exception) {
|
||||
Log.e("NostrExternalSigner", "Unable to parse returned decrypted Zap: $jsonEvent")
|
||||
}
|
||||
if (!backgroundQuery.decryptZapEvent(event, onReady)) {
|
||||
foregroundQuery.decryptZapEvent(event, onReady)
|
||||
}
|
||||
}
|
||||
}
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers
|
||||
|
||||
import android.content.ContentResolver
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.DerivationResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.EncryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.PubKeyResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.RequestAddressed
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.SignerResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.ZapEventDecryptionResult
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.DecryptZapQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.DeriveKeyQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.LoginQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.Nip04DecryptQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.Nip04EncryptQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.Nip44DecryptQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.Nip44EncryptQuery
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.background.queries.SignQuery
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
|
||||
class BackgroundRequestHandler(
|
||||
loggedInUser: HexKey,
|
||||
packageName: String,
|
||||
contentResolver: ContentResolver,
|
||||
) {
|
||||
val login = LoginQuery(packageName, contentResolver)
|
||||
val sign = SignQuery(loggedInUser, packageName, contentResolver)
|
||||
val nip04Encrypt = Nip04EncryptQuery(loggedInUser, packageName, contentResolver)
|
||||
val nip04Decrypt = Nip04DecryptQuery(loggedInUser, packageName, contentResolver)
|
||||
val nip44Encrypt = Nip44EncryptQuery(loggedInUser, packageName, contentResolver)
|
||||
val nip44Decrypt = Nip44DecryptQuery(loggedInUser, packageName, contentResolver)
|
||||
val decryptZap = DecryptZapQuery(loggedInUser, packageName, contentResolver)
|
||||
val deriveKey = DeriveKeyQuery(loggedInUser, packageName, contentResolver)
|
||||
|
||||
fun login(onReady: (HexKey) -> Unit): Boolean {
|
||||
val backgroundResult = login.query()
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<PubKeyResult>) {
|
||||
onReady(backgroundResult.result.pubkey)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun sign(
|
||||
unsignedEvent: Event,
|
||||
onReady: (Event) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = sign.query(unsignedEvent)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<SignResult>) {
|
||||
onReady(backgroundResult.result.event)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun nip04Encrypt(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = nip04Encrypt.query(plaintext, toPubKey)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<EncryptionResult>) {
|
||||
onReady(backgroundResult.result.ciphertext)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun nip04Decrypt(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = nip04Decrypt.query(ciphertext, fromPubKey)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<DecryptionResult>) {
|
||||
onReady(backgroundResult.result.plaintext)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun nip44Encrypt(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = nip44Encrypt.query(plaintext, toPubKey)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<EncryptionResult>) {
|
||||
onReady(backgroundResult.result.ciphertext)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun nip44Decrypt(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = nip44Decrypt.query(ciphertext, fromPubKey)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<DecryptionResult>) {
|
||||
onReady(backgroundResult.result.plaintext)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun decryptZapEvent(
|
||||
event: LnZapRequestEvent,
|
||||
onReady: (LnZapPrivateEvent) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = decryptZap.query(event)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<ZapEventDecryptionResult>) {
|
||||
onReady(backgroundResult.result.privateEvent)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
|
||||
fun deriveKey(
|
||||
nonce: HexKey,
|
||||
onReady: (HexKey) -> Unit,
|
||||
): Boolean {
|
||||
val backgroundResult = deriveKey.query(nonce)
|
||||
|
||||
if (backgroundResult is SignerResult.Successful<DerivationResult>) {
|
||||
onReady(backgroundResult.result.newPrivKey)
|
||||
}
|
||||
|
||||
return backgroundResult is RequestAddressed
|
||||
}
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip55AndroidSigner.client.handlers
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.IntentRequestDatabase
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.DecryptZapRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.DeriveKeyRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.Nip04DecryptRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.Nip04EncryptRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.Nip44DecryptRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.Nip44EncryptRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.intents.requests.SignRequest
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.DecryptZapResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.DeriveKeyResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.Nip04DecryptResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.Nip04EncryptResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.Nip44DecryptResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.Nip44EncryptResultProcessor
|
||||
import com.vitorpamplona.quartz.nip55AndroidSigner.api.foreground.processors.SignResultProcessor
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapPrivateEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent
|
||||
|
||||
class ForegroundRequestHandler(
|
||||
val loggedInUser: HexKey,
|
||||
val packageName: String,
|
||||
) {
|
||||
val launcher = IntentRequestDatabase()
|
||||
|
||||
fun sign(
|
||||
unsignedEvent: Event,
|
||||
onReady: (Event) -> Unit,
|
||||
) = launcher.launch(
|
||||
SignRequest.assemble(unsignedEvent, loggedInUser, packageName),
|
||||
SignResultProcessor(unsignedEvent, onReady),
|
||||
)
|
||||
|
||||
fun nip04Encrypt(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) = launcher.launch(
|
||||
Nip04EncryptRequest.assemble(plaintext, toPubKey, loggedInUser, packageName),
|
||||
Nip04EncryptResultProcessor(onReady),
|
||||
)
|
||||
|
||||
fun nip04Decrypt(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) = launcher.launch(
|
||||
Nip04DecryptRequest.assemble(ciphertext, fromPubKey, loggedInUser, packageName),
|
||||
Nip04DecryptResultProcessor(onReady),
|
||||
)
|
||||
|
||||
fun nip44Encrypt(
|
||||
plaintext: String,
|
||||
toPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) = launcher.launch(
|
||||
Nip44EncryptRequest.assemble(plaintext, toPubKey, loggedInUser, packageName),
|
||||
Nip44EncryptResultProcessor(onReady),
|
||||
)
|
||||
|
||||
fun nip44Decrypt(
|
||||
ciphertext: String,
|
||||
fromPubKey: HexKey,
|
||||
onReady: (String) -> Unit,
|
||||
) = launcher.launch(
|
||||
Nip44DecryptRequest.assemble(ciphertext, fromPubKey, loggedInUser, packageName),
|
||||
Nip44DecryptResultProcessor(onReady),
|
||||
)
|
||||
|
||||
fun decryptZapEvent(
|
||||
event: LnZapRequestEvent,
|
||||
onReady: (LnZapPrivateEvent) -> Unit,
|
||||
) = launcher.launch(
|
||||
DecryptZapRequest.assemble(event, loggedInUser, packageName),
|
||||
DecryptZapResultProcessor(onReady),
|
||||
)
|
||||
|
||||
fun deriveKey(
|
||||
nonce: HexKey,
|
||||
onReady: (HexKey) -> Unit,
|
||||
) = launcher.launch(
|
||||
DeriveKeyRequest.assemble(nonce, loggedInUser, packageName),
|
||||
DeriveKeyResultProcessor(onReady),
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user