commit c7b1b2a2515871154a790a42b0aad0a49870e655
parent fe0957ac7f79be56fcd1a5e592c02cbf5a6b4845
Author: triesap <tyson@radroots.org>
Date: Sun, 12 Apr 2026 23:54:23 +0000
sdk: checkpoint ingest parity
Diffstat:
2 files changed, 87 insertions(+), 1 deletion(-)
diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml
@@ -23,7 +23,11 @@ serde_json = [
"radroots_trade/serde_json",
]
nostr = ["radroots_events_codec/nostr"]
-identity-models = ["dep:radroots_identity", "radroots_identity/profile"]
+identity-models = [
+ "dep:radroots_identity",
+ "radroots_identity/profile",
+ "radroots_identity/std",
+]
identity-storage = ["identity-models", "std", "radroots_identity/std"]
signing = ["dep:radroots_nostr", "nostr"]
relay-client = ["signing", "std", "radroots_nostr/client"]
@@ -48,5 +52,9 @@ radroots_nostr_signer = { workspace = true, optional = true, default-features =
[dev-dependencies]
radroots_core = { workspace = true, default-features = false, features = ["std"] }
+radroots_replica_db = { workspace = true, default-features = false, features = ["native"] }
+radroots_replica_db_schema = { workspace = true }
+radroots_replica_sync = { workspace = true, features = ["std"] }
+radroots_sql_core = { workspace = true, features = ["native"] }
tempfile = { workspace = true }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
diff --git a/crates/sdk/tests/replica_ingest.rs b/crates/sdk/tests/replica_ingest.rs
@@ -0,0 +1,78 @@
+use radroots_replica_db::ReplicaSql;
+use radroots_replica_db_schema::farm::IFarmFindMany;
+use radroots_replica_sync::{RadrootsReplicaIngestOutcome, radroots_replica_ingest_event};
+use radroots_sdk::{RadrootsFarm, RadrootsNostrEvent, farm};
+use radroots_sql_core::{SqlExecutor, SqliteExecutor};
+use tempfile::{TempDir, tempdir};
+
+fn seller_pubkey() -> String {
+ "a".repeat(64)
+}
+
+fn sdk_event(
+ id: u64,
+ author: &str,
+ created_at: u32,
+ kind: u32,
+ content: String,
+ tags: Vec<Vec<String>>,
+) -> RadrootsNostrEvent {
+ RadrootsNostrEvent {
+ id: format!("{id:064x}"),
+ author: author.to_owned(),
+ created_at,
+ kind,
+ tags,
+ content,
+ sig: "f".repeat(128),
+ }
+}
+
+fn sample_farm() -> RadrootsFarm {
+ RadrootsFarm {
+ d_tag: "AAAAAAAAAAAAAAAAAAAAAA".into(),
+ name: "North Farm".into(),
+ about: Some("Organic coffee".into()),
+ website: None,
+ picture: None,
+ banner: None,
+ location: None,
+ tags: Some(vec!["coffee".into()]),
+ }
+}
+
+fn open_replica() -> (TempDir, ReplicaSql<SqliteExecutor>) {
+ let dir = tempdir().expect("tempdir");
+ let db_path = dir.path().join("replica.sqlite");
+ let executor = SqliteExecutor::open(&db_path).expect("open sqlite");
+ executor
+ .exec("PRAGMA foreign_keys = ON;", "[]")
+ .expect("enable foreign keys");
+ let replica = ReplicaSql::new(executor);
+ replica.migrate_up().expect("migrate");
+ (dir, replica)
+}
+
+fn ingest_farm(replica: &ReplicaSql<SqliteExecutor>) -> RadrootsNostrEvent {
+ let farm_value = sample_farm();
+ let author = seller_pubkey();
+ let parts = farm::build_draft(&farm_value).expect("farm draft");
+ let event = sdk_event(1, &author, 1_720_000_000, parts.kind, parts.content, parts.tags);
+ let outcome = radroots_replica_ingest_event(replica.executor(), &event).expect("ingest farm");
+ assert_eq!(outcome, RadrootsReplicaIngestOutcome::Applied);
+ event
+}
+
+#[test]
+fn sdk_farm_draft_ingests_into_replica_projection() {
+ let (_dir, replica) = open_replica();
+ let event = ingest_farm(&replica);
+ let farms = replica
+ .farm_find_many(&IFarmFindMany { filter: None })
+ .expect("query farms")
+ .results;
+ assert_eq!(farms.len(), 1);
+ assert_eq!(farms[0].d_tag, sample_farm().d_tag);
+ assert_eq!(farms[0].name, sample_farm().name);
+ assert_eq!(farms[0].pubkey, event.author);
+}