From 60f756338cd8d19ad245350bae3216dae29ad6dd Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Wed, 6 Dec 2023 17:30:06 +0100 Subject: [PATCH] ffi(nostr-sdk): use `uniffi` pro-macro instead of `UDL` --- Cargo.lock | 61 +- Cargo.toml | 2 +- bindings/nostr-sdk-ffi/Makefile | 21 +- .../bindings-android/lib/proguard-rules.pro | 2 + .../nostr-sdk-ffi/bindings-python/.gitignore | 1 + .../bindings-python/examples/bot.py | 6 +- .../examples/client-with-opts.py | 2 +- .../bindings-python/examples/client.py | 2 +- .../bindings-python/examples/database.py | 4 +- .../bindings-python/examples/metadata.py | 2 +- .../bindings-python/examples/nip94.py | 2 +- .../bindings-python/examples/relays.py | 6 +- .../bindings-python/src/nostr-sdk/__init__.py | 3 +- bindings/nostr-sdk-ffi/build.rs | 1 - bindings/nostr-sdk-ffi/src/client/builder.rs | 11 +- bindings/nostr-sdk-ffi/src/client/mod.rs | 18 +- bindings/nostr-sdk-ffi/src/client/options.rs | 11 +- bindings/nostr-sdk-ffi/src/database.rs | 10 +- bindings/nostr-sdk-ffi/src/error.rs | 3 +- bindings/nostr-sdk-ffi/src/lib.rs | 28 +- bindings/nostr-sdk-ffi/src/logger.rs | 3 + bindings/nostr-sdk-ffi/src/nostr_sdk.udl | 709 ------------------ bindings/nostr-sdk-ffi/src/relay.rs | 45 +- bindings/nostr-sdk-ffi/uniffi.toml | 5 - 24 files changed, 163 insertions(+), 795 deletions(-) delete mode 100644 bindings/nostr-sdk-ffi/src/nostr_sdk.udl diff --git a/Cargo.lock b/Cargo.lock index fa20ffeec..4f4fe4bea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2182,6 +2182,12 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +[[package]] +name = "smawk" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c" + [[package]] name = "socket2" version = "0.4.10" @@ -2261,6 +2267,17 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "textwrap" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +dependencies = [ + "smawk", + "unicode-linebreak", + "unicode-width", +] + [[package]] name = "thiserror" version = "1.0.50" @@ -2516,6 +2533,12 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-linebreak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f" + [[package]] name = "unicode-normalization" version = "0.1.22" @@ -2525,11 +2548,16 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "uniffi" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32e192430644d99babe02bede25316eee84fa154b1e5f8cfe99406c028b8c577" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "camino", @@ -2550,8 +2578,7 @@ dependencies = [ [[package]] name = "uniffi_bindgen" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c235355da41bc8347b2d5851e1060d4652dfbdc6d7d6ccddaabebe25e3c32a4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "askama", @@ -2565,6 +2592,7 @@ dependencies = [ "once_cell", "paste", "serde", + "textwrap", "toml", "uniffi_meta", "uniffi_testing", @@ -2574,8 +2602,7 @@ dependencies = [ [[package]] name = "uniffi_build" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81049ed7015a8a66b085aca3fb0c0011fdae4dd9ab8c38f5751f7861d60eb0f4" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "camino", @@ -2585,8 +2612,7 @@ dependencies = [ [[package]] name = "uniffi_checksum_derive" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce082833f0fcaf6fc221fbab26720440daf99381f5a71e89b6e23375eb6ea770" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "quote", "syn", @@ -2595,8 +2621,7 @@ dependencies = [ [[package]] name = "uniffi_core" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389bbe4d8334b3370c7cc998788d7a9619e0b61b58f1cbcd4a6a8606ab0a6f7d" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "bytes", @@ -2611,8 +2636,7 @@ dependencies = [ [[package]] name = "uniffi_macros" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34aa170f970d42d8fbe205f5794b83f72d6617835a73b91ed1869e1eba5dd06c" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "bincode", "camino", @@ -2630,8 +2654,7 @@ dependencies = [ [[package]] name = "uniffi_meta" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ef337c28a379ed6962eae0cb0824ab31202b21b8ae3bf6c2a706f5e7285f5f" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "bytes", @@ -2642,8 +2665,7 @@ dependencies = [ [[package]] name = "uniffi_testing" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f2e218997229b4ed6e08c1abc9e277dde817f68a633babd3ebbfc77e32db302" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", "camino", @@ -2655,10 +2677,10 @@ dependencies = [ [[package]] name = "uniffi_udl" version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb29909e50256f32986ea3b3c32d2c49dece14ae4b3428c047913696ed200b2a" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "anyhow", + "textwrap", "uniffi_meta", "uniffi_testing", "weedle2", @@ -2886,8 +2908,7 @@ checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" [[package]] name = "weedle2" version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e79c5206e1f43a2306fd64bdb95025ee4228960f2e6c5a8b173f3caaf807741" +source = "git+https://github.com/mozilla/uniffi-rs?rev=d380d164cfdba9e091c461baa6855f0a2294ac5b#d380d164cfdba9e091c461baa6855f0a2294ac5b" dependencies = [ "nom", ] diff --git a/Cargo.toml b/Cargo.toml index ebbbc8d91..38e3db845 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ thiserror = "1.0" tokio = { version = "1.32", default-features = false } tracing = { version = "0.1", default-features = false } tracing-subscriber = "0.3" -uniffi = "0.25" +uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "d380d164cfdba9e091c461baa6855f0a2294ac5b" } url-fork = { version = "3.0", default-features = false } [profile.release] diff --git a/bindings/nostr-sdk-ffi/Makefile b/bindings/nostr-sdk-ffi/Makefile index 3fe8851f7..dbaec9c2f 100644 --- a/bindings/nostr-sdk-ffi/Makefile +++ b/bindings/nostr-sdk-ffi/Makefile @@ -24,11 +24,14 @@ sdk-root: exit 1 ; \ fi +kotlin-clean: + find ./ffi/kotlin/jniLibs -name libnostr_sdk_ffi.so -type f -delete + kotlin: android find ./ffi/kotlin/jniLibs -name libnostr_ffi.so -type f -delete - cargo run -p uniffi-bindgen generate src/nostr_sdk.udl --language kotlin --no-format -o ffi/kotlin + cargo run -p uniffi-bindgen generate --library ../../target/x86_64-linux-android/release/libnostr_sdk_ffi.so --language kotlin --no-format -o ffi/kotlin -android: aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android +android: kotlin-clean aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android aarch64-linux-android: $(SOURCES) ndk-home cargo ndk -t aarch64-linux-android -o ffi/kotlin/jniLibs build --release @@ -46,7 +49,9 @@ bindings-android: sdk-root kotlin rm -rf bindings-android/lib/src/main/jniLibs rm -rf bindings-android/lib/src/main/kotlin cp -r ffi/kotlin/jniLibs bindings-android/lib/src/main - cp -r ffi/kotlin/nostr_sdk bindings-android/lib/src/main/kotlin/ + mkdir -p bindings-android/lib/src/main/kotlin/ + cp ffi/kotlin/nostr/nostr.kt bindings-android/lib/src/main/kotlin/ + cp ffi/kotlin/nostr_sdk/nostr_sdk.kt bindings-android/lib/src/main/kotlin/ cd bindings-android && ./gradlew assemble mkdir -p ffi/android cp bindings-android/lib/build/outputs/aar/lib-release.aar ffi/android @@ -71,18 +76,18 @@ darwin-universal: $(SOURCES) lipo -create -output ../../target/darwin-universal/release/libnostr_sdk_ffi.a ../../target/aarch64-apple-darwin/release/libnostr_sdk_ffi.a ../../target/x86_64-apple-darwin/release/libnostr_sdk_ffi.a swift-ios: ios-universal - cargo run -p uniffi-bindgen generate src/nostr_sdk.udl -l swift -o ffi/swift-ios + cargo run -p uniffi-bindgen generate --library ../../target/aarch64-apple-ios/release/libnostr_sdk_ffi.a -l swift -o ffi/swift-ios cp ../../target/ios-universal/release/libnostr_sdk_ffi.a ffi/swift-ios cd ffi/swift-ios && "swiftc" "-emit-module" "-module-name" "nostr_sdk_ffi" "-Xcc" "-fmodule-map-file=$(CURRENT_DIR)/ffi/swift-ios/nostr_sdkFFI.modulemap" "-I" "." "-L" "." "-lnostr_sdk_ffi" nostr_sdk.swift swift-darwin: darwin-universal - cargo run -p uniffi-bindgen generate src/nostr_sdk.udl -l swift -o ffi/swift-darwin + cargo run -p uniffi-bindgen generate --library ../../target/aarch64-apple-darwin/release/libnostr_sdk_ffi.a -l swift -o ffi/swift-darwin cp ../../target/darwin-universal/release/libnostr_sdk_ffi.dylib ffi/swift-darwin cd ffi/swift-darwin && "swiftc" "-emit-module" "-module-name" "nostr_sdk_ffi" "-Xcc" "-fmodule-map-file=$(CURRENT_DIR)/ffi/swift-darwin/nostr_sdkFFI.modulemap" "-I" "." "-L" "." "-lnostr_sdk_ffi" nostr_sdk.swift bindings-swift: ios-universal darwin-universal mkdir -p bindings-swift/Sources/NostrSDK - cargo run -p uniffi-bindgen generate src/nostr_sdk.udl --no-format --language swift --out-dir bindings-swift/Sources/NostrSDK + cargo run -p uniffi-bindgen generate --library ../../target/aarch64-apple-ios/release/libnostr_sdk_ffi.a --no-format --language swift --out-dir bindings-swift/Sources/NostrSDK mv bindings-swift/Sources/NostrSDK/nostr_sdk.swift bindings-swift/Sources/NostrSDK/NostrSDK.swift cp bindings-swift/Sources/NostrSDK/nostr_sdkFFI.h bindings-swift/nostr_sdkFFI.xcframework/ios-arm64/nostr_sdkFFI.framework/Headers cp bindings-swift/Sources/NostrSDK/nostr_sdkFFI.h bindings-swift/nostr_sdkFFI.xcframework/ios-arm64_x86_64-simulator/nostr_sdkFFI.framework/Headers @@ -97,7 +102,7 @@ python: rm -rf bindings-python/dist pip install -r bindings-python/requirements.txt cargo build --release - cargo run -p uniffi-bindgen generate src/nostr_sdk.udl --language python --no-format -o bindings-python/src/nostr-sdk/ + cargo run -p uniffi-bindgen generate --library ../../target/release/libnostr_sdk_ffi.so --language python --no-format -o bindings-python/src/nostr-sdk/ cp ../../target/release/libnostr_sdk_ffi.so bindings-python/src/nostr-sdk/ | true cp ../../target/release/libnostr_sdk_ffi.dylib bindings-python/src/nostr-sdk/ | true cd bindings-python && python setup.py --verbose bdist_wheel @@ -106,7 +111,7 @@ python: python-win: pip install -r bindings-python\requirements.txt cargo build --release - cargo run -p uniffi-bindgen generate src\nostr_sdk.udl --language python --no-format -o bindings-python\src\nostr-sdk + cargo run -p uniffi-bindgen generate --library ..\..\target\release\nostr_sdk_ffi.dll --language python --no-format -o bindings-python\src\nostr-sdk copy ..\..\target\release\nostr_sdk_ffi.dll bindings-python\src\nostr-sdk del /F /Q bindings-python\dist\* cd bindings-python && python setup.py --verbose bdist_wheel diff --git a/bindings/nostr-sdk-ffi/bindings-android/lib/proguard-rules.pro b/bindings/nostr-sdk-ffi/bindings-android/lib/proguard-rules.pro index 3048d83ab..138837183 100644 --- a/bindings/nostr-sdk-ffi/bindings-android/lib/proguard-rules.pro +++ b/bindings/nostr-sdk-ffi/bindings-android/lib/proguard-rules.pro @@ -24,7 +24,9 @@ -dontwarn java.awt.* -keep class com.sun.jna.* { *; } -keep class rust.nostr.sdk.* { *; } +-keep class nostr.** { *; } -keep class nostr_sdk.** { *; } -keepclassmembers class * extends rust.nostr.sdk.* { public *; } +-keepclassmembers class * extends nostr.** { public *; } -keepclassmembers class * extends nostr_sdk.** { public *; } -keepclassmembers class * extends com.sun.jna.* { public *; } diff --git a/bindings/nostr-sdk-ffi/bindings-python/.gitignore b/bindings/nostr-sdk-ffi/bindings-python/.gitignore index 2711ef622..cb773e3d4 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/.gitignore +++ b/bindings/nostr-sdk-ffi/bindings-python/.gitignore @@ -8,6 +8,7 @@ libnostr_sdk_ffi.dylib *.swp +src/nostr-sdk/nostr.py src/nostr-sdk/nostr_sdk.py src/nostr-sdk/*.so *.whl diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/bot.py b/bindings/nostr-sdk-ffi/bindings-python/examples/bot.py index 21ccce2a0..6251361ce 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/bot.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/bot.py @@ -14,9 +14,9 @@ client = Client(keys) -client.add_relay("wss://relay.damus.io") -client.add_relay("wss://nostr.mom") -client.add_relay("wss://nostr.oxtr.dev") +client.add_relay("wss://relay.damus.io", None) +client.add_relay("wss://nostr.mom", None) +client.add_relay("wss://nostr.oxtr.dev", None) client.connect() filter = Filter().pubkey(pk).kind(4).since(Timestamp.now()) diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/client-with-opts.py b/bindings/nostr-sdk-ffi/bindings-python/examples/client-with-opts.py index 87d48187c..0a30ecb9a 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/client-with-opts.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/client-with-opts.py @@ -8,7 +8,7 @@ opts = Options().send_timeout(timedelta(seconds=10)) client = Client.with_opts(keys, opts) -client.add_relay("wss://relay.damus.io") +client.add_relay("wss://relay.damus.io", None) client.connect() event = EventBuilder.new_text_note("Hello from Rust Nostr Python bindings!", []).to_event(keys) diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/client.py b/bindings/nostr-sdk-ffi/bindings-python/examples/client.py index 38c9a5c79..ea414b2f0 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/client.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/client.py @@ -7,7 +7,7 @@ client = Client(keys) -client.add_relay("wss://relay.damus.io") +client.add_relay("wss://relay.damus.io", None) client.connect() print("Mining a POW text note...") diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/database.py b/bindings/nostr-sdk-ffi/bindings-python/examples/database.py index eb7ebba43..cd0d18f10 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/database.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/database.py @@ -8,8 +8,8 @@ database = NostrDatabase.sqlite("nostr.db") client = ClientBuilder(keys).database(database).build() -client.add_relay("wss://relay.damus.io") -client.add_relay("wss://atl.purplerelay.com") +client.add_relay("wss://relay.damus.io", None) +client.add_relay("wss://atl.purplerelay.com", None) client.connect() # Negentropy reconciliation diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/metadata.py b/bindings/nostr-sdk-ffi/bindings-python/examples/metadata.py index 3f02419df..89f961b41 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/metadata.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/metadata.py @@ -5,7 +5,7 @@ client = Client(keys) -client.add_relay("wss://relay.damus.io") +client.add_relay("wss://relay.damus.io", None) client.connect() # Set metadata diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/nip94.py b/bindings/nostr-sdk-ffi/bindings-python/examples/nip94.py index 3ddebbb6d..783a69132 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/nip94.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/nip94.py @@ -5,7 +5,7 @@ client = Client(keys) -client.add_relay("wss://relay.damus.io") +client.add_relay("wss://relay.damus.io", None) client.add_relay("ws://jgqaglhautb4k6e6i2g34jakxiemqp6z4wynlirltuukgkft2xuglmqd.onion", "127.0.0.1:9050") client.connect() diff --git a/bindings/nostr-sdk-ffi/bindings-python/examples/relays.py b/bindings/nostr-sdk-ffi/bindings-python/examples/relays.py index 8ddf8e6ac..8fd2d629b 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/examples/relays.py +++ b/bindings/nostr-sdk-ffi/bindings-python/examples/relays.py @@ -4,9 +4,9 @@ keys = Keys.generate() client = Client(keys) -client.add_relay("wss://relay.damus.io") -client.add_relay("wss://nostr.wine") -client.add_relay("wss://relay.nostr.info") +client.add_relay("wss://relay.damus.io", None) +client.add_relay("wss://nostr.wine", None) +client.add_relay("wss://relay.nostr.info", None) client.connect() while True: diff --git a/bindings/nostr-sdk-ffi/bindings-python/src/nostr-sdk/__init__.py b/bindings/nostr-sdk-ffi/bindings-python/src/nostr-sdk/__init__.py index 5085043a4..cfb7c0aa7 100644 --- a/bindings/nostr-sdk-ffi/bindings-python/src/nostr-sdk/__init__.py +++ b/bindings/nostr-sdk-ffi/bindings-python/src/nostr-sdk/__init__.py @@ -1 +1,2 @@ -from nostr_sdk.nostr_sdk import * +from nostr_sdk.nostr import * +from nostr_sdk.nostr_sdk import * \ No newline at end of file diff --git a/bindings/nostr-sdk-ffi/build.rs b/bindings/nostr-sdk-ffi/build.rs index f8dd52519..056073af1 100644 --- a/bindings/nostr-sdk-ffi/build.rs +++ b/bindings/nostr-sdk-ffi/build.rs @@ -8,7 +8,6 @@ const DEFAULT_CLANG_VERSION: &str = "14.0.7"; fn main() { setup_x86_64_android_workaround(); - uniffi::generate_scaffolding("./src/nostr_sdk.udl").expect("Building the UDL file failed"); } /// Adds a temporary workaround for an issue with the Rust compiler and Android diff --git a/bindings/nostr-sdk-ffi/src/client/builder.rs b/bindings/nostr-sdk-ffi/src/client/builder.rs index ee34808ee..d23c1a1b8 100644 --- a/bindings/nostr-sdk-ffi/src/client/builder.rs +++ b/bindings/nostr-sdk-ffi/src/client/builder.rs @@ -7,11 +7,12 @@ use std::sync::Arc; use nostr_ffi::helper::unwrap_or_clone_arc; use nostr_ffi::Keys; use nostr_sdk::database::DynNostrDatabase; +use uniffi::Object; use super::{Client, ClientSdk, Options}; use crate::database::NostrDatabase; -#[derive(Clone)] +#[derive(Clone, Object)] pub struct ClientBuilder { inner: nostr_sdk::ClientBuilder, } @@ -22,12 +23,14 @@ impl From for ClientBuilder { } } +#[uniffi::export] impl ClientBuilder { /// New client builder - pub fn new(keys: Arc) -> Self { - Self { + #[uniffi::constructor] + pub fn new(keys: Arc) -> Arc { + Arc::new(Self { inner: nostr_sdk::ClientBuilder::new(keys.as_ref().deref()), - } + }) } pub fn database(self: Arc, database: Arc) -> Arc { diff --git a/bindings/nostr-sdk-ffi/src/client/mod.rs b/bindings/nostr-sdk-ffi/src/client/mod.rs index aab2c2e15..4d5c03443 100644 --- a/bindings/nostr-sdk-ffi/src/client/mod.rs +++ b/bindings/nostr-sdk-ffi/src/client/mod.rs @@ -14,6 +14,7 @@ use nostr_ffi::{ use nostr_sdk::client::blocking::Client as ClientSdk; use nostr_sdk::relay::RelayPoolNotification as RelayPoolNotificationSdk; use nostr_sdk::{NegentropyOptions, Options as OptionsSdk}; +use uniffi::Object; mod builder; mod options; @@ -23,6 +24,7 @@ pub use self::options::Options; use crate::error::Result; use crate::{NostrDatabase, Relay}; +#[derive(Object)] pub struct Client { inner: ClientSdk, } @@ -33,19 +35,22 @@ impl From for Client { } } +#[uniffi::export] impl Client { - pub fn new(keys: Arc) -> Self { + #[uniffi::constructor] + pub fn new(keys: Arc) -> Arc { let opts: OptionsSdk = OptionsSdk::new().shutdown_on_drop(true); - Self { + Arc::new(Self { inner: ClientSdk::with_opts(keys.as_ref().deref(), opts), - } + }) } - pub fn with_opts(keys: Arc, opts: Arc) -> Self { + #[uniffi::constructor] + pub fn with_opts(keys: Arc, opts: Arc) -> Arc { let opts: OptionsSdk = opts.as_ref().deref().clone().shutdown_on_drop(true); - Self { + Arc::new(Self { inner: ClientSdk::with_opts(keys.as_ref().deref(), opts), - } + }) } // TODO: add with_remote_signer @@ -266,6 +271,7 @@ impl Client { } } +#[uniffi::export(callback_interface)] pub trait HandleNotification: Send + Sync + Debug { fn handle_msg(&self, relay_url: String, msg: RelayMessage); fn handle(&self, relay_url: String, event: Arc); diff --git a/bindings/nostr-sdk-ffi/src/client/options.rs b/bindings/nostr-sdk-ffi/src/client/options.rs index b0654739a..c0d8e7519 100644 --- a/bindings/nostr-sdk-ffi/src/client/options.rs +++ b/bindings/nostr-sdk-ffi/src/client/options.rs @@ -6,8 +6,9 @@ use std::sync::Arc; use std::time::Duration; use nostr_ffi::helper::unwrap_or_clone_arc; +use uniffi::Object; -#[derive(Clone)] +#[derive(Clone, Object)] pub struct Options { inner: nostr_sdk::Options, } @@ -25,11 +26,13 @@ impl From for Options { } } +#[uniffi::export] impl Options { - pub fn new() -> Self { - Self { + #[uniffi::constructor] + pub fn new() -> Arc { + Arc::new(Self { inner: nostr_sdk::Options::new(), - } + }) } pub fn wait_for_connection(self: Arc, wait: bool) -> Arc { diff --git a/bindings/nostr-sdk-ffi/src/database.rs b/bindings/nostr-sdk-ffi/src/database.rs index 54659f878..6dcc8e865 100644 --- a/bindings/nostr-sdk-ffi/src/database.rs +++ b/bindings/nostr-sdk-ffi/src/database.rs @@ -7,9 +7,11 @@ use std::sync::Arc; use nostr_ffi::{Event, EventId, Filter, Metadata, PublicKey}; use nostr_sdk::database::{DynNostrDatabase, IntoNostrDatabase, NostrDatabaseExt}; use nostr_sdk::{block_on, SQLiteDatabase}; +use uniffi::Object; use crate::error::Result; +#[derive(Object)] pub struct NostrDatabase { inner: Arc, } @@ -26,13 +28,15 @@ impl From<&NostrDatabase> for Arc { } } +#[uniffi::export] impl NostrDatabase { - pub fn sqlite(path: String) -> Result { + #[uniffi::constructor] + pub fn sqlite(path: String) -> Result> { block_on(async move { let db = Arc::new(SQLiteDatabase::open(path).await?); - Ok(Self { + Ok(Arc::new(Self { inner: db.into_nostr_database(), - }) + })) }) } diff --git a/bindings/nostr-sdk-ffi/src/error.rs b/bindings/nostr-sdk-ffi/src/error.rs index 9ff2fbe0e..9ff420bd6 100644 --- a/bindings/nostr-sdk-ffi/src/error.rs +++ b/bindings/nostr-sdk-ffi/src/error.rs @@ -5,10 +5,11 @@ use std::fmt; use std::net::AddrParseError; use tracing::subscriber::SetGlobalDefaultError; +use uniffi::Error; pub type Result = std::result::Result; -#[derive(Debug)] +#[derive(Debug, Error)] pub enum NostrSdkError { Generic { err: String }, } diff --git a/bindings/nostr-sdk-ffi/src/lib.rs b/bindings/nostr-sdk-ffi/src/lib.rs index bfb67c8c5..0906e83d9 100644 --- a/bindings/nostr-sdk-ffi/src/lib.rs +++ b/bindings/nostr-sdk-ffi/src/lib.rs @@ -3,6 +3,14 @@ #![allow(clippy::new_without_default)] +pub use nostr_ffi::{ + generate_shared_key, get_nip05_profile, git_hash_version, nip04_decrypt, nip04_encrypt, + verify_nip05, Alphabet, ClientMessage, Contact, Event, EventBuilder, EventId, FileMetadata, + Filter, ImageDimensions, Keys, Metadata, NostrConnectURI, NostrError, Profile, PublicKey, + RelayInformationDocument, RelayMessage, SecretKey, Tag, TagEnum, TagKind, TagKindKnown, + Timestamp, UnsignedEvent, ZapRequestData, +}; + mod client; mod database; mod error; @@ -14,24 +22,10 @@ trait FromResult: Sized { fn from_result(_: T) -> error::Result; } -// External -pub use nostr_ffi::{ - generate_shared_key, get_nip05_profile, git_hash_version, nip04_decrypt, nip04_encrypt, - verify_nip05, ClientMessage, Contact, Event, EventBuilder, EventId, FileMetadata, Filter, - ImageDimensions, Keys, Metadata, NostrConnectURI, NostrError, Profile, PublicKey, - RelayInformationDocument, RelayMessage, SecretKey, Tag, TagEnum, TagKind, TagKindKnown, - Timestamp, UnsignedEvent, ZapRequestData, -}; -pub use nostr_sdk::{Alphabet, RelayStatus}; - -// Namespace -pub use crate::logger::{init_logger, LogLevel}; - -// Nostr SDK pub use crate::client::{Client, ClientBuilder, HandleNotification, Options}; pub use crate::database::NostrDatabase; pub use crate::error::NostrSdkError; -pub use crate::relay::{ActiveSubscription, Relay, RelayConnectionStats}; +pub use crate::logger::{init_logger, LogLevel}; +pub use crate::relay::{ActiveSubscription, Relay, RelayConnectionStats, RelayStatus}; -// UDL -uniffi::include_scaffolding!("nostr_sdk"); +uniffi::setup_scaffolding!("nostr_sdk"); diff --git a/bindings/nostr-sdk-ffi/src/logger.rs b/bindings/nostr-sdk-ffi/src/logger.rs index c2339cff1..6ea23ae9e 100644 --- a/bindings/nostr-sdk-ffi/src/logger.rs +++ b/bindings/nostr-sdk-ffi/src/logger.rs @@ -2,9 +2,11 @@ // Distributed under the MIT software license use tracing::Level; +use uniffi::Enum; use crate::error::Result; +#[derive(Enum)] pub enum LogLevel { Error, Warn, @@ -25,6 +27,7 @@ impl From for Level { } } +#[uniffi::export] pub fn init_logger(level: LogLevel) -> Result<()> { let level: Level = level.into(); let subscriber = tracing_subscriber::FmtSubscriber::builder() diff --git a/bindings/nostr-sdk-ffi/src/nostr_sdk.udl b/bindings/nostr-sdk-ffi/src/nostr_sdk.udl deleted file mode 100644 index 2f4fdee34..000000000 --- a/bindings/nostr-sdk-ffi/src/nostr_sdk.udl +++ /dev/null @@ -1,709 +0,0 @@ -// Copyright (c) 2022-2023 Yuki Kishimoto -// Distributed under the MIT software license - -namespace nostr_sdk { - string git_hash_version(); - - // Nostr - [Throws=NostrError] - sequence generate_shared_key(SecretKey secret_key, PublicKey public_key); - - [Throws=NostrError] - string nip04_encrypt(SecretKey secret_key, PublicKey public_key, string content); - [Throws=NostrError] - string nip04_decrypt(SecretKey secret_key, PublicKey public_key, string encrypted_content); - - [Throws=NostrError] - void verify_nip05(PublicKey public_key, string nip05, string? proxy); - [Throws=NostrError] - Profile get_nip05_profile(string nip05, string? proxy); - - // Nostr SDK - [Throws=NostrSdkError] - void init_logger(LogLevel level); -}; - -[Error] -interface NostrSdkError { - Generic(string err); -}; - -enum LogLevel { - "Error", - "Warn", - "Info", - "Debug", - "Trace", -}; - -// NOSTR - -[Error] -interface NostrError { - Generic(string err); -}; - -interface RelayInformationDocument { - [Throws=NostrError, Name=get] - constructor(string url, string? proxy); - string? name(); - string? description(); - string? pubkey(); - string? contact(); - sequence? supported_nips(); - string? software(); - string? version(); -}; - -interface NostrConnectURI { - [Throws=NostrError, Name=from_string] - constructor(string uri); - PublicKey public_key(); - string relay_url(); - string name(); - string? url(); - string? description(); -}; - -interface Profile { - constructor(PublicKey public_key, sequence relays); - [Throws=NostrError, Name=from_bech32] - constructor(string bech32); - [Throws=NostrError, Name=from_nostr_uri] - constructor(string uri); - [Throws=NostrError] - string to_bech32(); - [Throws=NostrError] - string to_nostr_uri(); - PublicKey public_key(); - sequence relays(); -}; - -interface ImageDimensions { - constructor(u64 width, u64 height); - u64 width(); - u64 height(); -}; - -interface Timestamp { - [Name=now] - constructor(); - [Name=from_secs] - constructor(u64 secs); - u64 as_secs(); - string to_human_datetime(); -}; - -interface SecretKey { - [Throws=NostrError, Name=from_hex] - constructor(string hex); - [Throws=NostrError, Name=from_bech32] - constructor(string sk); - [Throws=NostrError, Name=from_bytes] - constructor(sequence sk); - string to_hex(); - [Throws=NostrError] - string to_bech32(); -}; - -interface PublicKey { - [Throws=NostrError, Name=from_hex] - constructor(string hex); - [Throws=NostrError, Name=from_bech32] - constructor(string pk); - [Throws=NostrError, Name=from_bytes] - constructor(sequence pk); - [Throws=NostrError, Name=from_nostr_uri] - constructor(string uri); - string to_hex(); - [Throws=NostrError] - string to_bech32(); - [Throws=NostrError] - string to_nostr_uri(); -}; - -interface Keys { - constructor(SecretKey sk); - [Name=from_public_key] - constructor(PublicKey pk); - [Throws=NostrError, Name=from_sk_str] - constructor(string sk); - [Throws=NostrError, Name=from_pk_str] - constructor(string pk); - [Name=generate] - constructor(); - [Throws=NostrError, Name=vanity] - constructor(sequence prefixes, boolean bech32, u8 num_cores); - [Throws=NostrError, Name=from_mnemonic] - constructor(string mnemonic, optional string? passphrase = null); - PublicKey public_key(); - [Throws=NostrError] - SecretKey secret_key(); -}; - -[Enum] -interface ClientMessage { - Ev(string event); - Req(string subscription_id, sequence filters); - Count(string subscription_id, sequence filters); - Close(string subscription_id); - Auth(string event); -}; - -[Enum] -interface RelayMessage { - Ev(string subscription_id, string event); - Notice(string message); - EndOfStoredEvents(string subscription_id); - Ok(string event_id, boolean status, string message); - Auth(string challenge); - Count(string subscription_id, u64 count); - NegMsg(string subscription_id, string message); - NegErr(string subscription_id, string code); -}; - -interface ZapRequestData { - constructor(PublicKey public_key, sequence relays); - [Self=ByArc] - ZapRequestData amount(u64 amount); - [Self=ByArc] - ZapRequestData lnurl(string lnurl); - [Self=ByArc] - ZapRequestData event_id(EventId event_id); -}; - -enum Alphabet { - "A", - "B", - "C", - "D", - "E", - "F", - "G", - "H", - "I", - "J", - "K", - "L", - "M", - "N", - "O", - "P", - "Q", - "R", - "S", - "T", - "U", - "V", - "W", - "X", - "Y", - "Z", -}; - -interface Filter { - constructor(); - [Self=ByArc] - Filter id(EventId id); - [Self=ByArc] - Filter ids(sequence ids); - [Self=ByArc] - Filter author(PublicKey author); - [Self=ByArc] - Filter authors(sequence authors); - [Self=ByArc] - Filter kind(u64 kind); - [Self=ByArc] - Filter kinds(sequence kinds); - [Self=ByArc] - Filter event(EventId event_id); - [Self=ByArc] - Filter events(sequence ids); - [Self=ByArc] - Filter pubkey(PublicKey pubkey); - [Self=ByArc] - Filter pubkeys(sequence pubkeys); - [Self=ByArc] - Filter identifier(string identifier); - [Self=ByArc] - Filter search(string text); - [Self=ByArc] - Filter since(Timestamp timestamp); - [Self=ByArc] - Filter until(Timestamp timestamp); - [Self=ByArc] - Filter limit(u64 limit); - [Self=ByArc] - Filter custom_tag(Alphabet tag, sequence content); - boolean match_event(Event event); - [Throws=NostrError, Name=from_json] - constructor(string json); - string as_json(); -}; - -interface EventId { - [Throws=NostrError] - constructor(PublicKey pubkey, Timestamp created_at, u64 kind, sequence> tags, string content); - [Throws=NostrError, Name=from_bytes] - constructor(sequence bytes); - [Throws=NostrError, Name=from_hex] - constructor(string hex); - [Throws=NostrError, Name=from_bech32] - constructor(string id); - [Throws=NostrError, Name=from_nostr_uri] - constructor(string uri); - sequence as_bytes(); - string to_hex(); - [Throws=NostrError] - string to_bech32(); - [Throws=NostrError] - string to_nostr_uri(); -}; - -interface UnsignedEvent { - EventId id(); - PublicKey pubkey(); - Timestamp created_at(); - u64 kind(); - sequence tags(); - string content(); - [Throws=NostrError] - Event sign(Keys keys); - [Throws=NostrError] - Event add_signature(string sig); - [Throws=NostrError, Name=from_json] - constructor(string json); - string as_json(); -}; - -interface Event { - EventId id(); - PublicKey pubkey(); - Timestamp created_at(); - u64 kind(); - sequence tags(); - string content(); - string signature(); - boolean verify(); - [Throws=NostrError, Name=from_json] - constructor(string json); - string as_json(); -}; - -interface EventBuilder { - [Throws=NostrError] - constructor(u64 kind, string content, sequence tags); - [Throws=NostrError] - Event to_event(Keys keys); - [Throws=NostrError] - Event to_pow_event(Keys keys, u8 difficulty); - UnsignedEvent to_unsigned_event(PublicKey public_key); - UnsignedEvent to_unsigned_pow_event(PublicKey public_key, u8 difficulty); - - [Name=set_metadata] - constructor(Metadata metadata); - [Throws=NostrError, Name=add_recommended_relay] - constructor(string url); - [Throws=NostrError, Name=new_text_note] - constructor(string content, sequence tags); - [Throws=NostrError, Name=long_form_text_note] - constructor(string content, sequence tags); - [Name=repost] - constructor(EventId event_id, PublicKey public_key); - [Name=set_contact_list] - constructor(sequence list); - [Throws=NostrError, Name=new_encrypted_direct_msg] - constructor(Keys sender_keys, PublicKey receiver_pubkey, string content, EventId? reply_to); - [Name=delete] - constructor(sequence ids, optional string? reason = null); - [Name=new_reaction] - constructor(EventId event_id, PublicKey public_key, string content); - - [Name=new_channel] - constructor(Metadata metadata); - [Throws=NostrError, Name=set_channel_metadata] - constructor(string channel_id, string? relay_url, Metadata metadata); - [Throws=NostrError, Name=new_channel_msg] - constructor(string channel_id, string relay_url, string content); - [Name=hide_channel_msg] - constructor(EventId message_id, string? reason); - [Name=mute_channel_user] - constructor(PublicKey public_key, string? reason); - - [Throws=NostrError, Name=auth] - constructor(string challenge, string relay_url); - - [Name=report] - constructor(sequence tags, string content); - - [Name=new_zap_request] - constructor(ZapRequestData data); - [Name=new_zap_receipt] - constructor(string bolt11, string? preimage, Event zap_request); - - [Name=file_metadata] - constructor(string description, FileMetadata metadata); -}; - -interface Contact { - constructor(PublicKey pk, optional string? relay_url = null, optional string? alias = null); - string? alias(); - PublicKey public_key(); - string? relay_url(); -}; - -interface Metadata { - constructor(); - - [Throws=NostrError, Name=from_json] - constructor(string json); - string as_json(); - - [Self=ByArc] - Metadata set_name(string name); - [Self=ByArc] - Metadata set_display_name(string display_name); - [Self=ByArc] - Metadata set_about(string about); - [Throws=NostrError, Self=ByArc] - Metadata set_website(string website); - [Throws=NostrError, Self=ByArc] - Metadata set_picture(string picture); - [Throws=NostrError, Self=ByArc] - Metadata set_banner(string banner); - [Self=ByArc] - Metadata set_nip05(string nip05); - [Self=ByArc] - Metadata set_lud06(string lud06); - [Self=ByArc] - Metadata set_lud16(string lud16); - [Self=ByArc] - Metadata set_custom_field(string key, string value); - - string? get_name(); - string? get_display_name(); - string? get_about(); - string? get_website(); - string? get_picture(); - string? get_banner(); - string? get_nip05(); - string? get_lud06(); - string? get_lud16(); - string? get_custom_field(string key); -}; - -interface FileMetadata { - [Throws=NostrError] - constructor(string url, string mime_type, string hash); - [Self=ByArc] - FileMetadata aes_256_gcm(string key, string iv); - [Self=ByArc] - FileMetadata size(u64 size); - [Self=ByArc] - FileMetadata dimensions(ImageDimensions dim); - [Self=ByArc] - FileMetadata magnet(string magnet); - [Self=ByArc] - FileMetadata blurhash(string blurhash); -}; - -[Enum] -interface TagKind { - Known(TagKindKnown known); - Unknown(string unknown); -}; - -enum TagKindKnown { - "P", - "E", - "R", - "T", - "G", - "D", - "A", - "I", - "M", - "U", - "X", - "RelayUrl", - "Nonce", - "Delegation", - "ContentWarning", - "Expiration", - "Subject", - "Challenge", - "Title", - "Image", - "Thumb", - "Summary", - "PublishedAt", - "Description", - "Bolt11", - "Preimage", - "Relays", - "Amount", - "Lnurl", - "Name", - "Url", - "Aes256Gcm", - "Size", - "Dim", - "Magnet", - "Blurhash", - "Streaming", - "Recording", - "Starts", - "Ends", - "Status", - "CurrentParticipants", - "TotalParticipants", - "Method", - "Payload", - "Anon", - "Proxy", - "Emoji", - "Request", -}; - -[Enum] -interface TagEnum { - Unknown(TagKind kind, sequence data); - E(string event_id, string? relay_url, string? marker); - PubKey(string public_key, string? relay_url); - EventReport(string event_id, string report); - PubKeyReport(string public_key, string report); - PubKeyLiveEvent(string pk, string? relay_url, string marker, string? proof); - Reference(string reference); - RelayMetadata(string relay_url, string? rw); - Hashtag(string hashtag); - Geohash(string geohash); - Identifier(string identifier); - ExternalIdentity(string identity, string proof); - A(u64 kind, string public_key, string identifier, string? relay_url); - RelayUrl(string relay_url); - ContactList(string pk, string? relay_url, string? alias); - POW(string nonce, u8 difficulty); - Delegation(string delegator_pk, string conditions, string sig); - ContentWarning(string? reason); - Expiration(u64 timestamp); - Subject(string subject); - Challenge(string challenge); - Title(string title); - Image(string url, string? dimensions); - Thumb(string url, string? dimensions); - Summary(string summary); - Description(string desc); - Bolt11(string bolt11); - Preimage(string preimage); - Relays(sequence urls); - Amount(u64 millisats, string? bolt11); - Lnurl(string lnurl); - Name(string name); - PublishedAt(u64 timestamp); - Url(string url); - MimeType(string mime); - Aes256Gcm(string key, string iv); - Sha256(string hash); - Size(u64 size); - Dim(string dimensions); - Magnet(string uri); - Blurhash(string blurhash); - Streaming(string url); - Recording(string url); - Starts(u64 timestamp); - Ends(u64 timestamp); - LiveEventStatus(string status); - CurrentParticipants(u64 num); - TotalParticipants(u64 num); - AbsoluteURL(string url); - Method(string method); - Payload(string hash); - Anon(string? msg); - Proxy(string id, string protocol); - Emoji(string shortcode, string url); - Request(string event); - DataVendingMachineStatus(string status, string? extra_info); -}; - -interface Tag { - [Throws=NostrError, Name=parse] - constructor(sequence data); - [Throws=NostrError, Name=from_enum] - constructor(TagEnum e); - TagEnum as_enum(); - sequence as_vec(); - TagKind kind(); -}; - -// NOSTR-SDK - -interface RelayConnectionStats { - u64 attempts(); - u64 success(); - f64 uptime(); - u64 bytes_sent(); - u64 bytes_received(); - duration? latency(); - Timestamp connected_at(); -}; - -enum RelayStatus { - "Initialized", - "Pending", - "Connecting", - "Connected", - "Disconnected", - "Stopped", - "Terminated", -}; - -interface ActiveSubscription { - string id(); - sequence filters(); -}; - -interface Relay { - string url(); - string? proxy(); - RelayStatus status(); - boolean is_connected(); - RelayInformationDocument document(); - record subscriptions(); - void update_subscription_filters(string internal_id, sequence filters); - RelayConnectionStats stats(); - u64 queue(); - - void connect(boolean wait_for_connection); - [Throws=NostrSdkError] - void stop(); - [Throws=NostrSdkError] - void terminate(); - - [Throws=NostrSdkError] - void send_msg(ClientMessage msg, duration? wait); - [Throws=NostrSdkError] - void subscribe(sequence filters, duration? wait); - [Throws=NostrSdkError] - void unsubscribe(duration? wait); - - [Throws=NostrSdkError] - sequence get_events_of(sequence filters, duration timeout); - void req_events_of(sequence filters, duration timeout); -}; - -interface NostrDatabase { - [Throws=NostrSdkError, Name=sqlite] - constructor(string path); - - [Throws=NostrSdkError] - boolean save_event(Event event); - [Throws=NostrSdkError] - sequence? event_seen_on_relays(EventId event_id); - [Throws=NostrSdkError] - Event event_by_id(EventId event_id); - [Throws=NostrSdkError] - u64 count(sequence filters); - [Throws=NostrSdkError] - sequence query(sequence filters); - [Throws=NostrSdkError] - void wipe(); - [Throws=NostrSdkError] - Metadata profile(PublicKey public_key); -}; - -interface Options { - constructor(); - [Self=ByArc] - Options wait_for_connection(boolean wait); - [Self=ByArc] - Options wait_for_send(boolean wait); - [Self=ByArc] - Options wait_for_subscription(boolean wait); - [Self=ByArc] - Options difficulty(u8 difficulty); - [Self=ByArc] - Options req_filters_chunk_size(u8 req_filters_chunk_size); - [Self=ByArc] - Options skip_disconnected_relays(boolean skip); - [Self=ByArc] - Options timeout(duration timeout); - [Self=ByArc] - Options send_timeout(duration? send_timeout); - [Self=ByArc] - Options nip46_timeout(duration? nip46_timeout); -}; - -interface ClientBuilder { - constructor(Keys keys); - [Self=ByArc] - ClientBuilder opts(Options opts); - [Self=ByArc] - ClientBuilder database(NostrDatabase database); - Client build(); -}; - -interface Client { - constructor(Keys keys); - [Name=with_opts] - constructor(Keys keys, Options opts); - - void update_difficulty(u8 difficulty); - Keys keys(); - NostrDatabase database(); - - void start(); - [Throws=NostrSdkError] - void stop(); - boolean is_running(); - [Throws=NostrSdkError] - void shutdown(); - - record relays(); - [Throws=NostrSdkError] - Relay relay(string url); - [Throws=NostrSdkError] - boolean add_relay(string url, optional string? proxy = null); - [Throws=NostrSdkError] - void remove_relay(string url); - [Throws=NostrSdkError] - void connect_relay(string url); - [Throws=NostrSdkError] - void disconnect_relay(string url); - void connect(); - [Throws=NostrSdkError] - void disconnect(); - - void subscribe(sequence filters); - void unsubscribe(); - - [Throws=NostrSdkError] - sequence get_events_of(sequence filters, duration? timeout); - void req_events_of(sequence filters, duration? timeout); - - [Throws=NostrSdkError] - void send_msg(ClientMessage msg); - [Throws=NostrSdkError] - void send_msg_to(string url, ClientMessage msg); - [Throws=NostrSdkError] - EventId send_event(Event event); - [Throws=NostrSdkError] - EventId send_event_to(string url, Event event); - - [Throws=NostrSdkError] - EventId set_metadata(Metadata metadata); - [Throws=NostrSdkError] - EventId send_direct_msg(PublicKey receiver, string msg, EventId? reply); - [Throws=NostrSdkError] - EventId file_metadata(string description, FileMetadata metadata); - - [Throws=NostrSdkError] - void reconcile(Filter filter); - - [Self=ByArc] - void handle_notifications(HandleNotification handler); -}; - -callback interface HandleNotification { - void handle_msg(string relay_url, RelayMessage msg); - void handle(string relay_url, Event event); -}; diff --git a/bindings/nostr-sdk-ffi/src/relay.rs b/bindings/nostr-sdk-ffi/src/relay.rs index 1b1f5297b..924bd10da 100644 --- a/bindings/nostr-sdk-ffi/src/relay.rs +++ b/bindings/nostr-sdk-ffi/src/relay.rs @@ -7,10 +7,12 @@ use std::{collections::HashMap, ops::Deref}; use nostr_ffi::{ClientMessage, Event, Filter, RelayInformationDocument, Timestamp}; use nostr_sdk::relay::InternalSubscriptionId; -use nostr_sdk::{block_on, relay, FilterOptions, RelayStatus}; +use nostr_sdk::{block_on, relay, FilterOptions}; +use uniffi::{Object, Enum}; use crate::error::Result; +#[derive(Object)] pub struct RelayConnectionStats { inner: relay::RelayConnectionStats, } @@ -21,6 +23,7 @@ impl From for RelayConnectionStats { } } +#[uniffi::export] impl RelayConnectionStats { pub fn attempts(&self) -> u64 { self.inner.attempts() as u64 @@ -36,7 +39,7 @@ impl RelayConnectionStats { pub fn connected_at(&self) -> Arc { let secs = self.inner.connected_at().as_u64(); - Arc::new(Timestamp::from_secs(secs)) + Timestamp::from_secs(secs) } pub fn bytes_sent(&self) -> u64 { @@ -52,6 +55,7 @@ impl RelayConnectionStats { } } +#[derive(Object)] pub struct ActiveSubscription { inner: relay::ActiveSubscription, } @@ -62,6 +66,7 @@ impl From for ActiveSubscription { } } +#[uniffi::export] impl ActiveSubscription { pub fn id(&self) -> String { self.inner.id().to_string() @@ -76,6 +81,39 @@ impl ActiveSubscription { } } +#[derive(Enum)] +pub enum RelayStatus { + /// Relay initialized + Initialized, + /// Pending + Pending, + /// Connecting + Connecting, + /// Relay connected + Connected, + /// Relay disconnected, will retry to connect again + Disconnected, + /// Stop + Stopped, + /// Relay completely disconnected + Terminated, +} + +impl From for RelayStatus { + fn from(value: nostr_sdk::RelayStatus) -> Self { + match value { + nostr_sdk::RelayStatus::Initialized => Self::Initialized, + nostr_sdk::RelayStatus::Pending => Self::Pending, + nostr_sdk::RelayStatus::Connecting => Self::Connecting, + nostr_sdk::RelayStatus::Connected => Self::Connected, + nostr_sdk::RelayStatus::Disconnected => Self::Disconnected, + nostr_sdk::RelayStatus::Stopped => Self::Stopped, + nostr_sdk::RelayStatus::Terminated => Self::Terminated, + } + } +} + +#[derive(Object)] pub struct Relay { inner: relay::Relay, } @@ -86,6 +124,7 @@ impl From for Relay { } } +#[uniffi::export] impl Relay { pub fn url(&self) -> String { self.inner.url().to_string() @@ -96,7 +135,7 @@ impl Relay { } pub fn status(&self) -> RelayStatus { - self.inner.status_blocking() + self.inner.status_blocking().into() } pub fn is_connected(&self) -> bool { diff --git a/bindings/nostr-sdk-ffi/uniffi.toml b/bindings/nostr-sdk-ffi/uniffi.toml index 19edbcf28..38905989e 100644 --- a/bindings/nostr-sdk-ffi/uniffi.toml +++ b/bindings/nostr-sdk-ffi/uniffi.toml @@ -1,10 +1,5 @@ [bindings.kotlin] package_name = "nostr_sdk" -cdylib_name = "nostr_sdk_ffi" [bindings.swift] ffi_module_filename = "nostr_sdkFFI" -cdylib_name = "nostr_sdk_ffi" - -[bindings.python] -cdylib_name = "nostr_sdk_ffi"