Reduces the amount of wasted memory by using Array<Array<List>> as opposed to List<List<String>> for tags.

This commit is contained in:
Vitor Pamplona
2023-11-28 15:00:41 -05:00
parent d87542a949
commit 5356d869fd
68 changed files with 388 additions and 390 deletions
@@ -284,7 +284,7 @@ open class Note(val idHex: String) {
} }
fun removeReaction(note: Note) { fun removeReaction(note: Note) {
val tags = note.event?.tags() ?: emptyList() val tags = note.event?.tags() ?: emptyArray()
val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+" val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+"
if (reaction in reactions.keys && reactions[reaction]?.contains(note) == true) { if (reaction in reactions.keys && reactions[reaction]?.contains(note) == true) {
@@ -403,7 +403,7 @@ open class Note(val idHex: String) {
} }
fun addReaction(note: Note) { fun addReaction(note: Note) {
val tags = note.event?.tags() ?: emptyList() val tags = note.event?.tags() ?: emptyArray()
val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+" val reaction = note.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(tags)) ?: "+"
if (reaction !in reactions.keys) { if (reaction !in reactions.keys) {
@@ -1586,7 +1586,7 @@ fun RenderAppDefinition(
Row(verticalAlignment = Alignment.Bottom, modifier = Modifier.padding(top = 7.dp)) { Row(verticalAlignment = Alignment.Bottom, modifier = Modifier.padding(top = 7.dp)) {
CreateTextWithEmoji( CreateTextWithEmoji(
text = it, text = it,
tags = remember { (note.event?.tags() ?: emptyList()).toImmutableListOfLists() }, tags = remember { (note.event?.tags() ?: emptyArray()).toImmutableListOfLists() },
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 25.sp fontSize = 25.sp
) )
@@ -64,7 +64,7 @@ class MultiSetCard(
) )
val likeEventsByType = likeEvents.groupBy { val likeEventsByType = likeEvents.groupBy {
it.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(it.event?.tags() ?: emptyList())) ?: "+" it.event?.content()?.firstFullCharOrEmoji(ImmutableListOfLists(it.event?.tags() ?: emptyArray())) ?: "+"
}.mapValues { }.mapValues {
it.value.toImmutableList() it.value.toImmutableList()
}.toImmutableMap() }.toImmutableMap()
@@ -13,7 +13,7 @@ class AdvertisedRelayListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -47,11 +47,11 @@ class AdvertisedRelayListEvent(
) { ) {
val tags = list.map { val tags = list.map {
if (it.type == AdvertisedRelayType.BOTH) { if (it.type == AdvertisedRelayType.BOTH) {
listOf(it.relayUrl) arrayOf(it.relayUrl)
} else { } else {
listOf(it.relayUrl, it.type.code) arrayOf(it.relayUrl, it.type.code)
} }
} }.toTypedArray()
val msg = "" val msg = ""
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags, msg, onReady)
@@ -13,7 +13,7 @@ class AppDefinitionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -54,7 +54,7 @@ class AppDefinitionEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (AppDefinitionEvent) -> Unit onReady: (AppDefinitionEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -11,7 +11,7 @@ class AppRecommendationEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -27,7 +27,7 @@ class AppRecommendationEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (AppRecommendationEvent) -> Unit onReady: (AppRecommendationEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -11,7 +11,7 @@ class AudioHeaderEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -29,7 +29,7 @@ class AudioHeaderEvent(
private const val STREAM_URL = "stream_url" private const val STREAM_URL = "stream_url"
private const val WAVEFORM = "waveform" private const val WAVEFORM = "waveform"
suspend fun create( fun create(
description: String, description: String,
downloadUrl: String, downloadUrl: String,
streamUrl: String? = null, streamUrl: String? = null,
@@ -40,17 +40,17 @@ class AudioHeaderEvent(
onReady: (AudioHeaderEvent) -> Unit onReady: (AudioHeaderEvent) -> Unit
) { ) {
val tags = listOfNotNull( val tags = listOfNotNull(
downloadUrl.let { listOf(DOWNLOAD_URL, it) }, downloadUrl.let { arrayOf(DOWNLOAD_URL, it) },
streamUrl?.let { listOf(STREAM_URL, it) }, streamUrl?.let { arrayOf(STREAM_URL, it) },
wavefront?.let { listOf(WAVEFORM, it) }, wavefront?.let { arrayOf(WAVEFORM, it) },
sensitiveContent?.let { sensitiveContent?.let {
if (it) { if (it) {
listOf("content-warning", "") arrayOf("content-warning", "")
} else { } else {
null null
} }
} }
) ).toTypedArray()
signer.sign(createdAt, kind, tags, description, onReady) signer.sign(createdAt, kind, tags, description, onReady)
} }
@@ -13,7 +13,7 @@ class AudioTrackEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -46,12 +46,12 @@ class AudioTrackEvent(
onReady: (AudioTrackEvent) -> Unit onReady: (AudioTrackEvent) -> Unit
) { ) {
val tags = listOfNotNull( val tags = listOfNotNull(
listOf(MEDIA, media), arrayOf(MEDIA, media),
listOf(TYPE, type), arrayOf(TYPE, type),
price?.let { listOf(PRICE, it) }, price?.let { arrayOf(PRICE, it) },
cover?.let { listOf(COVER, it) }, cover?.let { arrayOf(COVER, it) },
subject?.let { listOf(SUBJECT, it) } subject?.let { arrayOf(SUBJECT, it) }
) ).toTypedArray()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
@@ -8,7 +8,7 @@ class BadgeAwardEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -9,7 +9,7 @@ class BadgeDefinitionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -9,7 +9,7 @@ class BadgeProfilesEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -16,7 +16,7 @@ open class BaseTextNoteEvent(
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -13,7 +13,7 @@ class BookmarkListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -49,7 +49,7 @@ class BookmarkListEvent(
) { ) {
add( add(
earlierVersion, earlierVersion,
listOf(listOf(tagName, tagValue)), arrayOf(arrayOf(tagName, tagValue)),
isPrivate, isPrivate,
signer, signer,
createdAt, createdAt,
@@ -59,7 +59,7 @@ class BookmarkListEvent(
fun add( fun add(
earlierVersion: BookmarkListEvent?, earlierVersion: BookmarkListEvent?,
listNewTags: List<List<String>>, listNewTags: Array<Array<String>>,
isPrivate: Boolean, isPrivate: Boolean,
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
@@ -88,7 +88,7 @@ class BookmarkListEvent(
) { encryptedTags -> ) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = emptyList(), tags = emptyArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -98,7 +98,7 @@ class BookmarkListEvent(
} else { } else {
create( create(
content = earlierVersion?.content ?: "", content = earlierVersion?.content ?: "",
tags = (earlierVersion?.tags ?: emptyList()).plus(listNewTags), tags = (earlierVersion?.tags ?: emptyArray()).plus(listNewTags),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -136,12 +136,12 @@ class BookmarkListEvent(
if (isPrivate) { if (isPrivate) {
earlierVersion.privateTagsOrEmpty(signer) { privateTags -> earlierVersion.privateTagsOrEmpty(signer) { privateTags ->
encryptTags( encryptTags(
privateTags = privateTags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }, privateTags = privateTags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }.toTypedArray(),
signer = signer signer = signer
) { encryptedTags -> ) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = earlierVersion.tags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }, tags = earlierVersion.tags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -151,7 +151,7 @@ class BookmarkListEvent(
} else { } else {
create( create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }, tags = earlierVersion.tags.filter { it.size <= 1 || !(it[0] == tagName && it[1] == tagValue) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -161,7 +161,7 @@ class BookmarkListEvent(
fun create( fun create(
content: String, content: String,
tags: List<List<String>>, tags: Array<Array<String>>,
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (BookmarkListEvent) -> Unit onReady: (BookmarkListEvent) -> Unit
@@ -184,21 +184,21 @@ class BookmarkListEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (BookmarkListEvent) -> Unit onReady: (BookmarkListEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
tags.add(listOf("d", name)) tags.add(arrayOf("d", name))
events?.forEach { events?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
users?.forEach { users?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
addresses?.forEach { addresses?.forEach {
tags.add(listOf("a", it.toTag())) tags.add(arrayOf("a", it.toTag()))
} }
createPrivateTags(privEvents, privUsers, privAddresses, signer) { content -> createPrivateTags(privEvents, privUsers, privAddresses, signer) { content ->
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -13,7 +13,7 @@ class CalendarDateSlotEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -33,7 +33,7 @@ class CalendarDateSlotEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (CalendarDateSlotEvent) -> Unit onReady: (CalendarDateSlotEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -13,7 +13,7 @@ class CalendarEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -25,7 +25,7 @@ class CalendarEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (CalendarEvent) -> Unit onReady: (CalendarEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -13,7 +13,7 @@ class CalendarRSVPEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -35,7 +35,7 @@ class CalendarRSVPEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (CalendarRSVPEvent) -> Unit onReady: (CalendarRSVPEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -13,7 +13,7 @@ class CalendarTimeSlotEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -37,7 +37,7 @@ class CalendarTimeSlotEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (CalendarTimeSlotEvent) -> Unit onReady: (CalendarTimeSlotEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -16,7 +16,7 @@ class ChannelCreateEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -65,7 +65,7 @@ class ChannelCreateEvent(
"" ""
} }
signer.sign(createdAt, kind, emptyList(), content, onReady) signer.sign(createdAt, kind, emptyArray(), content, onReady)
} }
} }
@@ -12,7 +12,7 @@ class ChannelHideMessageEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { ) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel {
@@ -36,8 +36,8 @@ class ChannelHideMessageEvent(
) { ) {
val tags = val tags =
messagesToHide?.map { messagesToHide?.map {
listOf("e", it) arrayOf("e", it)
} ?: emptyList() }?.toTypedArray() ?: emptyArray()
signer.sign(createdAt, kind, tags, reason, onReady) signer.sign(createdAt, kind, tags, reason, onReady)
} }
@@ -2,9 +2,6 @@ package com.vitorpamplona.quartz.events
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.TimeUtils
import com.vitorpamplona.quartz.encoders.toHexKey
import com.vitorpamplona.quartz.crypto.CryptoUtils
import com.vitorpamplona.quartz.crypto.KeyPair
import com.vitorpamplona.quartz.encoders.HexKey import com.vitorpamplona.quartz.encoders.HexKey
import com.vitorpamplona.quartz.signers.NostrSigner import com.vitorpamplona.quartz.signers.NostrSigner
@@ -13,7 +10,7 @@ class ChannelMessageEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { ) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel {
@@ -42,30 +39,29 @@ class ChannelMessageEvent(
geohash: String? = null, geohash: String? = null,
onReady: (ChannelMessageEvent) -> Unit onReady: (ChannelMessageEvent) -> Unit
) { ) {
val content = message
val tags = mutableListOf( val tags = mutableListOf(
listOf("e", channel, "", "root") arrayOf("e", channel, "", "root")
) )
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), message, onReady)
} }
} }
} }
@@ -14,7 +14,7 @@ class ChannelMetadataEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { ) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel {
@@ -65,8 +65,8 @@ class ChannelMetadataEvent(
"" ""
} }
val tags = listOf(listOf("e", originalChannelIdHex, "", "root")) val tags = listOf(arrayOf("e", originalChannelIdHex, "", "root"))
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -12,7 +12,7 @@ class ChannelMuteUserEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel { ) : Event(id, pubKey, createdAt, kind, tags, content, sig), IsInPublicChatChannel {
@@ -36,8 +36,8 @@ class ChannelMuteUserEvent(
) { ) {
val content = reason val content = reason
val tags = usersToMute?.map { val tags = usersToMute?.map {
listOf("p", it) arrayOf("p", it)
} ?: emptyList() }?.toTypedArray() ?: emptyArray()
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
} }
@@ -13,7 +13,7 @@ class ChatMessageEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable { ) : WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable {
@@ -64,33 +64,33 @@ class ChatMessageEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (ChatMessageEvent) -> Unit onReady: (ChatMessageEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
to?.forEach { to?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it, "", "mention")) tags.add(arrayOf("p", it, "", "mention"))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
subject?.let { subject?.let {
tags.add(listOf("subject", it)) tags.add(arrayOf("subject", it))
} }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -13,7 +13,7 @@ class ClassifiedsEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -46,26 +46,26 @@ class ClassifiedsEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (ClassifiedsEvent) -> Unit onReady: (ClassifiedsEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
tags.add(listOf("d", dTag)) tags.add(arrayOf("d", dTag))
title?.let { tags.add(listOf("title", it)) } title?.let { tags.add(arrayOf("title", it)) }
image?.let { tags.add(listOf("image", it)) } image?.let { tags.add(arrayOf("image", it)) }
summary?.let { tags.add(listOf("summary", it)) } summary?.let { tags.add(arrayOf("summary", it)) }
price?.let { price?.let {
if (it.frequency != null && it.currency != null) { if (it.frequency != null && it.currency != null) {
tags.add(listOf("price", it.amount, it.currency, it.frequency)) tags.add(arrayOf("price", it.amount, it.currency, it.frequency))
} else if (it.currency != null) { } else if (it.currency != null) {
tags.add(listOf("price", it.amount, it.currency)) tags.add(arrayOf("price", it.amount, it.currency))
} else { } else {
tags.add(listOf("price", it.amount)) tags.add(arrayOf("price", it.amount))
} }
} }
location?.let { tags.add(listOf("location", it)) } location?.let { tags.add(arrayOf("location", it)) }
publishedAt?.let { tags.add(listOf("publishedAt", it.toString())) } publishedAt?.let { tags.add(arrayOf("publishedAt", it.toString())) }
title?.let { tags.add(listOf("title", it)) } title?.let { tags.add(arrayOf("title", it)) }
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags.toTypedArray(), "", onReady)
} }
} }
} }
@@ -13,7 +13,7 @@ class CommunityDefinitionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -31,7 +31,7 @@ class CommunityDefinitionEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (CommunityDefinitionEvent) -> Unit onReady: (CommunityDefinitionEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -14,7 +14,7 @@ class CommunityPostApprovalEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -55,12 +55,12 @@ class CommunityPostApprovalEvent(
) { ) {
val content = approvedPost.toJson() val content = approvedPost.toJson()
val communities = listOf("a", community.address().toTag()) val communities = arrayOf("a", community.address().toTag())
val replyToPost = listOf("e", approvedPost.id()) val replyToPost = arrayOf("e", approvedPost.id())
val replyToAuthor = listOf("p", approvedPost.pubKey()) val replyToAuthor = arrayOf("p", approvedPost.pubKey())
val innerKind = listOf("k", "${approvedPost.kind()}") val innerKind = arrayOf("k", "${approvedPost.kind()}")
val tags: List<List<String>> = listOf(communities, replyToPost, replyToAuthor, innerKind) val tags: Array<Array<String>> = arrayOf(communities, replyToPost, replyToAuthor, innerKind)
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
} }
@@ -21,7 +21,7 @@ class ContactListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -112,27 +112,27 @@ class ContactListEvent(
val tags = followUsers.map { val tags = followUsers.map {
if (it.relayUri != null) { if (it.relayUri != null) {
listOf("p", it.pubKeyHex, it.relayUri) arrayOf("p", it.pubKeyHex, it.relayUri)
} else { } else {
listOf("p", it.pubKeyHex) arrayOf("p", it.pubKeyHex)
} }
} + followTags.map { } + followTags.map {
listOf("t", it) arrayOf("t", it)
} + followEvents.map { } + followEvents.map {
listOf("e", it) arrayOf("e", it)
} + followCommunities.map { } + followCommunities.map {
if (it.relay != null) { if (it.relay != null) {
listOf("a", it.toTag(), it.relay) arrayOf("a", it.toTag(), it.relay)
} else { } else {
listOf("a", it.toTag()) arrayOf("a", it.toTag())
} }
} + followGeohashes.map { } + followGeohashes.map {
listOf("g", it) arrayOf("g", it)
} }
return create( return create(
content = content, content = content,
tags = tags, tags = tags.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -144,7 +144,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("p", pubKeyHex)), tags = earlierVersion.tags.plus(element = arrayOf("p", pubKeyHex)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -156,7 +156,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != pubKeyHex }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -168,7 +168,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("t", hashtag)), tags = earlierVersion.tags.plus(element = arrayOf("t", hashtag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -180,7 +180,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && !it[1].equals(hashtag, true) }, tags = earlierVersion.tags.filter { it.size > 1 && !it[1].equals(hashtag, true) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -192,7 +192,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("g", hashtag)), tags = earlierVersion.tags.plus(element = arrayOf("g", hashtag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -204,7 +204,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != hashtag }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -216,7 +216,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf("e", idHex)), tags = earlierVersion.tags.plus(element = arrayOf("e", idHex)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -228,7 +228,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != idHex }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -240,7 +240,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay)), tags = earlierVersion.tags.plus(element = listOfNotNull("a", aTag.toTag(), aTag.relay).toTypedArray()),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -252,7 +252,7 @@ class ContactListEvent(
return create( return create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() }, tags = earlierVersion.tags.filter { it.size > 1 && it[1] != aTag.toTag() }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -277,7 +277,7 @@ class ContactListEvent(
fun create( fun create(
content: String, content: String,
tags: List<List<String>>, tags: Array<Array<String>>,
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (ContactListEvent) -> Unit onReady: (ContactListEvent) -> Unit
@@ -346,10 +346,10 @@ class UserMetadata {
} }
@Stable @Stable
data class ImmutableListOfLists<T>(val lists: List<List<T>> = emptyList()) data class ImmutableListOfLists<T>(val lists: Array<Array<T>>)
val EmptyTagList = ImmutableListOfLists<String>(emptyList()) val EmptyTagList = ImmutableListOfLists<String>(emptyArray())
fun List<List<String>>.toImmutableListOfLists(): ImmutableListOfLists<String> { fun Array<Array<String>>.toImmutableListOfLists(): ImmutableListOfLists<String> {
return ImmutableListOfLists(this) return ImmutableListOfLists(this)
} }
@@ -13,7 +13,7 @@ class DeletionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -24,7 +24,7 @@ class DeletionEvent(
fun create(deleteEvents: List<String>, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (DeletionEvent) -> Unit) { fun create(deleteEvents: List<String>, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (DeletionEvent) -> Unit) {
val content = "" val content = ""
val tags = deleteEvents.map { listOf("e", it) } val tags = deleteEvents.map { arrayOf("e", it) }.toTypedArray()
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
} }
} }
@@ -12,7 +12,7 @@ class EmojiPackEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -28,10 +28,10 @@ class EmojiPackEvent(
) { ) {
val content = "" val content = ""
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
tags.add(listOf("d", name)) tags.add(arrayOf("d", name))
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -14,7 +14,7 @@ class EmojiPackSelectionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -31,13 +31,13 @@ class EmojiPackSelectionEvent(
onReady: (EmojiPackSelectionEvent) -> Unit onReady: (EmojiPackSelectionEvent) -> Unit
) { ) {
val msg = "" val msg = ""
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
listOfEmojiPacks?.forEach { listOfEmojiPacks?.forEach {
tags.add(listOf("a", it.toTag())) tags.add(arrayOf("a", it.toTag()))
} }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -11,6 +11,7 @@ import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.SerializerProvider import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.deser.std.StdDeserializer import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.fasterxml.jackson.databind.module.SimpleModule import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.databind.node.ArrayNode
import com.fasterxml.jackson.databind.ser.std.StdSerializer import com.fasterxml.jackson.databind.ser.std.StdSerializer
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.vitorpamplona.quartz.crypto.CryptoUtils import com.vitorpamplona.quartz.crypto.CryptoUtils
@@ -33,7 +34,7 @@ open class Event(
@JsonProperty("created_at") @JsonProperty("created_at")
val createdAt: Long, val createdAt: Long,
val kind: Int, val kind: Int,
val tags: List<List<String>>, val tags: Array<Array<String>>,
val content: String, val content: String,
val sig: HexKey val sig: HexKey
) : EventInterface { ) : EventInterface {
@@ -55,7 +56,7 @@ open class Event(
override fun kind(): Int = kind override fun kind(): Int = kind
override fun tags(): List<List<String>> = tags override fun tags(): Array<Array<String>> = tags
override fun content(): String = content override fun content(): String = content
@@ -272,14 +273,13 @@ open class Event(
private class GossipDeserializer : StdDeserializer<Gossip>(Gossip::class.java) { private class GossipDeserializer : StdDeserializer<Gossip>(Gossip::class.java) {
override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Gossip { override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): Gossip {
val jsonObject: JsonNode = jp.codec.readTree(jp) val jsonObject: JsonNode = jp.codec.readTree(jp)
val tagList = jsonObject.get("tags")
return Gossip( return Gossip(
id = jsonObject.get("id")?.asText()?.intern(), id = jsonObject.get("id")?.asText()?.intern(),
pubKey = jsonObject.get("pubkey")?.asText()?.intern(), pubKey = jsonObject.get("pubkey")?.asText()?.intern(),
createdAt = jsonObject.get("created_at")?.asLong(), createdAt = jsonObject.get("created_at")?.asLong(),
kind = jsonObject.get("kind")?.asInt(), kind = jsonObject.get("kind")?.asInt(),
tags = tagList.mapTo(ArrayList<List<String>>(tagList.size())) { tags = jsonObject.get("tags").toTypedArray {
it.mapNotNullTo(ArrayList<String>(it.size())) { s -> if (s.isNull) null else s.asText().intern() } it.toTypedArray { s -> if (s.isNull) "" else s.asText().intern() }
}, },
content = jsonObject.get("content")?.asText() content = jsonObject.get("content")?.asText()
) )
@@ -295,7 +295,7 @@ open class Event(
gen.writeNumberField("kind", event.kind) gen.writeNumberField("kind", event.kind)
gen.writeArrayFieldStart("tags") gen.writeArrayFieldStart("tags")
event.tags.forEach { tag -> event.tags.forEach { tag ->
gen.writeArray(tag.toTypedArray(), 0, tag.size) gen.writeArray(tag, 0, tag.size)
} }
gen.writeEndArray() gen.writeEndArray()
gen.writeStringField("content", event.content) gen.writeStringField("content", event.content)
@@ -314,7 +314,7 @@ open class Event(
event.tags?.let { event.tags?.let {
gen.writeArrayFieldStart("tags") gen.writeArrayFieldStart("tags")
event.tags.forEach { tag -> event.tags.forEach { tag ->
gen.writeArray(tag.toTypedArray(), 0, tag.size) gen.writeArray(tag, 0, tag.size)
} }
gen.writeEndArray() gen.writeEndArray()
} }
@@ -361,24 +361,29 @@ open class Event(
) )
fun fromJson(jsonObject: JsonNode): Event { fun fromJson(jsonObject: JsonNode): Event {
val tagList = jsonObject.get("tags")
return EventFactory.create( return EventFactory.create(
id = jsonObject.get("id").asText().intern(), id = jsonObject.get("id").asText().intern(),
pubKey = jsonObject.get("pubkey").asText().intern(), pubKey = jsonObject.get("pubkey").asText().intern(),
createdAt = jsonObject.get("created_at").asLong(), createdAt = jsonObject.get("created_at").asLong(),
kind = jsonObject.get("kind").asInt(), kind = jsonObject.get("kind").asInt(),
tags = tagList.mapTo(ArrayList<List<String>>(tagList.size())) { tags = jsonObject.get("tags").toTypedArray {
it.mapNotNullTo(ArrayList<String>(it.size())) { s -> if (s.isNull) null else s.asText().intern() } it.toTypedArray { s -> if (s.isNull) "" else s.asText().intern() }
}, },
content = jsonObject.get("content").asText(), content = jsonObject.get("content").asText(),
sig = jsonObject.get("sig").asText() sig = jsonObject.get("sig").asText()
) )
} }
private inline fun <reified R> JsonNode.toTypedArray(transform: (JsonNode) -> R): Array<R> {
return Array(size()) {
transform(get(it))
}
}
fun fromJson(json: String): Event = mapper.readValue(json, Event::class.java) fun fromJson(json: String): Event = mapper.readValue(json, Event::class.java)
fun toJson(event: Event): String = mapper.writeValueAsString(event) fun toJson(event: Event): String = mapper.writeValueAsString(event)
fun makeJsonForId(pubKey: HexKey, createdAt: Long, kind: Int, tags: List<List<String>>, content: String): String { fun makeJsonForId(pubKey: HexKey, createdAt: Long, kind: Int, tags: Array<Array<String>>, content: String): String {
val factory = mapper.nodeFactory val factory = mapper.nodeFactory
val rawEvent = factory.arrayNode(6).apply { val rawEvent = factory.arrayNode(6).apply {
add(0) add(0)
@@ -402,11 +407,11 @@ open class Event(
return mapper.writeValueAsString(rawEvent) return mapper.writeValueAsString(rawEvent)
} }
fun generateId(pubKey: HexKey, createdAt: Long, kind: Int, tags: List<List<String>>, content: String): ByteArray { fun generateId(pubKey: HexKey, createdAt: Long, kind: Int, tags: Array<Array<String>>, content: String): ByteArray {
return CryptoUtils.sha256(makeJsonForId(pubKey, createdAt, kind, tags, content).toByteArray()) return CryptoUtils.sha256(makeJsonForId(pubKey, createdAt, kind, tags, content).toByteArray())
} }
fun create(signer: NostrSigner, kind: Int, tags: List<List<String>> = emptyList(), content: String = "", createdAt: Long = TimeUtils.now(), onReady: (Event) -> Unit) { fun create(signer: NostrSigner, kind: Int, tags: Array<Array<String>> = emptyArray(), content: String = "", createdAt: Long = TimeUtils.now(), onReady: (Event) -> Unit) {
return signer.sign(createdAt, kind, tags, content, onReady) return signer.sign(createdAt, kind, tags, content, onReady)
} }
} }
@@ -420,7 +425,7 @@ open class WrappedEvent(
@JsonProperty("created_at") @JsonProperty("created_at")
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -440,7 +445,7 @@ open class BaseAddressableEvent(
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
): Event(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent { ): Event(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent {
@@ -10,7 +10,7 @@ class EventFactory {
pubKey: String, pubKey: String,
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: String sig: String
) = when (kind) { ) = when (kind) {
@@ -17,7 +17,7 @@ interface EventInterface {
fun kind(): Int fun kind(): Int
fun tags(): List<List<String>> fun tags(): Array<Array<String>>
fun content(): String fun content(): String
@@ -13,7 +13,7 @@ class FileHeaderEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -62,20 +62,20 @@ class FileHeaderEvent(
onReady: (FileHeaderEvent) -> Unit onReady: (FileHeaderEvent) -> Unit
) { ) {
val tags = listOfNotNull( val tags = listOfNotNull(
listOf(URL, url), arrayOf(URL, url),
mimeType?.let { listOf(MIME_TYPE, mimeType) }, mimeType?.let { arrayOf(MIME_TYPE, mimeType) },
alt?.ifBlank { null }?.let { listOf(ALT, it) }, alt?.ifBlank { null }?.let { arrayOf(ALT, it) },
hash?.let { listOf(HASH, it) }, hash?.let { arrayOf(HASH, it) },
size?.let { listOf(FILE_SIZE, it) }, size?.let { arrayOf(FILE_SIZE, it) },
dimensions?.let { listOf(DIMENSION, it) }, dimensions?.let { arrayOf(DIMENSION, it) },
blurhash?.let { listOf(BLUR_HASH, it) }, blurhash?.let { arrayOf(BLUR_HASH, it) },
magnetURI?.let { listOf(MAGNET_URI, it) }, magnetURI?.let { arrayOf(MAGNET_URI, it) },
torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, torrentInfoHash?.let { arrayOf(TORRENT_INFOHASH, it) },
encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, encryptionKey?.let { arrayOf(ENCRYPTION_KEY, it.key, it.nonce) },
sensitiveContent?.let { sensitiveContent?.let {
if (it) { if (it) {
listOf("content-warning", "") arrayOf("content-warning", "")
} else { } else {
null null
} }
@@ -83,7 +83,7 @@ class FileHeaderEvent(
) )
val content = alt ?: "" val content = alt ?: ""
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -14,7 +14,7 @@ class FileStorageEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -49,11 +49,11 @@ class FileStorageEvent(
onReady: (FileStorageEvent) -> Unit onReady: (FileStorageEvent) -> Unit
) { ) {
val tags = listOfNotNull( val tags = listOfNotNull(
listOf(TYPE, mimeType) arrayOf(TYPE, mimeType)
) )
val content = encode(data) val content = encode(data)
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -12,7 +12,7 @@ class FileStorageHeaderEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -59,19 +59,19 @@ class FileStorageHeaderEvent(
onReady: (FileStorageHeaderEvent) -> Unit onReady: (FileStorageHeaderEvent) -> Unit
) { ) {
val tags = listOfNotNull( val tags = listOfNotNull(
listOf("e", storageEvent.id), arrayOf("e", storageEvent.id),
mimeType?.let { listOf(MIME_TYPE, mimeType) }, mimeType?.let { arrayOf(MIME_TYPE, mimeType) },
hash?.let { listOf(HASH, it) }, hash?.let { arrayOf(HASH, it) },
alt?.let { listOf(ALT, it) }, alt?.let { arrayOf(ALT, it) },
size?.let { listOf(FILE_SIZE, it) }, size?.let { arrayOf(FILE_SIZE, it) },
dimensions?.let { listOf(DIMENSION, it) }, dimensions?.let { arrayOf(DIMENSION, it) },
blurhash?.let { listOf(BLUR_HASH, it) }, blurhash?.let { arrayOf(BLUR_HASH, it) },
magnetURI?.let { listOf(MAGNET_URI, it) }, magnetURI?.let { arrayOf(MAGNET_URI, it) },
torrentInfoHash?.let { listOf(TORRENT_INFOHASH, it) }, torrentInfoHash?.let { arrayOf(TORRENT_INFOHASH, it) },
encryptionKey?.let { listOf(ENCRYPTION_KEY, it.key, it.nonce) }, encryptionKey?.let { arrayOf(ENCRYPTION_KEY, it.key, it.nonce) },
sensitiveContent?.let { sensitiveContent?.let {
if (it) { if (it) {
listOf("content-warning", "") arrayOf("content-warning", "")
} else { } else {
null null
} }
@@ -79,7 +79,7 @@ class FileStorageHeaderEvent(
) )
val content = alt ?: "" val content = alt ?: ""
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -17,12 +17,12 @@ abstract class GeneralListEvent(
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@Transient @Transient
private var privateTagsCache: List<List<String>>? = null private var privateTagsCache: Array<Array<String>>? = null
fun category() = dTag() fun category() = dTag()
fun bookmarkedPosts() = taggedEvents() fun bookmarkedPosts() = taggedEvents()
@@ -32,11 +32,11 @@ abstract class GeneralListEvent(
fun title() = tags.firstOrNull { it.size > 1 && it[0] == "title" }?.get(1) fun title() = tags.firstOrNull { it.size > 1 && it[0] == "title" }?.get(1)
fun nameOrTitle() = name() ?: title() fun nameOrTitle() = name() ?: title()
fun cachedPrivateTags(): List<List<String>>? { fun cachedPrivateTags(): Array<Array<String>>? {
return privateTagsCache return privateTagsCache
} }
fun filterTagList(key: String, privateTags: List<List<String>>?): ImmutableSet<String> { fun filterTagList(key: String, privateTags: Array<Array<String>>?): ImmutableSet<String> {
val privateUserList = privateTags?.let { val privateUserList = privateTags?.let {
it.filter { it.size > 1 && it[0] == key }.map { it[1] }.toSet() it.filter { it.size > 1 && it[0] == key }.map { it[1] }.toSet()
} ?: emptySet() } ?: emptySet()
@@ -57,7 +57,7 @@ abstract class GeneralListEvent(
} }
} }
fun privateTags(signer: NostrSigner, onReady: (List<List<String>>) -> Unit) { fun privateTags(signer: NostrSigner, onReady: (Array<Array<String>>) -> Unit) {
if (content.isBlank()) return if (content.isBlank()) return
privateTagsCache?.let { privateTagsCache?.let {
@@ -67,7 +67,7 @@ abstract class GeneralListEvent(
try { try {
signer.nip04Decrypt(content, pubKey) { signer.nip04Decrypt(content, pubKey) {
privateTagsCache = mapper.readValue<List<List<String>>>(it) privateTagsCache = mapper.readValue<Array<Array<String>>>(it)
privateTagsCache?.let { privateTagsCache?.let {
onReady(it) onReady(it)
} }
@@ -77,7 +77,7 @@ abstract class GeneralListEvent(
} }
} }
fun privateTagsOrEmpty(signer: NostrSigner, onReady: (List<List<String>>) -> Unit) { fun privateTagsOrEmpty(signer: NostrSigner, onReady: (Array<Array<String>>) -> Unit) {
privateTags(signer, onReady) privateTags(signer, onReady)
} }
@@ -97,23 +97,23 @@ abstract class GeneralListEvent(
onReady(filterAddresses(it)) onReady(filterAddresses(it))
} }
fun filterUsers(tags: List<List<String>>): List<String> { fun filterUsers(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] } return tags.filter { it.size > 1 && it[0] == "p" }.map { it[1] }
} }
fun filterHashtags(tags: List<List<String>>): List<String> { fun filterHashtags(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "t" }.map { it[1] } return tags.filter { it.size > 1 && it[0] == "t" }.map { it[1] }
} }
fun filterGeohashes(tags: List<List<String>>): List<String> { fun filterGeohashes(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "g" }.map { it[1] } return tags.filter { it.size > 1 && it[0] == "g" }.map { it[1] }
} }
fun filterEvents(tags: List<List<String>>): List<String> { fun filterEvents(tags: Array<Array<String>>): List<String> {
return tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] } return tags.filter { it.size > 1 && it[0] == "e" }.map { it[1] }
} }
fun filterAddresses(tags: List<List<String>>): List<ATag> { fun filterAddresses(tags: Array<Array<String>>): List<ATag> {
return tags.filter { it.firstOrNull() == "a" }.mapNotNull { return tags.filter { it.firstOrNull() == "a" }.mapNotNull {
val aTagValue = it.getOrNull(1) val aTagValue = it.getOrNull(1)
val relay = it.getOrNull(2) val relay = it.getOrNull(2)
@@ -131,22 +131,22 @@ abstract class GeneralListEvent(
signer: NostrSigner, signer: NostrSigner,
onReady: (String) -> Unit onReady: (String) -> Unit
) { ) {
val privTags = mutableListOf<List<String>>() val privTags = mutableListOf<Array<String>>()
privEvents?.forEach { privEvents?.forEach {
privTags.add(listOf("e", it)) privTags.add(arrayOf("e", it))
} }
privUsers?.forEach { privUsers?.forEach {
privTags.add(listOf("p", it)) privTags.add(arrayOf("p", it))
} }
privAddresses?.forEach { privAddresses?.forEach {
privTags.add(listOf("a", it.toTag())) privTags.add(arrayOf("a", it.toTag()))
} }
return encryptTags(privTags, signer, onReady) return encryptTags(privTags.toTypedArray(), signer, onReady)
} }
fun encryptTags( fun encryptTags(
privateTags: List<List<String>>? = null, privateTags: Array<Array<String>>? = null,
signer: NostrSigner, signer: NostrSigner,
onReady: (String) -> Unit onReady: (String) -> Unit
) { ) {
@@ -13,7 +13,7 @@ class GenericRepostEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -38,18 +38,18 @@ class GenericRepostEvent(
) { ) {
val content = boostedPost.toJson() val content = boostedPost.toJson()
val replyToPost = listOf("e", boostedPost.id()) val replyToPost = arrayOf("e", boostedPost.id())
val replyToAuthor = listOf("p", boostedPost.pubKey()) val replyToAuthor = arrayOf("p", boostedPost.pubKey())
var tags: List<List<String>> = listOf(replyToPost, replyToAuthor) var tags: List<Array<String>> = listOf(replyToPost, replyToAuthor)
if (boostedPost is AddressableEvent) { if (boostedPost is AddressableEvent) {
tags = tags + listOf(listOf("a", boostedPost.address().toTag())) tags = tags + listOf(arrayOf("a", boostedPost.address().toTag()))
} }
tags = tags + listOf(listOf("k", "${boostedPost.kind()}")) tags = tags + listOf(arrayOf("k", "${boostedPost.kind()}"))
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -19,7 +19,7 @@ class GiftWrapEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -71,7 +71,7 @@ class GiftWrapEvent(
) { ) {
val signer = NostrSignerInternal(KeyPair()) // GiftWrap is always a random key val signer = NostrSignerInternal(KeyPair()) // GiftWrap is always a random key
val serializedContent = toJson(event) val serializedContent = toJson(event)
val tags = listOf(listOf("p", recipientPubKey)) val tags = arrayOf(arrayOf("p", recipientPubKey))
signer.nip44Encrypt(serializedContent, recipientPubKey) { signer.nip44Encrypt(serializedContent, recipientPubKey) {
signer.sign(createdAt, kind, tags, it, onReady) signer.sign(createdAt, kind, tags, it, onReady)
@@ -13,7 +13,7 @@ class HTTPAuthorizationEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -35,12 +35,12 @@ class HTTPAuthorizationEvent(
} }
val tags = listOfNotNull( val tags = listOfNotNull(
listOf("u", url), arrayOf("u", url),
listOf("method", method), arrayOf("method", method),
listOf("payload", hash) arrayOf("payload", hash)
) )
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags.toTypedArray(), "", onReady)
} }
} }
} }
@@ -12,7 +12,7 @@ class HighlightEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -32,7 +32,7 @@ class HighlightEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (HighlightEvent) -> Unit onReady: (HighlightEvent) -> Unit
) { ) {
signer.sign(createdAt, kind, emptyList(), msg, onReady) signer.sign(createdAt, kind, emptyArray(), msg, onReady)
} }
} }
} }
@@ -14,7 +14,7 @@ class LiveActivitiesChatMessageEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -60,28 +60,28 @@ class LiveActivitiesChatMessageEvent(
) { ) {
val content = message val content = message
val tags = mutableListOf( val tags = mutableListOf(
listOf("a", activity.toTag(), "", "root") arrayOf("a", activity.toTag(), "", "root")
) )
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
@@ -13,7 +13,7 @@ class LiveActivitiesEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -55,7 +55,7 @@ class LiveActivitiesEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (LiveActivitiesEvent) -> Unit onReady: (LiveActivitiesEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -10,7 +10,7 @@ class LnZapEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : LnZapEventInterface, Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : LnZapEventInterface, Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -18,7 +18,7 @@ class LnZapPaymentRequestEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -66,8 +66,7 @@ class LnZapPaymentRequestEvent(
) { ) {
val serializedRequest = mapper.writeValueAsString(PayInvoiceMethod.create(lnInvoice)) val serializedRequest = mapper.writeValueAsString(PayInvoiceMethod.create(lnInvoice))
val tags = mutableListOf<List<String>>() val tags = arrayOf(arrayOf("p", walletServicePubkey))
tags.add(listOf("p", walletServicePubkey))
signer.nip04Encrypt( signer.nip04Encrypt(
serializedRequest, serializedRequest,
@@ -16,7 +16,7 @@ class LnZapPaymentResponseEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -21,7 +21,7 @@ class LnZapPrivateEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -31,7 +31,7 @@ class LnZapPrivateEvent(
fun create( fun create(
signer: NostrSigner, signer: NostrSigner,
tags: List<List<String>> = emptyList(), tags: Array<Array<String>> = emptyArray(),
content: String = "", content: String = "",
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (LnZapPrivateEvent) -> Unit onReady: (LnZapPrivateEvent) -> Unit
@@ -22,7 +22,7 @@ class LnZapRequestEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -89,25 +89,25 @@ class LnZapRequestEvent(
if (zapType == LnZapEvent.ZapType.NONZAP) return if (zapType == LnZapEvent.ZapType.NONZAP) return
var tags = listOf( var tags = listOf(
listOf("e", originalNote.id()), arrayOf("e", originalNote.id()),
listOf("p", toUserPubHex ?: originalNote.pubKey()), arrayOf("p", toUserPubHex ?: originalNote.pubKey()),
listOf("relays") + relays arrayOf("relays") + relays
) )
if (originalNote is AddressableEvent) { if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag())) tags = tags + listOf(arrayOf("a", originalNote.address().toTag()))
} }
if (pollOption != null && pollOption >= 0) { if (pollOption != null && pollOption >= 0) {
tags = tags + listOf(listOf(POLL_OPTION, pollOption.toString())) tags = tags + listOf(arrayOf(POLL_OPTION, pollOption.toString()))
} }
if (zapType == LnZapEvent.ZapType.ANONYMOUS) { if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
tags = tags + listOf(listOf("anon")) tags = tags + listOf(arrayOf("anon"))
NostrSignerInternal(KeyPair()).sign(createdAt, kind, tags, message, onReady) NostrSignerInternal(KeyPair()).sign(createdAt, kind, tags.toTypedArray(), message, onReady)
} else if (zapType == LnZapEvent.ZapType.PRIVATE) { } else if (zapType == LnZapEvent.ZapType.PRIVATE) {
tags = tags + listOf(listOf("anon", "")) tags = tags + listOf(arrayOf("anon", ""))
signer.sign(createdAt, kind, tags, message, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), message, onReady)
} else { } else {
signer.sign(createdAt, kind, tags, message, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), message, onReady)
} }
} }
@@ -122,16 +122,16 @@ class LnZapRequestEvent(
) { ) {
if (zapType == LnZapEvent.ZapType.NONZAP) return if (zapType == LnZapEvent.ZapType.NONZAP) return
var tags = listOf( var tags = arrayOf(
listOf("p", userHex), arrayOf("p", userHex),
listOf("relays") + relays arrayOf("relays") + relays
) )
if (zapType == LnZapEvent.ZapType.ANONYMOUS) { if (zapType == LnZapEvent.ZapType.ANONYMOUS) {
tags = tags + listOf(listOf("anon", "")) tags += arrayOf(arrayOf("anon", ""))
NostrSignerInternal(KeyPair()).sign(createdAt, kind, tags, message, onReady) NostrSignerInternal(KeyPair()).sign(createdAt, kind, tags, message, onReady)
} else if (zapType == LnZapEvent.ZapType.PRIVATE) { } else if (zapType == LnZapEvent.ZapType.PRIVATE) {
tags = tags + listOf(listOf("anon", "")) tags += arrayOf(arrayOf("anon", ""))
signer.sign(createdAt, kind, tags, message, onReady) signer.sign(createdAt, kind, tags, message, onReady)
} else { } else {
signer.sign(createdAt, kind, tags, message, onReady) signer.sign(createdAt, kind, tags, message, onReady)
@@ -13,7 +13,7 @@ class LongTextNoteEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent { ) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig), AddressableEvent {
@@ -42,14 +42,14 @@ class LongTextNoteEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (LongTextNoteEvent) -> Unit onReady: (LongTextNoteEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -123,7 +123,7 @@ class MetadataEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -157,13 +157,13 @@ class MetadataEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (MetadataEvent) -> Unit onReady: (MetadataEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
identities.forEach { identities.forEach {
tags.add(listOf("i", it.platformIdentity(), it.proof)) tags.add(arrayOf("i", it.platformIdentity(), it.proof))
} }
signer.sign(createdAt, kind, tags, contactMetaData, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), contactMetaData, onReady)
} }
} }
} }
@@ -18,7 +18,7 @@ class MuteListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -61,10 +61,10 @@ class MuteListEvent(
fun createListWithTag(key: String, tag: String, isPrivate: Boolean, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (MuteListEvent) -> Unit) { fun createListWithTag(key: String, tag: String, isPrivate: Boolean, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (MuteListEvent) -> Unit) {
if (isPrivate) { if (isPrivate) {
encryptTags(listOf(listOf(key, tag)), signer) { encryptedTags -> encryptTags(arrayOf(arrayOf(key, tag)), signer) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = emptyList(), tags = emptyArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -73,7 +73,7 @@ class MuteListEvent(
} else { } else {
create( create(
content = "", content = "",
tags = listOf(listOf(key, tag)), tags = arrayOf(arrayOf(key, tag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -95,7 +95,7 @@ class MuteListEvent(
encryptTags( encryptTags(
privateTags = privateTags.plus( privateTags = privateTags.plus(
listPubKeyHex.map { listPubKeyHex.map {
listOf("p", it) arrayOf("p", it)
} }
), ),
signer = signer signer = signer
@@ -114,7 +114,7 @@ class MuteListEvent(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus( tags = earlierVersion.tags.plus(
listPubKeyHex.map { listPubKeyHex.map {
listOf("p", it) arrayOf("p", it)
} }
), ),
signer = signer, signer = signer,
@@ -138,7 +138,7 @@ class MuteListEvent(
if (isPrivate) { if (isPrivate) {
earlierVersion.privateTagsOrEmpty(signer) { privateTags -> earlierVersion.privateTagsOrEmpty(signer) { privateTags ->
encryptTags( encryptTags(
privateTags = privateTags.plus(element = listOf(key, tag)), privateTags = privateTags.plus(element = arrayOf(key, tag)),
signer = signer signer = signer
) { encryptedTags -> ) { encryptedTags ->
create( create(
@@ -153,7 +153,7 @@ class MuteListEvent(
} else { } else {
create( create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf(key, tag)), tags = earlierVersion.tags.plus(element = arrayOf(key, tag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -177,12 +177,12 @@ class MuteListEvent(
if (isPrivate) { if (isPrivate) {
earlierVersion.privateTagsOrEmpty(signer) { privateTags -> earlierVersion.privateTagsOrEmpty(signer) { privateTags ->
encryptTags( encryptTags(
privateTags = privateTags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, privateTags = privateTags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer signer = signer
) { encryptedTags -> ) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -192,7 +192,7 @@ class MuteListEvent(
} else { } else {
create( create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -204,7 +204,7 @@ class MuteListEvent(
fun create( fun create(
content: String, content: String,
tags: List<List<String>>, tags: Array<Array<String>>,
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (MuteListEvent) -> Unit onReady: (MuteListEvent) -> Unit
@@ -13,7 +13,7 @@ class NNSEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -29,7 +29,7 @@ class NNSEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (NNSEvent) -> Unit onReady: (NNSEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = emptyArray<Array<String>>()
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags, "", onReady)
} }
} }
@@ -15,7 +15,7 @@ class PeopleListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : GeneralListEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -94,10 +94,10 @@ class PeopleListEvent(
fun createListWithTag(name: String, key: String, tag: String, isPrivate: Boolean, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (PeopleListEvent) -> Unit) { fun createListWithTag(name: String, key: String, tag: String, isPrivate: Boolean, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (PeopleListEvent) -> Unit) {
if (isPrivate) { if (isPrivate) {
encryptTags(listOf(listOf(key, tag)), signer) { encryptedTags -> encryptTags(arrayOf(arrayOf(key, tag)), signer) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = listOf(listOf("d", name)), tags = arrayOf(arrayOf("d", name)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -106,7 +106,7 @@ class PeopleListEvent(
} else { } else {
create( create(
content = "", content = "",
tags = listOf(listOf("d", name), listOf(key, tag)), tags = arrayOf(arrayOf("d", name), arrayOf(key, tag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -128,7 +128,7 @@ class PeopleListEvent(
encryptTags( encryptTags(
privateTags = privateTags.plus( privateTags = privateTags.plus(
listPubKeyHex.map { listPubKeyHex.map {
listOf("p", it) arrayOf("p", it)
} }
), ),
signer = signer signer = signer
@@ -147,7 +147,7 @@ class PeopleListEvent(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus( tags = earlierVersion.tags.plus(
listPubKeyHex.map { listPubKeyHex.map {
listOf("p", it) arrayOf("p", it)
} }
), ),
signer = signer, signer = signer,
@@ -171,7 +171,7 @@ class PeopleListEvent(
if (isPrivate) { if (isPrivate) {
earlierVersion.privateTagsOrEmpty(signer) { privateTags -> earlierVersion.privateTagsOrEmpty(signer) { privateTags ->
encryptTags( encryptTags(
privateTags = privateTags.plus(element = listOf(key, tag)), privateTags = privateTags.plus(element = arrayOf(key, tag)),
signer = signer signer = signer
) { encryptedTags -> ) { encryptedTags ->
create( create(
@@ -186,7 +186,7 @@ class PeopleListEvent(
} else { } else {
create( create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.plus(element = listOf(key, tag)), tags = earlierVersion.tags.plus(element = arrayOf(key, tag)),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -210,12 +210,12 @@ class PeopleListEvent(
if (isPrivate) { if (isPrivate) {
earlierVersion.privateTagsOrEmpty(signer) { privateTags -> earlierVersion.privateTagsOrEmpty(signer) { privateTags ->
encryptTags( encryptTags(
privateTags = privateTags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, privateTags = privateTags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer signer = signer
) { encryptedTags -> ) { encryptedTags ->
create( create(
content = encryptedTags, content = encryptedTags,
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -225,7 +225,7 @@ class PeopleListEvent(
} else { } else {
create( create(
content = earlierVersion.content, content = earlierVersion.content,
tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }, tags = earlierVersion.tags.filter { it.size > 1 && !(it[0] == key && it[1] == tag) }.toTypedArray(),
signer = signer, signer = signer,
createdAt = createdAt, createdAt = createdAt,
onReady = onReady onReady = onReady
@@ -237,7 +237,7 @@ class PeopleListEvent(
fun create( fun create(
content: String, content: String,
tags: List<List<String>>, tags: Array<Array<String>>,
signer: NostrSigner, signer: NostrSigner,
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (PeopleListEvent) -> Unit onReady: (PeopleListEvent) -> Unit
@@ -13,7 +13,7 @@ class PinListEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -29,12 +29,12 @@ class PinListEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (PinListEvent) -> Unit onReady: (PinListEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
pins.forEach { pins.forEach {
tags.add(listOf("pin", it)) tags.add(arrayOf("pin", it))
} }
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags.toTypedArray(), "", onReady)
} }
} }
} }
@@ -19,7 +19,7 @@ class PollNoteEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
// ots: String?, TODO implement OTS: https://github.com/opentimestamps/java-opentimestamps // ots: String?, TODO implement OTS: https://github.com/opentimestamps/java-opentimestamps
content: String, content: String,
sig: HexKey sig: HexKey
@@ -62,45 +62,45 @@ class PollNoteEvent(
geohash: String? = null, geohash: String? = null,
onReady: (PollNoteEvent) -> Unit onReady: (PollNoteEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
addresses?.forEach { addresses?.forEach {
tags.add(listOf("a", it.toTag())) tags.add(arrayOf("a", it.toTag()))
} }
pollOptions.forEach { poll_op -> pollOptions.forEach { poll_op ->
tags.add(listOf(POLL_OPTION, poll_op.key.toString(), poll_op.value)) tags.add(arrayOf(POLL_OPTION, poll_op.key.toString(), poll_op.value))
} }
valueMaximum?.let { valueMaximum?.let {
tags.add(listOf(VALUE_MAXIMUM, valueMaximum.toString())) tags.add(arrayOf(VALUE_MAXIMUM, valueMaximum.toString()))
} }
valueMinimum?.let { valueMinimum?.let {
tags.add(listOf(VALUE_MINIMUM, valueMinimum.toString())) tags.add(arrayOf(VALUE_MINIMUM, valueMinimum.toString()))
} }
consensusThreshold?.let { consensusThreshold?.let {
tags.add(listOf(CONSENSUS_THRESHOLD, consensusThreshold.toString())) tags.add(arrayOf(CONSENSUS_THRESHOLD, consensusThreshold.toString()))
} }
closedAt?.let { closedAt?.let {
tags.add(listOf(CLOSED_AT, closedAt.toString())) tags.add(arrayOf(CLOSED_AT, closedAt.toString()))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -19,7 +19,7 @@ class PrivateDmEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable { ) : Event(id, pubKey, createdAt, kind, tags, content, sig), ChatroomKeyable {
@@ -109,38 +109,38 @@ class PrivateDmEvent(
onReady: (PrivateDmEvent) -> Unit onReady: (PrivateDmEvent) -> Unit
) { ) {
val message = if (advertiseNip18) { nip18Advertisement } else { "" } + msg val message = if (advertiseNip18) { nip18Advertisement } else { "" } + msg
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
publishedRecipientPubKey?.let { publishedRecipientPubKey?.let {
tags.add(listOf("p", publishedRecipientPubKey)) tags.add(arrayOf("p", publishedRecipientPubKey))
} }
replyTos?.forEach { replyTos?.forEach {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
mentions?.forEach { mentions?.forEach {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
signer.nip04Encrypt(message, recipientPubKey) { content -> signer.nip04Encrypt(message, recipientPubKey) { content ->
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
} }
} }
} }
fun geohashMipMap(geohash: String): List<List<String>> { fun geohashMipMap(geohash: String): Array<Array<String>> {
return geohash.indices.asSequence().map { return geohash.indices.asSequence().map {
listOf("g", geohash.substring(0, it+1)) arrayOf("g", geohash.substring(0, it+1))
}.toList().reversed() }.toList().reversed().toTypedArray()
} }
@@ -13,7 +13,7 @@ class ReactionEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -33,25 +33,25 @@ class ReactionEvent(
} }
fun create(content: String, originalNote: EventInterface, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (ReactionEvent) -> Unit) { fun create(content: String, originalNote: EventInterface, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (ReactionEvent) -> Unit) {
var tags = listOf(listOf("e", originalNote.id()), listOf("p", originalNote.pubKey())) var tags = listOf(arrayOf("e", originalNote.id()), arrayOf("p", originalNote.pubKey()))
if (originalNote is AddressableEvent) { if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag())) tags = tags + listOf(arrayOf("a", originalNote.address().toTag()))
} }
return signer.sign(createdAt, kind, tags, content, onReady) return signer.sign(createdAt, kind, tags.toTypedArray(), content, onReady)
} }
fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (ReactionEvent) -> Unit) { fun create(emojiUrl: EmojiUrl, originalNote: EventInterface, signer: NostrSigner, createdAt: Long = TimeUtils.now(), onReady: (ReactionEvent) -> Unit) {
val content = ":${emojiUrl.code}:" val content = ":${emojiUrl.code}:"
var tags = listOf( var tags = arrayOf(
listOf("e", originalNote.id()), arrayOf("e", originalNote.id()),
listOf("p", originalNote.pubKey()), arrayOf("p", originalNote.pubKey()),
listOf("emoji", emojiUrl.code, emojiUrl.url) arrayOf("emoji", emojiUrl.code, emojiUrl.url)
) )
if (originalNote is AddressableEvent) { if (originalNote is AddressableEvent) {
tags = tags + listOf(listOf("a", originalNote.address().toTag())) tags += arrayOf(arrayOf("a", originalNote.address().toTag()))
} }
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
@@ -13,7 +13,7 @@ class RecommendRelayEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -30,8 +30,7 @@ class RecommendRelayEvent(
onReady: (RecommendRelayEvent) -> Unit onReady: (RecommendRelayEvent) -> Unit
) { ) {
val content = relay.toString() val content = relay.toString()
val tags = listOf<List<String>>() signer.sign(createdAt, kind, emptyArray(), content, onReady)
signer.sign(createdAt, kind, tags, content, onReady)
} }
} }
} }
@@ -12,7 +12,7 @@ class RelayAuthEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -30,9 +30,9 @@ class RelayAuthEvent(
onReady: (RelayAuthEvent) -> Unit onReady: (RelayAuthEvent) -> Unit
) { ) {
val content = "" val content = ""
val tags = listOf( val tags = arrayOf(
listOf("relay", relay), arrayOf("relay", relay),
listOf("challenge", challenge) arrayOf("challenge", challenge)
) )
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
} }
@@ -13,7 +13,7 @@ class RelaySetEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -29,12 +29,12 @@ class RelaySetEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (RelaySetEvent) -> Unit onReady: (RelaySetEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
relays.forEach { relays.forEach {
tags.add(listOf("r", it)) tags.add(arrayOf("r", it))
} }
signer.sign(createdAt, kind, tags, "", onReady) signer.sign(createdAt, kind, tags.toTypedArray(), "", onReady)
} }
} }
} }
@@ -17,7 +17,7 @@ class ReportEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -63,13 +63,13 @@ class ReportEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (ReportEvent) -> Unit onReady: (ReportEvent) -> Unit
) { ) {
val reportPostTag = listOf("e", reportedPost.id(), type.name.lowercase()) val reportPostTag = arrayOf("e", reportedPost.id(), type.name.lowercase())
val reportAuthorTag = listOf("p", reportedPost.pubKey(), type.name.lowercase()) val reportAuthorTag = arrayOf("p", reportedPost.pubKey(), type.name.lowercase())
var tags: List<List<String>> = listOf(reportPostTag, reportAuthorTag) var tags: Array<Array<String>> = arrayOf(reportPostTag, reportAuthorTag)
if (reportedPost is AddressableEvent) { if (reportedPost is AddressableEvent) {
tags = tags + listOf(listOf("a", reportedPost.address().toTag())) tags = tags + listOf(arrayOf("a", reportedPost.address().toTag()))
} }
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
@@ -84,9 +84,9 @@ class ReportEvent(
) { ) {
val content = "" val content = ""
val reportAuthorTag = listOf("p", reportedUser, type.name.lowercase()) val reportAuthorTag = arrayOf("p", reportedUser, type.name.lowercase())
val tags: List<List<String>> = listOf(reportAuthorTag) val tags: Array<Array<String>> = arrayOf(reportAuthorTag)
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
} }
} }
@@ -13,7 +13,7 @@ class RepostEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : Event(id, pubKey, createdAt, kind, tags, content, sig) { ) : Event(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -38,13 +38,13 @@ class RepostEvent(
) { ) {
val content = boostedPost.toJson() val content = boostedPost.toJson()
val replyToPost = listOf("e", boostedPost.id()) val replyToPost = arrayOf("e", boostedPost.id())
val replyToAuthor = listOf("p", boostedPost.pubKey()) val replyToAuthor = arrayOf("p", boostedPost.pubKey())
var tags: List<List<String>> = listOf(replyToPost, replyToAuthor) var tags: Array<Array<String>> = arrayOf(replyToPost, replyToAuthor)
if (boostedPost is AddressableEvent) { if (boostedPost is AddressableEvent) {
tags = tags + listOf(listOf("a", boostedPost.address().toTag())) tags = tags + listOf(arrayOf("a", boostedPost.address().toTag()))
} }
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, tags, content, onReady)
@@ -19,7 +19,7 @@ class SealedGossipEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
): WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig) { ): WrappedEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -85,10 +85,9 @@ class SealedGossipEvent(
onReady: (SealedGossipEvent) -> Unit onReady: (SealedGossipEvent) -> Unit
) { ) {
val msg = Gossip.toJson(gossip) val msg = Gossip.toJson(gossip)
val tags = listOf<List<String>>()
signer.nip44Encrypt(msg, encryptTo) { content -> signer.nip44Encrypt(msg, encryptTo) { content ->
signer.sign(createdAt, kind, tags, content, onReady) signer.sign(createdAt, kind, emptyArray(), content, onReady)
} }
} }
} }
@@ -101,14 +100,14 @@ class Gossip(
@JsonProperty("created_at") @JsonProperty("created_at")
val createdAt: Long?, val createdAt: Long?,
val kind: Int?, val kind: Int?,
val tags: List<List<String>>?, val tags: Array<Array<String>>?,
val content: String? val content: String?
) { ) {
fun mergeWith(event: SealedGossipEvent): Event { fun mergeWith(event: SealedGossipEvent): Event {
val newPubKey = pubKey?.ifBlank { null } ?: event.pubKey val newPubKey = pubKey?.ifBlank { null } ?: event.pubKey
val newCreatedAt = if (createdAt != null && createdAt > 1000) createdAt else event.createdAt val newCreatedAt = if (createdAt != null && createdAt > 1000) createdAt else event.createdAt
val newKind = kind ?: -1 val newKind = kind ?: -1
val newTags = (tags ?: emptyList()).plus(event.tags) val newTags = (tags ?: emptyArray()).plus(event.tags)
val newContent = content ?: "" val newContent = content ?: ""
val newID = id?.ifBlank { null } ?: Event.generateId(newPubKey, newCreatedAt, newKind, newTags, newContent).toHexKey() val newID = id?.ifBlank { null } ?: Event.generateId(newPubKey, newCreatedAt, newKind, newTags, newContent).toHexKey()
val sig = "" val sig = ""
@@ -14,7 +14,7 @@ class StatusEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseAddressableEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -30,12 +30,12 @@ class StatusEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (StatusEvent) -> Unit onReady: (StatusEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
tags.add(listOf("d", type)) tags.add(arrayOf("d", type))
expiration?.let { tags.add(listOf("expiration", it.toString())) } expiration?.let { tags.add(arrayOf("expiration", it.toString())) }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
fun update( fun update(
@@ -57,7 +57,7 @@ class StatusEvent(
) { ) {
val msg = "" val msg = ""
val tags = event.tags.filter { it.size > 1 && it[0] == "d" } val tags = event.tags.filter { it.size > 1 && it[0] == "d" }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -16,7 +16,7 @@ class TextNoteEvent(
id: HexKey, id: HexKey,
pubKey: HexKey, pubKey: HexKey,
createdAt: Long, createdAt: Long,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
sig: HexKey sig: HexKey
) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) { ) : BaseTextNoteEvent(id, pubKey, createdAt, kind, tags, content, sig) {
@@ -43,61 +43,61 @@ class TextNoteEvent(
createdAt: Long = TimeUtils.now(), createdAt: Long = TimeUtils.now(),
onReady: (TextNoteEvent) -> Unit onReady: (TextNoteEvent) -> Unit
) { ) {
val tags = mutableListOf<List<String>>() val tags = mutableListOf<Array<String>>()
replyTos?.forEach { replyTos?.forEach {
if (it == root) { if (it == root) {
tags.add(listOf("e", it, "", "root")) tags.add(arrayOf("e", it, "", "root"))
} else if (it == replyingTo) { } else if (it == replyingTo) {
tags.add(listOf("e", it, "", "reply")) tags.add(arrayOf("e", it, "", "reply"))
} else if (it in directMentions) { } else if (it in directMentions) {
tags.add(listOf("e", it, "", "mention")) tags.add(arrayOf("e", it, "", "mention"))
} else { } else {
tags.add(listOf("e", it)) tags.add(arrayOf("e", it))
} }
} }
mentions?.forEach { mentions?.forEach {
if (it in directMentions) { if (it in directMentions) {
tags.add(listOf("p", it, "", "mention")) tags.add(arrayOf("p", it, "", "mention"))
} else { } else {
tags.add(listOf("p", it)) tags.add(arrayOf("p", it))
} }
} }
addresses?.forEach { addresses?.forEach {
val aTag = it.toTag() val aTag = it.toTag()
if (aTag == root) { if (aTag == root) {
tags.add(listOf("a", aTag, "", "root")) tags.add(arrayOf("a", aTag, "", "root"))
} else if (aTag == replyingTo) { } else if (aTag == replyingTo) {
tags.add(listOf("a", aTag, "", "reply")) tags.add(arrayOf("a", aTag, "", "reply"))
} else if (aTag in directMentions) { } else if (aTag in directMentions) {
tags.add(listOf("a", aTag, "", "mention")) tags.add(arrayOf("a", aTag, "", "mention"))
} else { } else {
tags.add(listOf("a", aTag)) tags.add(arrayOf("a", aTag))
} }
} }
findHashtags(msg).forEach { findHashtags(msg).forEach {
tags.add(listOf("t", it)) tags.add(arrayOf("t", it))
tags.add(listOf("t", it.lowercase())) tags.add(arrayOf("t", it.lowercase()))
} }
extraTags?.forEach { extraTags?.forEach {
tags.add(listOf("t", it)) tags.add(arrayOf("t", it))
} }
zapReceiver?.forEach { zapReceiver?.forEach {
tags.add(listOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString())) tags.add(arrayOf("zap", it.lnAddressOrPubKeyHex, it.relay ?: "", it.weight.toString()))
} }
findURLs(msg).forEach { findURLs(msg).forEach {
tags.add(listOf("r", it)) tags.add(arrayOf("r", it))
} }
if (markAsSensitive) { if (markAsSensitive) {
tags.add(listOf("content-warning", "")) tags.add(arrayOf("content-warning", ""))
} }
zapRaiserAmount?.let { zapRaiserAmount?.let {
tags.add(listOf("zapraiser", "$it")) tags.add(arrayOf("zapraiser", "$it"))
} }
geohash?.let { geohash?.let {
tags.addAll(geohashMipMap(it)) tags.addAll(geohashMipMap(it))
} }
signer.sign(createdAt, kind, tags, msg, onReady) signer.sign(createdAt, kind, tags.toTypedArray(), msg, onReady)
} }
} }
} }
@@ -11,7 +11,7 @@ import kotlinx.coroutines.withContext
abstract class NostrSigner(val pubKey: HexKey) { abstract class NostrSigner(val pubKey: HexKey) {
abstract fun <T: Event> sign(createdAt: Long, kind: Int, tags: List<List<String>>, content: String, onReady: (T) -> Unit) abstract fun <T: Event> sign(createdAt: Long, kind: Int, tags: Array<Array<String>>, content: String, onReady: (T) -> Unit)
abstract fun nip04Encrypt(decryptedContent: String, toPublicKey: HexKey, onReady: (String)-> Unit) abstract fun nip04Encrypt(decryptedContent: String, toPublicKey: HexKey, onReady: (String)-> Unit)
abstract fun nip04Decrypt(encryptedContent: String, fromPublicKey: HexKey, onReady: (String)-> Unit) abstract fun nip04Decrypt(encryptedContent: String, fromPublicKey: HexKey, onReady: (String)-> Unit)
@@ -17,7 +17,7 @@ class NostrSignerExternal(
override fun <T: Event> sign( override fun <T: Event> sign(
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
onReady: (T) -> Unit onReady: (T) -> Unit
) { ) {
@@ -21,7 +21,7 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
override fun <T: Event> sign( override fun <T: Event> sign(
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
onReady: (T)-> Unit onReady: (T)-> Unit
) { ) {
@@ -37,7 +37,7 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
fun isUnsignedPrivateEvent( fun isUnsignedPrivateEvent(
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
): Boolean { ): Boolean {
return kind == LnZapRequestEvent.kind && tags.any { t -> t.size > 1 && t[0] == "anon" && t[1].isBlank() } return kind == LnZapRequestEvent.kind && tags.any { t -> t.size > 1 && t[0] == "anon" && t[1].isBlank() }
} }
@@ -45,7 +45,7 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
fun <T: Event> signNormal( fun <T: Event> signNormal(
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
onReady: (T)-> Unit onReady: (T)-> Unit
) { ) {
@@ -123,7 +123,7 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
private fun <T> signPrivateZap( private fun <T> signPrivateZap(
createdAt: Long, createdAt: Long,
kind: Int, kind: Int,
tags: List<List<String>>, tags: Array<Array<String>>,
content: String, content: String,
onReady: (T)-> Unit onReady: (T)-> Unit
) { ) {
@@ -138,7 +138,7 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
val encryptionPrivateKey = val encryptionPrivateKey =
LnZapRequestEvent.createEncryptionPrivateKey(keyPair.privKey.toHexKey(), idToGeneratePrivateKey, createdAt) LnZapRequestEvent.createEncryptionPrivateKey(keyPair.privKey.toHexKey(), idToGeneratePrivateKey, createdAt)
val fullTagsNoAnon = tags.filter { t -> t.getOrNull(0) != "anon" } val fullTagsNoAnon = tags.filter { t -> t.getOrNull(0) != "anon" }.toTypedArray()
LnZapPrivateEvent.create(this, fullTagsNoAnon, content) { LnZapPrivateEvent.create(this, fullTagsNoAnon, content) {
val noteJson = it.toJson() val noteJson = it.toJson()
@@ -148,10 +148,10 @@ class NostrSignerInternal(val keyPair: KeyPair): NostrSigner(keyPair.pubKey.toHe
userHex.hexToByteArray() userHex.hexToByteArray()
) )
val newTags = tags.filter { t -> t.getOrNull(0) != "anon" } + listOf(listOf("anon", encryptedContent)) val newTags = tags.filter { t -> t.getOrNull(0) != "anon" } + listOf(arrayOf("anon", encryptedContent))
val newContent = "" val newContent = ""
NostrSignerInternal(KeyPair(encryptionPrivateKey)).signNormal(createdAt, kind, newTags, newContent, onReady) NostrSignerInternal(KeyPair(encryptionPrivateKey)).signNormal(createdAt, kind, newTags.toTypedArray(), newContent, onReady)
} }
} }