mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-10 08:27:04 +00:00
refactor(clink): clink_offer metadata via ClinkOfferTag + DSL builder
Brings the kind-0 clink_offer field in line with the sibling fields' structure instead of a raw string constant written to content only: - New ClinkOfferTag (TAG_NAME/assemble/parse) under nip01Core/metadata/tags. - clinkOffer() TagArrayBuilder DSL extension in TagArrayBuilderExt. - MetadataEvent uses ClinkOfferTag.TAG_NAME and dual-writes it as a kind-0 tag in updateOrDeleteTagNames (NIP-1770 pattern), like lud16/nip05; drops the ad-hoc CLINK_OFFER_PROPERTY constant. UpdateMetadataTest now also asserts the tag is emitted. quartz tests pass.
This commit is contained in:
+3
-4
@@ -28,6 +28,7 @@ import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.core.builder
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.AboutTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.BannerTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.ClinkOfferTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.DisplayNameTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.Lud06Tag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.Lud16Tag
|
||||
@@ -88,9 +89,6 @@ class MetadataEvent(
|
||||
const val KIND = 0
|
||||
const val FIXED_D_TAG = ""
|
||||
|
||||
// CLINK Offers discovery key in kind-0 content (mirrors the NIP-05 `clink_offer` key).
|
||||
const val CLINK_OFFER_PROPERTY = "clink_offer"
|
||||
|
||||
fun createAddress(pubKey: HexKey): Address = Address(KIND, pubKey, FIXED_D_TAG)
|
||||
|
||||
fun createAddressATag(pubKey: HexKey): ATag = ATag(KIND, pubKey, FIXED_D_TAG, null)
|
||||
@@ -252,7 +250,7 @@ class MetadataEvent(
|
||||
nip05?.let { addIfNotBlank(currentMetadata, Nip05Tag.TAG_NAME, it) }
|
||||
lnAddress?.let { addIfNotBlank(currentMetadata, Lud16Tag.TAG_NAME, it) }
|
||||
lnURL?.let { addIfNotBlank(currentMetadata, Lud06Tag.TAG_NAME, it) }
|
||||
clinkOffer?.let { addIfNotBlank(currentMetadata, CLINK_OFFER_PROPERTY, it) }
|
||||
clinkOffer?.let { addIfNotBlank(currentMetadata, ClinkOfferTag.TAG_NAME, it) }
|
||||
}
|
||||
|
||||
// For https://github.com/nostr-protocol/nips/pull/1770
|
||||
@@ -267,6 +265,7 @@ class MetadataEvent(
|
||||
currentMetadata[Nip05Tag.TAG_NAME]?.let { nip05(it.text) } ?: run { remove(Nip05Tag.TAG_NAME) }
|
||||
currentMetadata[Lud16Tag.TAG_NAME]?.let { lud16(it.text) } ?: run { remove(Lud16Tag.TAG_NAME) }
|
||||
currentMetadata[Lud06Tag.TAG_NAME]?.let { lud06(it.text) } ?: run { remove(Lud06Tag.TAG_NAME) }
|
||||
currentMetadata[ClinkOfferTag.TAG_NAME]?.let { clinkOffer(it.text) } ?: run { remove(ClinkOfferTag.TAG_NAME) }
|
||||
}
|
||||
|
||||
private fun addIfNotBlank(
|
||||
|
||||
+3
@@ -23,6 +23,7 @@ package com.vitorpamplona.quartz.nip01Core.metadata
|
||||
import com.vitorpamplona.quartz.nip01Core.core.TagArrayBuilder
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.AboutTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.BannerTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.ClinkOfferTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.DisplayNameTag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.Lud06Tag
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.tags.Lud16Tag
|
||||
@@ -51,3 +52,5 @@ fun TagArrayBuilder<MetadataEvent>.lud06(lud06: String) = addUnique(Lud06Tag.ass
|
||||
fun TagArrayBuilder<MetadataEvent>.banner(banner: String) = addUnique(BannerTag.assemble(banner))
|
||||
|
||||
fun TagArrayBuilder<MetadataEvent>.pronouns(pronouns: String) = addUnique(PronounsTag.assemble(pronouns))
|
||||
|
||||
fun TagArrayBuilder<MetadataEvent>.clinkOffer(offer: String) = addUnique(ClinkOfferTag.assemble(offer))
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip01Core.metadata.tags
|
||||
|
||||
import com.vitorpamplona.quartz.utils.ensure
|
||||
|
||||
/** CLINK Offers pointer (`noffer1…`) advertised in a kind-0 profile, mirroring the NIP-05 `clink_offer` key. */
|
||||
class ClinkOfferTag {
|
||||
companion object {
|
||||
const val TAG_NAME = "clink_offer"
|
||||
|
||||
fun parse(tag: Array<String>): String? {
|
||||
ensure(tag.size > 1) { return null }
|
||||
ensure(tag[0] == TAG_NAME) { return null }
|
||||
ensure(tag[1].isNotEmpty()) { return null }
|
||||
return tag[1]
|
||||
}
|
||||
|
||||
fun assemble(offer: String) = arrayOf(TAG_NAME, offer)
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -205,7 +205,10 @@ class UpdateMetadataTest {
|
||||
// written into kind-0 content under the spec's `clink_offer` key
|
||||
assertEquals(true, event.content.contains("\"clink_offer\":\"$noffer\""))
|
||||
|
||||
// and parses back out
|
||||
// and dual-written as a kind-0 tag (NIP-1770 pattern), like the other fields
|
||||
assertContentEquals(arrayOf("clink_offer", noffer), event.tags.firstOrNull { it.firstOrNull() == "clink_offer" })
|
||||
|
||||
// and parses back out of the content
|
||||
val metadata = event.contactMetaData()
|
||||
assertNotNull(metadata)
|
||||
assertEquals(noffer, metadata.clinkOffer)
|
||||
|
||||
Reference in New Issue
Block a user