commit 7940737d0dfa008579c71f2f5be7073631b7f3fd
parent e7817600be65afe420b9346ba2f8dfcd601b8131
Author: triesap <tyson@radroots.org>
Date: Fri, 12 Jun 2026 23:02:43 -0700
events: add frozen event drafts
- add canonical frozen draft and signed event protocol types under radroots_events
- compute deterministic NIP-01 event IDs from fixed draft preimages
- replace the codec EventDraft helper with a no-alias frozen draft adapter
- align SDK shared-type metadata and contract fixtures with the new draft surface
Diffstat:
17 files changed, 428 insertions(+), 40 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -4023,9 +4023,11 @@ dependencies = [
name = "radroots_events"
version = "0.1.0-alpha.2"
dependencies = [
+ "hex",
"radroots_core",
"serde",
"serde_json",
+ "sha2",
]
[[package]]
diff --git a/crates/events/Cargo.toml b/crates/events/Cargo.toml
@@ -19,10 +19,12 @@ serde = ["dep:serde", "radroots_core/serde"]
[dependencies]
radroots_core = { workspace = true, default-features = false }
+hex = { version = "0.4", default-features = false, features = ["alloc"] }
serde = { workspace = true, default-features = false, features = [
"alloc",
"derive",
], optional = true }
+serde_json = { workspace = true, default-features = false, features = ["alloc"] }
+sha2 = { workspace = true, default-features = false }
[dev-dependencies]
-serde_json = { workspace = true }
diff --git a/crates/events/src/contract.rs b/crates/events/src/contract.rs
@@ -5,6 +5,8 @@ use alloc::{string::String, vec::Vec};
use crate::kinds::*;
+pub const RADROOTS_EVENT_CONTRACT_REGISTRY_VERSION: u32 = 1;
+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum RadrootsEventClass {
Regular,
diff --git a/crates/events/src/draft.rs b/crates/events/src/draft.rs
@@ -0,0 +1,363 @@
+#![forbid(unsafe_code)]
+
+#[cfg(not(feature = "std"))]
+use alloc::{
+ borrow::ToOwned,
+ string::{String, ToString},
+ vec::Vec,
+};
+
+#[cfg(feature = "std")]
+use std::{
+ borrow::ToOwned,
+ string::{String, ToString},
+ vec::Vec,
+};
+
+use crate::RadrootsNostrEvent;
+use crate::contract::{RADROOTS_EVENT_CONTRACT_REGISTRY_VERSION, event_contract};
+use crate::ids::{
+ RadrootsEventId, RadrootsEventSignature, RadrootsIdParseError, RadrootsPublicKey,
+};
+use core::fmt;
+use sha2::{Digest, Sha256};
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub enum RadrootsDraftError {
+ UnknownContract(String),
+ ContractKindMismatch {
+ contract_id: String,
+ expected_kind: u32,
+ actual_kind: u32,
+ },
+ IdParse(RadrootsIdParseError),
+ JsonString(String),
+}
+
+impl fmt::Display for RadrootsDraftError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::UnknownContract(contract_id) => {
+ write!(f, "unknown event contract `{contract_id}`")
+ }
+ Self::ContractKindMismatch {
+ contract_id,
+ expected_kind,
+ actual_kind,
+ } => write!(
+ f,
+ "event contract `{contract_id}` expects kind {expected_kind}, got {actual_kind}"
+ ),
+ Self::IdParse(error) => write!(f, "{error}"),
+ Self::JsonString(error) => write!(f, "json string serialization failed: {error}"),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for RadrootsDraftError {}
+
+impl From<RadrootsIdParseError> for RadrootsDraftError {
+ fn from(value: RadrootsIdParseError) -> Self {
+ Self::IdParse(value)
+ }
+}
+
+impl From<serde_json::Error> for RadrootsDraftError {
+ fn from(value: serde_json::Error) -> Self {
+ Self::JsonString(value.to_string())
+ }
+}
+
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct RadrootsFrozenEventDraft {
+ pub contract_id: String,
+ pub contract_registry_version: u32,
+ pub kind: u32,
+ pub created_at: u32,
+ pub tags: Vec<Vec<String>>,
+ pub content: String,
+ pub expected_pubkey: String,
+ pub expected_event_id: String,
+}
+
+impl RadrootsFrozenEventDraft {
+ pub fn new(
+ contract_id: impl Into<String>,
+ kind: u32,
+ created_at: u32,
+ tags: Vec<Vec<String>>,
+ content: impl Into<String>,
+ expected_pubkey: impl AsRef<str>,
+ ) -> Result<Self, RadrootsDraftError> {
+ let contract_id = contract_id.into();
+ let contract = event_contract(&contract_id)
+ .ok_or_else(|| RadrootsDraftError::UnknownContract(contract_id.clone()))?;
+ if contract.kind != kind {
+ return Err(RadrootsDraftError::ContractKindMismatch {
+ contract_id,
+ expected_kind: contract.kind,
+ actual_kind: kind,
+ });
+ }
+ let expected_pubkey = RadrootsPublicKey::parse(expected_pubkey.as_ref())?.into_string();
+ let content = content.into();
+ let expected_event_id =
+ compute_nip01_event_id(expected_pubkey.as_str(), created_at, kind, &tags, &content)?
+ .into_string();
+ Ok(Self {
+ contract_id: contract.id.to_owned(),
+ contract_registry_version: RADROOTS_EVENT_CONTRACT_REGISTRY_VERSION,
+ kind,
+ created_at,
+ tags,
+ content,
+ expected_pubkey,
+ expected_event_id,
+ })
+ }
+
+ pub fn nip01_preimage(&self) -> Result<String, RadrootsDraftError> {
+ nip01_event_id_preimage(
+ self.expected_pubkey.as_str(),
+ self.created_at,
+ self.kind,
+ &self.tags,
+ self.content.as_str(),
+ )
+ }
+}
+
+#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct RadrootsSignedNostrEvent {
+ pub id: String,
+ pub pubkey: String,
+ pub created_at: u32,
+ pub kind: u32,
+ pub tags: Vec<Vec<String>>,
+ pub content: String,
+ pub sig: String,
+ pub raw_json: String,
+}
+
+impl RadrootsSignedNostrEvent {
+ pub fn new(
+ id: impl AsRef<str>,
+ pubkey: impl AsRef<str>,
+ created_at: u32,
+ kind: u32,
+ tags: Vec<Vec<String>>,
+ content: impl Into<String>,
+ sig: impl AsRef<str>,
+ raw_json: impl Into<String>,
+ ) -> Result<Self, RadrootsDraftError> {
+ let id = RadrootsEventId::parse(id.as_ref())?.into_string();
+ let pubkey = RadrootsPublicKey::parse(pubkey.as_ref())?.into_string();
+ let sig = RadrootsEventSignature::parse(sig.as_ref())?.into_string();
+ Ok(Self {
+ id,
+ pubkey,
+ created_at,
+ kind,
+ tags,
+ content: content.into(),
+ sig,
+ raw_json: raw_json.into(),
+ })
+ }
+
+ pub fn from_event(
+ event: RadrootsNostrEvent,
+ raw_json: impl Into<String>,
+ ) -> Result<Self, RadrootsDraftError> {
+ Self::new(
+ event.id,
+ event.author,
+ event.created_at,
+ event.kind,
+ event.tags,
+ event.content,
+ event.sig,
+ raw_json,
+ )
+ }
+}
+
+pub fn compute_nip01_event_id(
+ pubkey: &str,
+ created_at: u32,
+ kind: u32,
+ tags: &[Vec<String>],
+ content: &str,
+) -> Result<RadrootsEventId, RadrootsDraftError> {
+ let pubkey = RadrootsPublicKey::parse(pubkey)?;
+ let preimage = nip01_event_id_preimage(pubkey.as_str(), created_at, kind, tags, content)?;
+ let digest = Sha256::digest(preimage.as_bytes());
+ let event_id = hex::encode(digest);
+ Ok(RadrootsEventId::parse(event_id)?)
+}
+
+pub fn nip01_event_id_preimage(
+ pubkey: &str,
+ created_at: u32,
+ kind: u32,
+ tags: &[Vec<String>],
+ content: &str,
+) -> Result<String, RadrootsDraftError> {
+ let mut preimage = String::new();
+ preimage.push_str("[0,");
+ push_json_string(&mut preimage, pubkey)?;
+ preimage.push(',');
+ preimage.push_str(created_at.to_string().as_str());
+ preimage.push(',');
+ preimage.push_str(kind.to_string().as_str());
+ preimage.push_str(",[");
+ for (tag_index, tag) in tags.iter().enumerate() {
+ if tag_index > 0 {
+ preimage.push(',');
+ }
+ preimage.push('[');
+ for (value_index, value) in tag.iter().enumerate() {
+ if value_index > 0 {
+ preimage.push(',');
+ }
+ push_json_string(&mut preimage, value)?;
+ }
+ preimage.push(']');
+ }
+ preimage.push_str("],");
+ push_json_string(&mut preimage, content)?;
+ preimage.push(']');
+ Ok(preimage)
+}
+
+fn push_json_string(target: &mut String, value: &str) -> Result<(), RadrootsDraftError> {
+ target.push_str(serde_json::to_string(value)?.as_str());
+ Ok(())
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::kinds::{KIND_POST, KIND_PROFILE};
+
+ fn hex_64(character: char) -> String {
+ core::iter::repeat_n(character, 64).collect()
+ }
+
+ #[test]
+ fn frozen_draft_computes_expected_event_id() {
+ let draft = RadrootsFrozenEventDraft::new(
+ "radroots.social.post.v1",
+ KIND_POST,
+ 1_700_000_000,
+ vec![
+ vec!["t".to_owned(), "soil".to_owned()],
+ vec!["p".to_owned(), hex_64('b')],
+ ],
+ "hello",
+ hex_64('a'),
+ )
+ .expect("draft");
+
+ assert_eq!(
+ draft.nip01_preimage().expect("preimage"),
+ "[0,\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\",1700000000,1,[[\"t\",\"soil\"],[\"p\",\"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\"]],\"hello\"]"
+ );
+ assert_eq!(
+ draft.expected_event_id,
+ "59d2486ef5557e0e317127de55005f2863361ad4041277ae523a869f2294cf9c"
+ );
+ }
+
+ #[test]
+ fn deterministic_event_id_changes_when_preimage_changes() {
+ let tags = vec![vec!["t".to_owned(), "soil".to_owned()]];
+ let base = compute_nip01_event_id(hex_64('a').as_str(), 1, KIND_POST, &tags, "hello")
+ .expect("base");
+ let pubkey_changed =
+ compute_nip01_event_id(hex_64('b').as_str(), 1, KIND_POST, &tags, "hello")
+ .expect("pubkey");
+ let time_changed =
+ compute_nip01_event_id(hex_64('a').as_str(), 2, KIND_POST, &tags, "hello")
+ .expect("time");
+ let kind_changed =
+ compute_nip01_event_id(hex_64('a').as_str(), 1, KIND_PROFILE, &tags, "hello")
+ .expect("kind");
+ let tag_order_changed = compute_nip01_event_id(
+ hex_64('a').as_str(),
+ 1,
+ KIND_POST,
+ &[
+ vec!["p".to_owned(), hex_64('c')],
+ vec!["t".to_owned(), "soil".to_owned()],
+ ],
+ "hello",
+ )
+ .expect("tag order");
+ let content_changed =
+ compute_nip01_event_id(hex_64('a').as_str(), 1, KIND_POST, &tags, "hello!")
+ .expect("content");
+
+ assert_ne!(base, pubkey_changed);
+ assert_ne!(base, time_changed);
+ assert_ne!(base, kind_changed);
+ assert_ne!(base, tag_order_changed);
+ assert_ne!(base, content_changed);
+ }
+
+ #[test]
+ fn profile_golden_event_id_is_stable() {
+ let event_id = compute_nip01_event_id(hex_64('c').as_str(), 1_700_000_001, 0, &[], "{}")
+ .expect("event id");
+
+ assert_eq!(
+ event_id.as_str(),
+ "2a15e33622a155ae231b28bebe390869e67a0e228f77ecfcd652b1ce180a9dde"
+ );
+ }
+
+ #[test]
+ fn draft_constructor_rejects_unknown_contract_and_kind_mismatch() {
+ let unknown =
+ RadrootsFrozenEventDraft::new("missing", KIND_POST, 1, Vec::new(), "", hex_64('a'))
+ .expect_err("unknown contract");
+ assert!(matches!(unknown, RadrootsDraftError::UnknownContract(_)));
+
+ let mismatch = RadrootsFrozenEventDraft::new(
+ "radroots.social.post.v1",
+ KIND_PROFILE,
+ 1,
+ Vec::new(),
+ "",
+ hex_64('a'),
+ )
+ .expect_err("kind mismatch");
+ assert!(matches!(
+ mismatch,
+ RadrootsDraftError::ContractKindMismatch { .. }
+ ));
+ }
+
+ #[test]
+ fn signed_event_validates_ids_and_roundtrips_with_serde() {
+ let signed = RadrootsSignedNostrEvent::new(
+ hex_64('d'),
+ hex_64('e'),
+ 10,
+ KIND_POST,
+ Vec::new(),
+ "hello",
+ "f".repeat(128),
+ "{\"id\":\"fixture\"}",
+ )
+ .expect("signed event");
+ let json = serde_json::to_string(&signed).expect("serialize");
+ let decoded: RadrootsSignedNostrEvent = serde_json::from_str(&json).expect("deserialize");
+
+ assert_eq!(decoded, signed);
+ assert_eq!(decoded.pubkey, hex_64('e'));
+ }
+}
diff --git a/crates/events/src/lib.rs b/crates/events/src/lib.rs
@@ -14,6 +14,7 @@ pub mod comment;
pub mod contract;
pub mod coop;
pub mod document;
+pub mod draft;
pub mod event_head;
pub mod farm;
pub mod farm_crdt;
diff --git a/crates/events_codec/src/job/encode.rs b/crates/events_codec/src/job/encode.rs
@@ -3,7 +3,8 @@ use core::fmt;
#[cfg(not(feature = "std"))]
use alloc::{string::String, vec, vec::Vec};
-pub use crate::wire::{EventDraft, WireEventParts, canonicalize_tags, empty_content, to_draft};
+pub use crate::wire::{WireEventParts, canonicalize_tags, empty_content, to_frozen_draft};
+pub use radroots_events::draft::RadrootsFrozenEventDraft;
#[derive(Debug)]
pub enum JobEncodeError {
diff --git a/crates/events_codec/src/wire.rs b/crates/events_codec/src/wire.rs
@@ -4,30 +4,29 @@ use alloc::{
vec::Vec,
};
-#[derive(Debug, Clone)]
-pub struct WireEventParts {
- pub kind: u32,
- pub content: String,
- pub tags: Vec<Vec<String>>,
-}
+use radroots_events::draft::{RadrootsDraftError, RadrootsFrozenEventDraft};
#[derive(Debug, Clone)]
-pub struct EventDraft {
+pub struct WireEventParts {
pub kind: u32,
- pub created_at: u32,
- pub author: String,
pub content: String,
pub tags: Vec<Vec<String>>,
}
-pub fn to_draft(parts: WireEventParts, author: impl Into<String>, created_at: u32) -> EventDraft {
- EventDraft {
- kind: parts.kind,
+pub fn to_frozen_draft(
+ parts: WireEventParts,
+ contract_id: impl Into<String>,
+ expected_pubkey: impl AsRef<str>,
+ created_at: u32,
+) -> Result<RadrootsFrozenEventDraft, RadrootsDraftError> {
+ RadrootsFrozenEventDraft::new(
+ contract_id,
+ parts.kind,
created_at,
- author: author.into(),
- content: parts.content,
- tags: parts.tags,
- }
+ parts.tags,
+ parts.content,
+ expected_pubkey,
+ )
}
pub fn canonicalize_tags(tags: &mut Vec<Vec<String>>) {
diff --git a/crates/events_codec/tests/wire.rs b/crates/events_codec/tests/wire.rs
@@ -1,5 +1,7 @@
use radroots_events::kinds::KIND_POST;
-use radroots_events_codec::wire::{WireEventParts, canonicalize_tags, empty_content, to_draft};
+use radroots_events_codec::wire::{
+ WireEventParts, canonicalize_tags, empty_content, to_frozen_draft,
+};
#[test]
fn canonicalize_tags_trims_sorts_and_dedups() {
@@ -23,20 +25,22 @@ fn canonicalize_tags_trims_sorts_and_dedups() {
}
#[test]
-fn to_draft_copies_fields() {
+fn to_frozen_draft_copies_fields_and_computes_expected_id() {
let parts = WireEventParts {
kind: KIND_POST,
content: "hello".to_string(),
tags: vec![vec!["t".to_string(), "a".to_string()]],
};
- let draft = to_draft(parts, "author", 99);
+ let draft =
+ to_frozen_draft(parts, "radroots.social.post.v1", "a".repeat(64), 99).expect("draft");
assert_eq!(draft.kind, KIND_POST);
assert_eq!(draft.created_at, 99);
- assert_eq!(draft.author, "author");
+ assert_eq!(draft.expected_pubkey, "a".repeat(64));
assert_eq!(draft.content, "hello");
assert_eq!(draft.tags.len(), 1);
+ assert_eq!(draft.expected_event_id.len(), 64);
}
#[test]
diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs
@@ -57,6 +57,7 @@ pub use crate::config::{
};
pub use radroots_events::{
RadrootsNostrEvent, RadrootsNostrEventPtr, RadrootsNostrEventRef,
+ draft::{RadrootsFrozenEventDraft, RadrootsSignedNostrEvent},
farm::RadrootsFarm,
listing::RadrootsListing,
profile::{RadrootsProfile, RadrootsProfileType},
@@ -65,7 +66,7 @@ pub use radroots_events::{
pub use radroots_events_codec::order::{
RadrootsOrderEnvelopeParseError, RadrootsOrderListingAddress, RadrootsOrderListingAddressError,
};
-pub use radroots_events_codec::wire::{EventDraft as UnsignedEventDraft, WireEventParts};
+pub use radroots_events_codec::wire::WireEventParts;
pub use radroots_trade::listing::validation::RadrootsTradeListing as TradeListingValidateResult;
pub type NostrTags = Vec<Vec<String>>;
diff --git a/crates/xtask/src/contract.rs b/crates/xtask/src/contract.rs
@@ -4197,7 +4197,8 @@ order = 1
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsListing" = "RadrootsListing"
@@ -4260,7 +4261,8 @@ domains = ["profile", "farm", "listing", "trade"]
[shared_types]
public = [
"WireEventParts",
- "UnsignedEventDraft",
+ "RadrootsFrozenEventDraft",
+ "RadrootsSignedNostrEvent",
"RadrootsNostrEvent",
"RadrootsNostrEventRef",
"RadrootsNostrEventPtr",
@@ -4338,7 +4340,8 @@ order = 1
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsListing" = "RadrootsListing"
diff --git a/spec/RCLD.md b/spec/RCLD.md
@@ -122,7 +122,8 @@ Public cross-operation types required for operation inputs and outputs.
Examples:
- `WireEventParts`
-- `UnsignedEventDraft`
+- `RadrootsFrozenEventDraft`
+- `RadrootsSignedNostrEvent`
- `RadrootsNostrEvent`
- `RadrootsNostrEventRef`
- `RadrootsOrderListingAddress`
@@ -172,7 +173,7 @@ Input:
Output:
- `WireEventParts`
-- optional `UnsignedEventDraft` helper via shared draft adapter
+- optional `RadrootsFrozenEventDraft` helper via shared draft adapter
Determinism:
@@ -250,7 +251,7 @@ Input:
Output:
- `WireEventParts`
-- optionally adapted to `UnsignedEventDraft`
+- optionally adapted to `RadrootsFrozenEventDraft`
Determinism:
@@ -375,7 +376,8 @@ The public contract should explicitly enumerate a minimal shared type set.
Recommended Tier 1 shared types:
- `WireEventParts`
-- `UnsignedEventDraft`
+- `RadrootsFrozenEventDraft`
+- `RadrootsSignedNostrEvent`
- `RadrootsNostrEvent`
- `RadrootsNostrEventRef`
- `RadrootsNostrEventPtr`
@@ -386,7 +388,7 @@ Recommended Tier 1 shared types:
- `RadrootsListing`
- trade payload and envelope types required by approved trade operations
-`UnsignedEventDraft` should be a public contract alias or wrapper over the current `EventDraft` concept in `crates/events_codec/src/wire.rs`. The public naming should emphasize unsigned event construction rather than internal adapter mechanics.
+`RadrootsFrozenEventDraft` should be a public frozen draft contract type in `crates/events/src/draft.rs`, with `crates/events_codec/src/wire.rs` adapting codec output into the shared type. The public naming should emphasize frozen event construction rather than internal adapter mechanics.
## Shared Errors
@@ -502,7 +504,8 @@ domains = ["profile", "farm", "listing", "trade"]
[shared_types]
public = [
"WireEventParts",
- "UnsignedEventDraft",
+ "RadrootsFrozenEventDraft",
+ "RadrootsSignedNostrEvent",
"RadrootsNostrEvent",
"RadrootsNostrEventRef",
"RadrootsNostrEventPtr",
@@ -612,7 +615,8 @@ networking = "native"
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsOrderListingAddress" = "OrderListingAddress"
@@ -732,7 +736,7 @@ Recommended shape:
This facade should:
- define public operation names
-- define any public wrapper naming such as `UnsignedEventDraft`
+- define any public draft naming such as `RadrootsFrozenEventDraft`
- centralize contract documentation and source references
- make it easier for generators and future language bindings to target one approved surface
diff --git a/spec/operations.toml b/spec/operations.toml
@@ -9,7 +9,8 @@ domains = ["profile", "farm", "listing", "order", "trade_validation", "social"]
[shared_types]
public = [
"WireEventParts",
- "UnsignedEventDraft",
+ "RadrootsFrozenEventDraft",
+ "RadrootsSignedNostrEvent",
"RadrootsNostrEvent",
"RadrootsNostrEventRef",
"RadrootsNostrEventPtr",
diff --git a/spec/sdk-exports/go.toml b/spec/sdk-exports/go.toml
@@ -34,7 +34,8 @@ order = 3
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsNostrEventRef" = "RadrootsNostrEventRef"
"RadrootsNostrEventPtr" = "RadrootsNostrEventPtr"
diff --git a/spec/sdk-exports/kotlin.toml b/spec/sdk-exports/kotlin.toml
@@ -34,7 +34,8 @@ order = 2
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsNostrEventRef" = "RadrootsNostrEventRef"
"RadrootsNostrEventPtr" = "RadrootsNostrEventPtr"
diff --git a/spec/sdk-exports/py.toml b/spec/sdk-exports/py.toml
@@ -34,7 +34,8 @@ order = 3
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsNostrEventRef" = "RadrootsNostrEventRef"
"RadrootsNostrEventPtr" = "RadrootsNostrEventPtr"
diff --git a/spec/sdk-exports/swift.toml b/spec/sdk-exports/swift.toml
@@ -34,7 +34,8 @@ order = 2
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsNostrEventRef" = "RadrootsNostrEventRef"
"RadrootsNostrEventPtr" = "RadrootsNostrEventPtr"
diff --git a/spec/sdk-exports/ts.toml b/spec/sdk-exports/ts.toml
@@ -35,7 +35,8 @@ order = 1
[shared_types]
"WireEventParts" = "WireEventParts"
-"UnsignedEventDraft" = "UnsignedEventDraft"
+"RadrootsFrozenEventDraft" = "RadrootsFrozenEventDraft"
+"RadrootsSignedNostrEvent" = "RadrootsSignedNostrEvent"
"RadrootsNostrEvent" = "RadrootsNostrEvent"
"RadrootsNostrEventRef" = "RadrootsNostrEventRef"
"RadrootsNostrEventPtr" = "RadrootsNostrEventPtr"