Oddbean new post about | logout
 I mean Rust. 
 Async makes Rust less fun and is overkill for small stuff 
 I'm happy with the Kotlin bindings as they are. 
 Ahh ok. I'll think about that. But it's pretty easy to write a blocking wrapper, including only the stuff you need. This could be a solution for your above request:

```toml
[dependencies]
nostr-sdk = "0.36"
tokio = { version = "1.41", features = ["full"] }
```

```rust
use std::sync::LazyLock;

use nostr_sdk::prelude::*;
use tokio::runtime::Runtime;

static RUNTIME: LazyLock<Runtime> = LazyLock::new(|| Runtime::new().unwrap());

pub struct ClientBlocking {
    inner: Client,
}

impl ClientBlocking {
    pub fn add_relay(&self, url: &str) -> Result<bool> {
        RUNTIME.block_on(async {
            Ok(self.inner.add_relay(url).await?)
        })
    }

    pub fn connect(&self) {
        RUNTIME.block_on(async {
            self.inner.connect().await
        })
    }

    pub fn send_event(&self, event: Event) -> Result<Output<EventId>> {
        RUNTIME.block_on(async {
            Ok(self.inner.send_event(event).await?)
        })
    }

    pub fn subscribe(&self, filters: Vec<Filter>) -> Result<Output<SubscriptionId>> {
        RUNTIME.block_on(async {
            Ok(self.inner.subscribe(filters, None).await?)
        })
    }

    pub fn handle_notifications<F>(&self, func: F) -> Result<()>
    where
        F: Fn(RelayPoolNotification) -> Result<bool>,
    {
        let mut notifications = self.inner.notifications();
        while let Ok(notification) = RUNTIME.block_on(notifications.recv()) {
            let shutdown: bool = RelayPoolNotification::Shutdown == notification;
            let exit: bool = func(notification)?;
            if exit || shutdown {
                break;
            }
        }
        Ok(())
    }
}
``` 
 With this I'd still have longer compile times and bigger binaries compared to a non async solution. 
 To reduce speed compilation you can disable all default features (I'll probably disable all feature by default in future) and, to reduce the binary size, change some `profile.release` config.

Tests for the example I shared yesterday:

Default features and default release profile: 
* compilation time: 43 secs
* cdylib size: 479kb
* staticlib size: 58Mb

Without default features but with default release profile:
* compilation time: 31 secs
* cdylib size: 479kb
* staticlib size: 49Mb

Without default features and with LTO enabled, codegen-units set to 1 and abort on panic (but still optimized for performance instead of size):
* compilation time: 35 secs
* cdylib size: 437kb
* staticlib size: 12Mb

Same as above but optimized for size (not aggressive):
* compilation time: 30 secs
* cdylib size: 427kb
* staticlib size: 9.5Mb

I not plan to write a sync version of the SDK, also if very very basic. But I can try to reduce the above values as much as possible.
 
 Thank you for running the numbers. Very interesting.