diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ATag.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ATag.kt index 8ad632241..27a39b4d8 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/model/ATag.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/model/ATag.kt @@ -3,9 +3,7 @@ package com.vitorpamplona.amethyst.service.model import android.util.Log import com.vitorpamplona.amethyst.model.toByteArray import com.vitorpamplona.amethyst.model.toHexKey -import com.vitorpamplona.amethyst.service.nip19.TlvTypes -import com.vitorpamplona.amethyst.service.nip19.parseTLV -import com.vitorpamplona.amethyst.service.nip19.toInt32 +import com.vitorpamplona.amethyst.service.nip19.Tlv import fr.acinq.secp256k1.Hex import nostr.postr.Bech32 import nostr.postr.bechToBytes @@ -20,15 +18,15 @@ data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val rela val dTag = dTag.toByteArray(Charsets.UTF_8) val relay = relay?.toByteArray(Charsets.UTF_8) - var fullArray = byteArrayOf(TlvTypes.SPECIAL.id, dTag.size.toByte()) + dTag + var fullArray = byteArrayOf(Tlv.Type.SPECIAL.id, dTag.size.toByte()) + dTag if (relay != null) { - fullArray = fullArray + byteArrayOf(TlvTypes.RELAY.id, relay.size.toByte()) + relay + fullArray = fullArray + byteArrayOf(Tlv.Type.RELAY.id, relay.size.toByte()) + relay } fullArray = fullArray + - byteArrayOf(TlvTypes.AUTHOR.id, author.size.toByte()) + author + - byteArrayOf(TlvTypes.KIND.id, kind.size.toByte()) + kind + byteArrayOf(Tlv.Type.AUTHOR.id, author.size.toByte()) + author + + byteArrayOf(Tlv.Type.KIND.id, kind.size.toByte()) + kind return Bech32.encodeBytes(hrp = "naddr", fullArray, Bech32.Encoding.Bech32) } @@ -62,11 +60,11 @@ data class ATag(val kind: Int, val pubKeyHex: String, val dTag: String, val rela val key = naddr.removePrefix("nostr:") if (key.startsWith("naddr")) { - val tlv = parseTLV(key.bechToBytes()) - val d = tlv.get(TlvTypes.SPECIAL.id)?.get(0)?.toString(Charsets.UTF_8) ?: "" - val relay = tlv.get(TlvTypes.RELAY.id)?.get(0)?.toString(Charsets.UTF_8) - val author = tlv.get(TlvTypes.AUTHOR.id)?.get(0)?.toHexKey() - val kind = tlv.get(TlvTypes.KIND.id)?.get(0)?.let { toInt32(it) } + val tlv = Tlv.parse(key.bechToBytes()) + val d = tlv.get(Tlv.Type.SPECIAL.id)?.get(0)?.toString(Charsets.UTF_8) ?: "" + val relay = tlv.get(Tlv.Type.RELAY.id)?.get(0)?.toString(Charsets.UTF_8) + val author = tlv.get(Tlv.Type.AUTHOR.id)?.get(0)?.toHexKey() + val kind = tlv.get(Tlv.Type.KIND.id)?.get(0)?.let { Tlv.toInt32(it) } if (kind != null && author != null) { return ATag(kind, author, d, relay) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Nip19.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Nip19.kt index 5967dda1e..796936331 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Nip19.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Nip19.kt @@ -44,13 +44,13 @@ object Nip19 { } private fun nprofile(bytes: ByteArray): Return? { - val tlv = parseTLV(bytes) + val tlv = Tlv.parse(bytes) - val hex = tlv.get(TlvTypes.SPECIAL.id) + val hex = tlv.get(Tlv.Type.SPECIAL.id) ?.get(0) ?.toHexKey() ?: return null - val relay = tlv.get(TlvTypes.RELAY.id) + val relay = tlv.get(Tlv.Type.RELAY.id) ?.get(0) ?.toString(Charsets.UTF_8) @@ -58,13 +58,13 @@ object Nip19 { } private fun nevent(bytes: ByteArray): Return? { - val tlv = parseTLV(bytes) + val tlv = Tlv.parse(bytes) - val hex = tlv.get(TlvTypes.SPECIAL.id) + val hex = tlv.get(Tlv.Type.SPECIAL.id) ?.get(0) ?.toHexKey() ?: return null - val relay = tlv.get(TlvTypes.RELAY.id) + val relay = tlv.get(Tlv.Type.RELAY.id) ?.get(0) ?.toString(Charsets.UTF_8) @@ -72,8 +72,8 @@ object Nip19 { } private fun nrelay(bytes: ByteArray): Return? { - val relayUrl = parseTLV(bytes) - .get(TlvTypes.SPECIAL.id) + val relayUrl = Tlv.parse(bytes) + .get(Tlv.Type.SPECIAL.id) ?.get(0) ?.toString(Charsets.UTF_8) ?: return null @@ -81,23 +81,23 @@ object Nip19 { } private fun naddr(bytes: ByteArray): Return? { - val tlv = parseTLV(bytes) + val tlv = Tlv.parse(bytes) - val d = tlv.get(TlvTypes.SPECIAL.id) + val d = tlv.get(Tlv.Type.SPECIAL.id) ?.get(0) ?.toString(Charsets.UTF_8) ?: return null - val relay = tlv.get(TlvTypes.RELAY.id) + val relay = tlv.get(Tlv.Type.RELAY.id) ?.get(0) ?.toString(Charsets.UTF_8) - val author = tlv.get(TlvTypes.AUTHOR.id) + val author = tlv.get(Tlv.Type.AUTHOR.id) ?.get(0) ?.toHexKey() - val kind = tlv.get(TlvTypes.KIND.id) + val kind = tlv.get(Tlv.Type.KIND.id) ?.get(0) - ?.let { toInt32(it) } + ?.let { Tlv.toInt32(it) } return Return(Type.ADDRESS, "$kind:$author:$d", relay) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Tlv.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Tlv.kt new file mode 100644 index 000000000..ef285d627 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Tlv.kt @@ -0,0 +1,36 @@ +package com.vitorpamplona.amethyst.service.nip19 + +import java.nio.ByteBuffer +import java.nio.ByteOrder + +object Tlv { + enum class Type(val id: Byte) { + SPECIAL(0), + RELAY(1), + AUTHOR(2), + KIND(3); + } + + fun toInt32(bytes: ByteArray): Int { + require(bytes.size == 4) { "length must be 4, got: ${bytes.size}" } + return ByteBuffer.wrap(bytes, 0, 4).order(ByteOrder.BIG_ENDIAN).int + } + + fun parse(data: ByteArray): Map> { + val result = mutableMapOf>() + var rest = data + while (rest.isNotEmpty()) { + val t = rest[0] + val l = rest[1] + val v = rest.sliceArray(IntRange(2, (2 + l) - 1)) + rest = rest.sliceArray(IntRange(2 + l, rest.size - 1)) + if (v.size < l) continue + + if (!result.containsKey(t)) { + result[t] = mutableListOf() + } + result[t]?.add(v) + } + return result + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/TlvTypes.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/TlvTypes.kt deleted file mode 100644 index 7199cc6e3..000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/TlvTypes.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.vitorpamplona.amethyst.service.nip19 - -enum class TlvTypes(val id: Byte) { - SPECIAL(0), - RELAY(1), - AUTHOR(2), - KIND(3); -} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Utils.kt b/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Utils.kt deleted file mode 100644 index 01f0f1c04..000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/service/nip19/Utils.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.vitorpamplona.amethyst.service.nip19 - -import java.nio.ByteBuffer -import java.nio.ByteOrder - -fun toInt32(bytes: ByteArray): Int { - require(bytes.size == 4) { "length must be 4, got: ${bytes.size}" } - return ByteBuffer.wrap(bytes, 0, 4).order(ByteOrder.BIG_ENDIAN).int -} - -fun parseTLV(data: ByteArray): Map> { - val result = mutableMapOf>() - var rest = data - while (rest.isNotEmpty()) { - val t = rest[0] - val l = rest[1] - val v = rest.sliceArray(IntRange(2, (2 + l) - 1)) - rest = rest.sliceArray(IntRange(2 + l, rest.size - 1)) - if (v.size < l) continue - - if (!result.containsKey(t)) { - result[t] = mutableListOf() - } - result[t]?.add(v) - } - return result -} diff --git a/app/src/test/java/com/vitorpamplona/amethyst/service/UtilsTest.kt b/app/src/test/java/com/vitorpamplona/amethyst/service/TlvTest.kt similarity index 74% rename from app/src/test/java/com/vitorpamplona/amethyst/service/UtilsTest.kt rename to app/src/test/java/com/vitorpamplona/amethyst/service/TlvTest.kt index bf791042d..9f9087036 100644 --- a/app/src/test/java/com/vitorpamplona/amethyst/service/UtilsTest.kt +++ b/app/src/test/java/com/vitorpamplona/amethyst/service/TlvTest.kt @@ -1,25 +1,25 @@ package com.vitorpamplona.amethyst.service -import com.vitorpamplona.amethyst.service.nip19.toInt32 +import com.vitorpamplona.amethyst.service.nip19.Tlv import org.junit.Assert import org.junit.Ignore import org.junit.Test -class UtilsTest { +class TlvTest { @Test(expected = IllegalArgumentException::class) fun to_int_32_length_smaller_than_4() { - toInt32(byteArrayOfInts(1, 2, 3)) + Tlv.toInt32(byteArrayOfInts(1, 2, 3)) } @Test(expected = IllegalArgumentException::class) fun to_int_32_length_bigger_than_4() { - toInt32(byteArrayOfInts(1, 2, 3, 4, 5)) + Tlv.toInt32(byteArrayOfInts(1, 2, 3, 4, 5)) } @Test() fun to_int_32_length_4() { - val actual = toInt32(byteArrayOfInts(1, 2, 3, 4)) + val actual = Tlv.toInt32(byteArrayOfInts(1, 2, 3, 4)) Assert.assertEquals(16909060, actual) }