mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-10-10 00:22:43 +02:00
Adds basic support for NIP-46 events.
This commit is contained in:
@@ -0,0 +1,254 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.vitorpamplona.quartz.crypto.KeyPair
|
||||||
|
import com.vitorpamplona.quartz.events.ContactListEvent
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import com.vitorpamplona.quartz.signers.NostrSignerInternal
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import org.junit.Ignore
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
internal class Nip46Test {
|
||||||
|
val remoteKey = NostrSignerInternal(KeyPair())
|
||||||
|
val signer = NostrSignerInternal(KeyPair())
|
||||||
|
val peer = NostrSignerInternal(KeyPair())
|
||||||
|
|
||||||
|
val dummyEvent =
|
||||||
|
Event(
|
||||||
|
id = "",
|
||||||
|
pubKey = "",
|
||||||
|
createdAt = TimeUtils.now(),
|
||||||
|
kind = 1,
|
||||||
|
tags = emptyArray(),
|
||||||
|
content = "test",
|
||||||
|
sig = "",
|
||||||
|
)
|
||||||
|
|
||||||
|
fun <T : BunkerMessage> encodeDecodeEvent(req: T): T {
|
||||||
|
var countDownLatch = CountDownLatch(1)
|
||||||
|
var eventStr: String? = null
|
||||||
|
|
||||||
|
NostrConnectEvent.create(req, remoteKey.pubKey, signer) {
|
||||||
|
eventStr = it.toJson()
|
||||||
|
countDownLatch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownLatch.await()
|
||||||
|
|
||||||
|
countDownLatch = CountDownLatch(1)
|
||||||
|
var innerMessage: T? = null
|
||||||
|
|
||||||
|
(Event.fromJson(eventStr!!) as NostrConnectEvent).plainContent(signer) {
|
||||||
|
innerMessage = it as T
|
||||||
|
countDownLatch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
countDownLatch.await()
|
||||||
|
|
||||||
|
return innerMessage!!
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun signEncoder() {
|
||||||
|
val expected = BunkerRequestSign(event = dummyEvent)
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(BunkerRequestSign.METHOD_NAME, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(dummyEvent.id, actual.event.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun connectEncoder() {
|
||||||
|
val expected = BunkerRequestConnect(remoteKey = remoteKey.pubKey)
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun pingEncoder() {
|
||||||
|
val expected = BunkerRequestPing()
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getPubkeyEncoder() {
|
||||||
|
val expected = BunkerRequestGetPublicKey()
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getRelaysEncoder() {
|
||||||
|
val expected = BunkerRequestGetRelays()
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNip04Encrypt() {
|
||||||
|
val expected = BunkerRequestNip04Encrypt(pubKey = peer.pubKey, message = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.pubKey, actual.pubKey)
|
||||||
|
assertEquals(expected.message, actual.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNip44Encrypt() {
|
||||||
|
val expected = BunkerRequestNip44Encrypt(pubKey = peer.pubKey, message = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.pubKey, actual.pubKey)
|
||||||
|
assertEquals(expected.message, actual.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNip04Decrypt() {
|
||||||
|
val expected = BunkerRequestNip04Decrypt(pubKey = peer.pubKey, ciphertext = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.pubKey, actual.pubKey)
|
||||||
|
assertEquals(expected.ciphertext, actual.ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testNip44Decrypt() {
|
||||||
|
val expected = BunkerRequestNip44Decrypt(pubKey = peer.pubKey, ciphertext = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.method, actual.method)
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.pubKey, actual.pubKey)
|
||||||
|
assertEquals(expected.ciphertext, actual.ciphertext)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responses
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAckResponse() {
|
||||||
|
val expected = BunkerResponseAck()
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPongResponse() {
|
||||||
|
val expected = BunkerResponsePong()
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testErrorResponse() {
|
||||||
|
val expected = BunkerResponseError(error = "Error")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testEventResponse() {
|
||||||
|
val expected = BunkerResponseEvent(event = dummyEvent)
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
assertEquals(dummyEvent.id, actual.event.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testPubkeyResponse() {
|
||||||
|
val expected = BunkerResponsePublicKey(pubkey = peer.pubKey)
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
assertEquals(expected.pubkey, actual.pubkey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testRelaysResponse() {
|
||||||
|
val expected = BunkerResponseGetRelays(relays = mapOf("url" to ContactListEvent.ReadWrite(true, false)))
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
assertEquals(expected.relays["url"], actual.relays["url"])
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore("Impossible to recreate the class since there are no hints on the json")
|
||||||
|
fun testDecryptResponse() {
|
||||||
|
val expected = BunkerResponseDecrypt(plaintext = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
assertEquals(expected.plaintext, actual.plaintext)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Ignore("Impossible to recreate the class since there are no hints on the json")
|
||||||
|
fun testEncryptResponse() {
|
||||||
|
val expected = BunkerResponseEncrypt(ciphertext = "Test")
|
||||||
|
val actual = encodeDecodeEvent(expected)
|
||||||
|
|
||||||
|
assertEquals(expected.id, actual.id)
|
||||||
|
assertEquals(expected.result, actual.result)
|
||||||
|
assertEquals(expected.error, actual.error)
|
||||||
|
assertEquals(expected.ciphertext, actual.ciphertext)
|
||||||
|
}
|
||||||
|
}
|
@@ -43,6 +43,9 @@ import com.vitorpamplona.quartz.encoders.Nip01Serializer
|
|||||||
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
||||||
import com.vitorpamplona.quartz.encoders.PoWRank
|
import com.vitorpamplona.quartz.encoders.PoWRank
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
|
import com.vitorpamplona.quartz.events.nip46.BunkerMessage
|
||||||
|
import com.vitorpamplona.quartz.events.nip46.BunkerRequest
|
||||||
|
import com.vitorpamplona.quartz.events.nip46.BunkerResponse
|
||||||
import com.vitorpamplona.quartz.signers.NostrSigner
|
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||||
@@ -435,7 +438,12 @@ open class Event(
|
|||||||
.addSerializer(Gossip::class.java, GossipSerializer())
|
.addSerializer(Gossip::class.java, GossipSerializer())
|
||||||
.addDeserializer(Gossip::class.java, GossipDeserializer())
|
.addDeserializer(Gossip::class.java, GossipDeserializer())
|
||||||
.addDeserializer(Response::class.java, ResponseDeserializer())
|
.addDeserializer(Response::class.java, ResponseDeserializer())
|
||||||
.addDeserializer(Request::class.java, RequestDeserializer()),
|
.addDeserializer(Request::class.java, RequestDeserializer())
|
||||||
|
.addDeserializer(BunkerMessage::class.java, BunkerMessage.BunkerMessageDeserializer())
|
||||||
|
.addSerializer(BunkerRequest::class.java, BunkerRequest.BunkerRequestSerializer())
|
||||||
|
.addDeserializer(BunkerRequest::class.java, BunkerRequest.BunkerRequestDeserializer())
|
||||||
|
.addSerializer(BunkerResponse::class.java, BunkerResponse.BunkerResponseSerializer())
|
||||||
|
.addDeserializer(BunkerResponse::class.java, BunkerResponse.BunkerResponseDeserializer()),
|
||||||
)
|
)
|
||||||
|
|
||||||
fun fromJson(jsonObject: JsonNode): Event =
|
fun fromJson(jsonObject: JsonNode): Event =
|
||||||
@@ -452,7 +460,7 @@ open class Event(
|
|||||||
sig = jsonObject.get("sig").asText(),
|
sig = jsonObject.get("sig").asText(),
|
||||||
)
|
)
|
||||||
|
|
||||||
private inline fun <reified R> JsonNode.toTypedArray(transform: (JsonNode) -> R): Array<R> = Array(size()) { transform(get(it)) }
|
inline fun <reified R> JsonNode.toTypedArray(transform: (JsonNode) -> R): Array<R> = 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)
|
||||||
|
|
||||||
|
@@ -21,6 +21,7 @@
|
|||||||
package com.vitorpamplona.quartz.events
|
package com.vitorpamplona.quartz.events
|
||||||
|
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
|
import com.vitorpamplona.quartz.events.nip46.NostrConnectEvent
|
||||||
|
|
||||||
class EventFactory {
|
class EventFactory {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -120,6 +121,7 @@ class EventFactory {
|
|||||||
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
MetadataEvent.KIND -> MetadataEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
MuteListEvent.KIND -> MuteListEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
NNSEvent.KIND -> NNSEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
NostrConnectEvent.KIND -> NostrConnectEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
NIP90StatusEvent.KIND -> NIP90StatusEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
NIP90ContentDiscoveryRequestEvent.KIND -> NIP90ContentDiscoveryRequestEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
NIP90ContentDiscoveryResponseEvent.KIND -> NIP90ContentDiscoveryResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
NIP90ContentDiscoveryResponseEvent.KIND -> NIP90ContentDiscoveryResponseEvent(id, pubKey, createdAt, tags, content, sig)
|
||||||
|
@@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
|
|
||||||
|
abstract class BunkerMessage {
|
||||||
|
abstract fun countMemory(): Long
|
||||||
|
|
||||||
|
class BunkerMessageDeserializer : StdDeserializer<BunkerMessage>(BunkerMessage::class.java) {
|
||||||
|
override fun deserialize(
|
||||||
|
jp: JsonParser,
|
||||||
|
ctxt: DeserializationContext,
|
||||||
|
): BunkerMessage {
|
||||||
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
|
val isRequest = jsonObject.has("method")
|
||||||
|
|
||||||
|
if (isRequest) {
|
||||||
|
return jp.codec.treeToValue(jsonObject, BunkerRequest::class.java)
|
||||||
|
} else {
|
||||||
|
return jp.codec.treeToValue(jsonObject, BunkerResponse::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||||
|
import com.vitorpamplona.quartz.events.Event.Companion.toTypedArray
|
||||||
|
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||||
|
import com.vitorpamplona.quartz.utils.pointerSizeInBytes
|
||||||
|
|
||||||
|
open class BunkerRequest(
|
||||||
|
val id: String,
|
||||||
|
val method: String,
|
||||||
|
val params: Array<String> = emptyArray(),
|
||||||
|
) : BunkerMessage() {
|
||||||
|
override fun countMemory(): Long =
|
||||||
|
3 * pointerSizeInBytes + // 3 fields, 4 bytes each reference (32bit)
|
||||||
|
id.bytesUsedInMemory() +
|
||||||
|
method.bytesUsedInMemory() +
|
||||||
|
params.sumOf { pointerSizeInBytes + it.bytesUsedInMemory() }
|
||||||
|
|
||||||
|
class BunkerRequestDeserializer : StdDeserializer<BunkerRequest>(BunkerRequest::class.java) {
|
||||||
|
override fun deserialize(
|
||||||
|
jp: JsonParser,
|
||||||
|
ctxt: DeserializationContext,
|
||||||
|
): BunkerRequest {
|
||||||
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
|
val id = jsonObject.get("id").asText().intern()
|
||||||
|
val method = jsonObject.get("method").asText().intern()
|
||||||
|
val params = jsonObject.get("params")?.toTypedArray { it.asText().intern() } ?: emptyArray()
|
||||||
|
|
||||||
|
return when (method) {
|
||||||
|
BunkerRequestConnect.METHOD_NAME -> BunkerRequestConnect.parse(id, params)
|
||||||
|
BunkerRequestGetPublicKey.METHOD_NAME -> BunkerRequestGetPublicKey.parse(id, params)
|
||||||
|
BunkerRequestGetRelays.METHOD_NAME -> BunkerRequestGetRelays.parse(id, params)
|
||||||
|
|
||||||
|
BunkerRequestNip04Decrypt.METHOD_NAME -> BunkerRequestNip04Decrypt.parse(id, params)
|
||||||
|
BunkerRequestNip04Encrypt.METHOD_NAME -> BunkerRequestNip04Encrypt.parse(id, params)
|
||||||
|
BunkerRequestNip44Decrypt.METHOD_NAME -> BunkerRequestNip44Decrypt.parse(id, params)
|
||||||
|
BunkerRequestNip44Encrypt.METHOD_NAME -> BunkerRequestNip44Encrypt.parse(id, params)
|
||||||
|
|
||||||
|
BunkerRequestPing.METHOD_NAME -> BunkerRequestPing.parse(id, params)
|
||||||
|
BunkerRequestSign.METHOD_NAME -> BunkerRequestSign.parse(id, params)
|
||||||
|
else -> BunkerRequest(id, method, params)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BunkerRequestSerializer : StdSerializer<BunkerRequest>(BunkerRequest::class.java) {
|
||||||
|
override fun serialize(
|
||||||
|
value: BunkerRequest,
|
||||||
|
gen: JsonGenerator,
|
||||||
|
provider: SerializerProvider,
|
||||||
|
) {
|
||||||
|
gen.writeStartObject()
|
||||||
|
gen.writeStringField("id", value.id)
|
||||||
|
gen.writeStringField("method", value.method)
|
||||||
|
gen.writeArrayFieldStart("params")
|
||||||
|
value.params.forEach {
|
||||||
|
gen.writeString(it)
|
||||||
|
}
|
||||||
|
gen.writeEndArray()
|
||||||
|
gen.writeEndObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,42 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestConnect(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val remoteKey: HexKey,
|
||||||
|
val secret: HexKey? = null,
|
||||||
|
val permissions: String? = null,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, listOfNotNull(remoteKey, secret, permissions).toTypedArray()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "connect"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestConnect = BunkerRequestConnect(id, params[0], params.getOrNull(1), params.getOrNull(2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T> Array<T>.getOrNull(index: Int): T? = if (index in 0..<size) get(index) else null
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestGetPublicKey(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, arrayOf()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "get_public_key"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestGetPublicKey = BunkerRequestGetPublicKey(id)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestGetRelays(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, arrayOf()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "get_relays"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestGetRelays = BunkerRequestGetRelays(id)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestNip04Decrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val pubKey: HexKey,
|
||||||
|
val ciphertext: String,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, listOfNotNull(pubKey, ciphertext).toTypedArray()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "nip04_decrypt"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestNip04Decrypt = BunkerRequestNip04Decrypt(id, params[0], params.get(1))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestNip04Encrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val pubKey: HexKey,
|
||||||
|
val message: String,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, listOfNotNull(pubKey, message).toTypedArray()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "nip04_encrypt"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestNip04Encrypt = BunkerRequestNip04Encrypt(id, params[0], params.get(1))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestNip44Decrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val pubKey: HexKey,
|
||||||
|
val ciphertext: String,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, listOfNotNull(pubKey, ciphertext).toTypedArray()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "nip44_decrypt"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestNip44Decrypt = BunkerRequestNip44Decrypt(id, params[0], params.get(1))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestNip44Encrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val pubKey: HexKey,
|
||||||
|
val message: String,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, listOfNotNull(pubKey, message).toTypedArray()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "nip44_encrypt"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestNip44Encrypt = BunkerRequestNip44Encrypt(id, params[0], params.get(1))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestPing(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, arrayOf()) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "ping"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestPing = BunkerRequestPing(id)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,38 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerRequestSign(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val event: Event,
|
||||||
|
) : BunkerRequest(id, METHOD_NAME, arrayOf(event.toJson())) {
|
||||||
|
companion object {
|
||||||
|
val METHOD_NAME = "sign_event"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
params: Array<String>,
|
||||||
|
): BunkerRequestSign = BunkerRequestSign(id, Event.fromJson(params[0]))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerator
|
||||||
|
import com.fasterxml.jackson.core.JsonParser
|
||||||
|
import com.fasterxml.jackson.databind.DeserializationContext
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode
|
||||||
|
import com.fasterxml.jackson.databind.SerializerProvider
|
||||||
|
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||||
|
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexValidator
|
||||||
|
import com.vitorpamplona.quartz.utils.bytesUsedInMemory
|
||||||
|
import com.vitorpamplona.quartz.utils.pointerSizeInBytes
|
||||||
|
|
||||||
|
open class BunkerResponse(
|
||||||
|
val id: String,
|
||||||
|
val result: String?,
|
||||||
|
val error: String?,
|
||||||
|
) : BunkerMessage() {
|
||||||
|
override fun countMemory(): Long =
|
||||||
|
3 * pointerSizeInBytes + // 3 fields, 4 bytes each reference (32bit)
|
||||||
|
id.bytesUsedInMemory() +
|
||||||
|
(result?.bytesUsedInMemory() ?: 0) +
|
||||||
|
(error?.bytesUsedInMemory() ?: 0)
|
||||||
|
|
||||||
|
class BunkerResponseDeserializer : StdDeserializer<BunkerResponse>(BunkerResponse::class.java) {
|
||||||
|
override fun deserialize(
|
||||||
|
jp: JsonParser,
|
||||||
|
ctxt: DeserializationContext,
|
||||||
|
): BunkerResponse {
|
||||||
|
val jsonObject: JsonNode = jp.codec.readTree(jp)
|
||||||
|
|
||||||
|
val id = jsonObject.get("id").asText().intern()
|
||||||
|
val result = jsonObject.get("result")?.asText()
|
||||||
|
val error = jsonObject.get("error")?.asText()
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
return BunkerResponseError.parse(id, result, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
when (result) {
|
||||||
|
BunkerResponseAck.RESULT -> return BunkerResponseAck.parse(id, result, error)
|
||||||
|
BunkerResponsePong.RESULT -> return BunkerResponsePong.parse(id, result, error)
|
||||||
|
else -> {
|
||||||
|
if (result.length == 64 && HexValidator.isHex(result)) {
|
||||||
|
return BunkerResponsePublicKey.parse(id, result)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.get(0) == '{') {
|
||||||
|
try {
|
||||||
|
return BunkerResponseEvent.parse(id, result)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return BunkerResponseGetRelays.parse(id, result)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BunkerResponse(id, result, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return BunkerResponse(id, result, error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BunkerResponseSerializer : StdSerializer<BunkerResponse>(BunkerResponse::class.java) {
|
||||||
|
override fun serialize(
|
||||||
|
value: BunkerResponse,
|
||||||
|
gen: JsonGenerator,
|
||||||
|
provider: SerializerProvider,
|
||||||
|
) {
|
||||||
|
gen.writeStartObject()
|
||||||
|
gen.writeStringField("id", value.id)
|
||||||
|
value.result?.let { gen.writeStringField("result", value.result) }
|
||||||
|
value.error?.let { gen.writeStringField("error", it) }
|
||||||
|
gen.writeEndObject()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseAck(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
) : BunkerResponse(id, RESULT, null) {
|
||||||
|
companion object {
|
||||||
|
val RESULT = "ack"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponseAck(id)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseDecrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val plaintext: String,
|
||||||
|
) : BunkerResponse(id, plaintext, null) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponseDecrypt(id, result)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseEncrypt(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val ciphertext: String,
|
||||||
|
) : BunkerResponse(id, ciphertext, null) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponseEncrypt(id, result)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,36 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseError(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
error: String,
|
||||||
|
) : BunkerResponse(id, null, error) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String? = null,
|
||||||
|
error: String,
|
||||||
|
) = BunkerResponseError(id, error)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseEvent(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val event: Event,
|
||||||
|
) : BunkerResponse(id, event.toJson(), null) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponseEvent(id, Event.fromJson(result))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference
|
||||||
|
import com.vitorpamplona.quartz.events.ContactListEvent.ReadWrite
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponseGetRelays(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val relays: Map<String, ReadWrite>,
|
||||||
|
) : BunkerResponse(id, Event.mapper.writeValueAsString(relays), null) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponseGetRelays(id, Event.mapper.readValue(result, object : TypeReference<Map<String, ReadWrite>>() {}))
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponsePong(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
) : BunkerResponse(id, RESULT, null) {
|
||||||
|
companion object {
|
||||||
|
val RESULT = "pong"
|
||||||
|
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponsePong(id)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,37 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
|
class BunkerResponsePublicKey(
|
||||||
|
id: String = UUID.randomUUID().toString(),
|
||||||
|
val pubkey: HexKey,
|
||||||
|
) : BunkerResponse(id, pubkey, null) {
|
||||||
|
companion object {
|
||||||
|
fun parse(
|
||||||
|
id: String,
|
||||||
|
result: String,
|
||||||
|
error: String? = null,
|
||||||
|
) = BunkerResponsePublicKey(id, result)
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,108 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 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.events.nip46
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import com.vitorpamplona.quartz.encoders.Hex
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexKey
|
||||||
|
import com.vitorpamplona.quartz.encoders.HexValidator
|
||||||
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import com.vitorpamplona.quartz.signers.NostrSigner
|
||||||
|
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||||
|
import com.vitorpamplona.quartz.utils.pointerSizeInBytes
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
class NostrConnectEvent(
|
||||||
|
id: HexKey,
|
||||||
|
pubKey: HexKey,
|
||||||
|
createdAt: Long,
|
||||||
|
tags: Array<Array<String>>,
|
||||||
|
content: String,
|
||||||
|
sig: HexKey,
|
||||||
|
) : Event(id, pubKey, createdAt, KIND, tags, content, sig) {
|
||||||
|
@Transient private var decryptedContent: Map<HexKey, BunkerMessage> = mapOf()
|
||||||
|
|
||||||
|
override fun countMemory(): Long =
|
||||||
|
super.countMemory() +
|
||||||
|
pointerSizeInBytes + (decryptedContent.values.sumOf { pointerSizeInBytes + it.countMemory() })
|
||||||
|
|
||||||
|
override fun isContentEncoded() = true
|
||||||
|
|
||||||
|
private fun recipientPubKey() = tags.firstOrNull { it.size > 1 && it[0] == "p" }?.get(1)
|
||||||
|
|
||||||
|
fun recipientPubKeyBytes() = recipientPubKey()?.runCatching { Hex.decode(this) }?.getOrNull()
|
||||||
|
|
||||||
|
fun verifiedRecipientPubKey(): HexKey? {
|
||||||
|
val recipient = recipientPubKey()
|
||||||
|
return if (HexValidator.isHex(recipient)) {
|
||||||
|
recipient
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun talkingWith(oneSideHex: String): HexKey = if (pubKey == oneSideHex) verifiedRecipientPubKey() ?: pubKey else pubKey
|
||||||
|
|
||||||
|
fun plainContent(
|
||||||
|
signer: NostrSigner,
|
||||||
|
onReady: (BunkerMessage) -> Unit,
|
||||||
|
) {
|
||||||
|
decryptedContent[signer.pubKey]?.let {
|
||||||
|
onReady(it)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// decrypts using NIP-04 or NIP-44
|
||||||
|
signer.decrypt(content, talkingWith(signer.pubKey)) { retVal ->
|
||||||
|
val content = Event.mapper.readValue(retVal, BunkerMessage::class.java)
|
||||||
|
|
||||||
|
decryptedContent = decryptedContent + Pair(signer.pubKey, content)
|
||||||
|
|
||||||
|
onReady(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val KIND = 24133
|
||||||
|
const val ALT = "Nostr Connect Event"
|
||||||
|
|
||||||
|
fun create(
|
||||||
|
message: BunkerMessage,
|
||||||
|
remoteKey: HexKey,
|
||||||
|
signer: NostrSigner,
|
||||||
|
createdAt: Long = TimeUtils.now(),
|
||||||
|
onReady: (NostrConnectEvent) -> Unit,
|
||||||
|
) {
|
||||||
|
val tags =
|
||||||
|
arrayOf(
|
||||||
|
arrayOf("alt", ALT),
|
||||||
|
arrayOf("p", remoteKey),
|
||||||
|
)
|
||||||
|
signer.sign(createdAt, KIND, tags, "", onReady)
|
||||||
|
|
||||||
|
val encrypted = mapper.writeValueAsString(message)
|
||||||
|
|
||||||
|
signer.nip44Encrypt(encrypted, remoteKey) { content ->
|
||||||
|
signer.sign(createdAt, KIND, tags, content, onReady)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user