Adds a Share option with NIP-19 nprofile icon on the User Profile screen

Moves to NProfile instead of NPub to cite users.
Adds Npub or NIP-05 to the QR Screen
This commit is contained in:
Vitor Pamplona
2024-06-21 11:59:58 -04:00
parent 35a9c07636
commit accad0c77a
10 changed files with 281 additions and 201 deletions
@@ -39,7 +39,9 @@ object Nip19Bech32 {
ADDRESS,
}
enum class TlvTypes(val id: Byte) {
enum class TlvTypes(
val id: Byte,
) {
SPECIAL(0),
RELAY(1),
AUTHOR(2),
@@ -53,33 +55,59 @@ object Nip19Bech32 {
)
@Immutable
data class ParseReturn(val entity: Entity, val additionalChars: String? = null)
data class ParseReturn(
val entity: Entity,
val additionalChars: String? = null,
)
interface Entity
@Immutable
data class NSec(val hex: String) : Entity
data class NSec(
val hex: String,
) : Entity
@Immutable
data class NPub(val hex: String) : Entity
data class NPub(
val hex: String,
) : Entity
@Immutable
data class Note(val hex: String) : Entity
data class Note(
val hex: String,
) : Entity
@Immutable
data class NProfile(val hex: String, val relay: List<String>) : Entity
data class NProfile(
val hex: String,
val relay: List<String>,
) : Entity
@Immutable
data class NEvent(val hex: String, val relay: List<String>, val author: String?, val kind: Int?) : Entity
data class NEvent(
val hex: String,
val relay: List<String>,
val author: String?,
val kind: Int?,
) : Entity
@Immutable
data class NAddress(val atag: String, val relay: List<String>, val author: String, val kind: Int) : Entity
data class NAddress(
val atag: String,
val relay: List<String>,
val author: String,
val kind: Int,
) : Entity
@Immutable
data class NRelay(val relay: List<String>) : Entity
data class NRelay(
val relay: List<String>,
) : Entity
@Immutable
data class NEmbed(val event: Event) : Entity
data class NEmbed(
val event: Event,
) : Entity
fun uriToRoute(uri: String?): ParseReturn? {
if (uri == null) return null
@@ -108,8 +136,8 @@ object Nip19Bech32 {
type: String,
key: String?,
additionalChars: String?,
): ParseReturn? {
return try {
): ParseReturn? =
try {
val bytes = (type + key).bechToBytes()
when (type.lowercase()) {
@@ -129,7 +157,6 @@ object Nip19Bech32 {
Log.w("NIP19 Parser", "Issue trying to Decode NIP19 $key: ${e.message}", e)
null
}
}
private fun nembed(bytes: ByteArray): NEmbed? {
if (bytes.isEmpty()) return null
@@ -205,21 +232,30 @@ object Nip19Bech32 {
author: String?,
kind: Int?,
relay: String?,
): String {
return TlvBuilder()
): String =
TlvBuilder()
.apply {
addHex(TlvTypes.SPECIAL, idHex)
addStringIfNotNull(TlvTypes.RELAY, relay)
addHexIfNotNull(TlvTypes.AUTHOR, author)
addIntIfNotNull(TlvTypes.KIND, kind)
}
.build()
}.build()
.toNEvent()
}
fun createNEmbed(event: Event): String {
return gzip(event.toJson()).toNEmbed()
}
fun createNProfile(
authorPubKeyHex: String,
relay: List<String>,
): String =
TlvBuilder()
.apply {
addHex(TlvTypes.SPECIAL, authorPubKeyHex)
relay.forEach {
addStringIfNotNull(TlvTypes.RELAY, it)
}
}.build()
.toNProfile()
fun createNEmbed(event: Event): String = gzip(event.toJson()).toNEmbed()
fun gzip(content: String): ByteArray {
val bos = ByteArrayOutputStream()
@@ -239,23 +275,24 @@ fun ByteArray.toNote() = Bech32.encodeBytes(hrp = "note", this, Bech32.Encoding.
fun ByteArray.toNEvent() = Bech32.encodeBytes(hrp = "nevent", this, Bech32.Encoding.Bech32)
fun ByteArray.toNProfile() = Bech32.encodeBytes(hrp = "nprofile", this, Bech32.Encoding.Bech32)
fun ByteArray.toNAddress() = Bech32.encodeBytes(hrp = "naddr", this, Bech32.Encoding.Bech32)
fun ByteArray.toLnUrl() = Bech32.encodeBytes(hrp = "lnurl", this, Bech32.Encoding.Bech32)
fun ByteArray.toNEmbed() = Bech32.encodeBytes(hrp = "nembed", this, Bech32.Encoding.Bech32)
fun decodePublicKey(key: String): ByteArray {
return when (val parsed = Nip19Bech32.uriToRoute(key)?.entity) {
fun decodePublicKey(key: String): ByteArray =
when (val parsed = Nip19Bech32.uriToRoute(key)?.entity) {
is Nip19Bech32.NSec -> KeyPair(privKey = key.bechToBytes()).pubKey
is Nip19Bech32.NPub -> parsed.hex.hexToByteArray()
is Nip19Bech32.NProfile -> parsed.hex.hexToByteArray()
else -> Hex.decode(key) // crashes on purpose
}
}
fun decodePrivateKeyAsHexOrNull(key: String): HexKey? {
return try {
fun decodePrivateKeyAsHexOrNull(key: String): HexKey? =
try {
when (val parsed = Nip19Bech32.uriToRoute(key)?.entity) {
is Nip19Bech32.NSec -> parsed.hex
is Nip19Bech32.NPub -> null
@@ -271,10 +308,9 @@ fun decodePrivateKeyAsHexOrNull(key: String): HexKey? {
if (e is CancellationException) throw e
null
}
}
fun decodePublicKeyAsHexOrNull(key: String): HexKey? {
return try {
fun decodePublicKeyAsHexOrNull(key: String): HexKey? =
try {
when (val parsed = Nip19Bech32.uriToRoute(key)?.entity) {
is Nip19Bech32.NSec -> KeyPair(privKey = key.bechToBytes()).pubKey.toHexKey()
is Nip19Bech32.NPub -> parsed.hex
@@ -290,10 +326,9 @@ fun decodePublicKeyAsHexOrNull(key: String): HexKey? {
if (e is CancellationException) throw e
null
}
}
fun decodeEventIdAsHexOrNull(key: String): HexKey? {
return try {
fun decodeEventIdAsHexOrNull(key: String): HexKey? =
try {
when (val parsed = Nip19Bech32.uriToRoute(key)?.entity) {
is Nip19Bech32.NSec -> null
is Nip19Bech32.NPub -> null
@@ -309,7 +344,6 @@ fun decodeEventIdAsHexOrNull(key: String): HexKey? {
if (e is CancellationException) throw e
null
}
}
fun TlvBuilder.addString(
type: Nip19Bech32.TlvTypes,