Expand description
§Pubky SDK
Ergonomic building blocks for Pubky apps: one facade (Pubky) plus focused actors for sessions, storage API, signer helpers, and QR auth flow for keyless apps.
Rust implementation of Pubky SDK.
§Install
# Cargo.toml
[dependencies]
pubky = "0.x" # this crate
# Optional helpers used in examples:
# pubky-testnet = "0.x"§Quick start
use pubky::prelude::*;
let pubky = Pubky::new()?; // or Pubky::testnet() for local testnet.
// 1) Create a new random key user and bound to a Signer
let keypair = Keypair::random();
let signer = pubky.signer(keypair);
// 2) Sign up on a homeserver (identified by its public key)
let homeserver = PublicKey::try_from("o4dksf...uyy").unwrap();
let session = signer.signup(&homeserver, None).await?;
// 3) Read/Write as the signed-in user
session.storage().put("/pub/my-cool-app/hello.txt", "hello").await?;
let body = session.storage().get("/pub/my-cool-app/hello.txt").await?.text().await?;
assert_eq!(&body, "hello");
// 4) Public read of another user’s file
let txt = pubky
.public_storage()
.get(format!(
"{}/pub/my-cool-app/hello.txt",
session.info().public_key()
))
.await?
.text().await?;
assert_eq!(txt, "hello");
// 5) Keyless app flow (QR/deeplink)
let caps = Capabilities::builder().write("/pub/example.com/").finish();
let flow = pubky.start_auth_flow(&caps, AuthFlowKind::signin())?;
println!("Scan to sign in: {}", flow.authorization_url());
let app_session = flow.await_approval().await?;
// 6) Optional (advanced): publish or resolve PKDNS (_pubky) records
signer.pkdns().publish_homeserver_if_stale(None).await?;
let resolved = signer.pkdns().get_homeserver().await;
println!("Your current homeserver: {:?}", resolved);
§Key formats (display vs transport)
PublicKey has two string representations:
- Display format:
pubky<z32>(used for logs/UI and human-facing identifiers). - Transport/storage format: raw
z32(used for hostnames, headers, query params, serde/JSON, and database storage).
Use .z32() whenever you are building hostnames or transport values (for example _pubky.<z32> or the pubky-host header). Use Display/.to_string() when you want the prefixed identifier for people.
§Reuse a single facade across your app
Use a shared Pubky (via cloning it, passing down as argument or behind OnceCell) instead of constructing one per request. This avoids reinitializing transports and keeps the same client available for repeated usage.
§Mental model
Pubky- facade, always start here! Owns the transport and constructs actors.PubkySigner- local key holder. Cansignup,signin, approve QR auth, publish PKDNS.PubkySession- authenticated “as me” handle. Exposes session-scoped storage.PublicStorage- unauthenticated reads of others’ public data.Pkdns- resolve/publish_pubkyrecords.
§Transport:
PubkyHttpClient: handles requests to pubky public-key hosts.
§Examples
§Storage API (session & public)
Session (authenticated):
use pubky::{Pubky, Keypair};
let pubky = Pubky::new()?;
let session = pubky.signer(keypair).signin().await?;
let storage = session.storage();
storage.put("/pub/my-cool-app/data.txt", "hi").await?;
let text = storage.get("/pub/my-cool-app/data.txt").await?.text().await?;
Public (read-only):
use pubky::{Pubky, PublicKey};
let pubky = Pubky::new()?;
let public = pubky.public_storage();
let file = public
.get(format!("{user_id}/pub/example.com/file.bin"))
.await?
.bytes()
.await?;
let entries = public
.list(format!("{user_id}/pub/example.com/"))?
.limit(10)
.send()
.await?;
for entry in entries {
println!("{}", entry.to_pubky_url());
}
See the Public Storage example.
Path rules:
- Session storage uses absolute paths like
"/pub/app/file.txt". - Public storage uses addressed form
pubky<user>/pub/app/file.txt(preferred) orpubky://<user>/....
Convention: put your app’s public data under a domain-like folder in /pub, e.g. /pub/my-new-app/.
§Resolve identifiers into transport URLs
Need to feed a public resource into a raw HTTP client? Use resolve_pubky to transform the human-facing identifier into the HTTPS homeserver URL:
let url = resolve_pubky("pubkyoperrr8wsbpr3ue9d4qj41ge1kcc6r7fdiy6o3ugjrrhi4y77rdo/pub/pubky.app/posts/0033X02JAN0SG")?;
assert_eq!(
url.as_str(),
"https://_pubky.operrr8wsbpr3ue9d4qj41ge1kcc6r7fdiy6o3ugjrrhi4y77rdo/pub/pubky.app/posts/0033X02JAN0SG"
);§PKDNS (Pkarr)
Resolve another user’s homeserver (_pubky record), or publish your own via the signer.
use pubky::{Pubky, PublicKey, Keypair};
let pubky = Pubky::new()?;
// read-only homeserver resolver
let host = pubky.get_homeserver_of(&other).await;
// publish with your key
let signer = pubky.signer(Keypair::random());
signer.pkdns().publish_homeserver_if_stale(None).await?;
// or force republish (e.g. homeserver migration)
signer.pkdns().publish_homeserver_force(Some(&new_homeserver_id)).await?;
// resolve your own homeserver
signer.pkdns().get_homeserver().await?;
§Pubky QR auth for third-party and keyless apps
Request an authorization URL and await approval.
Typical usage:
- Start an auth flow with
pubky.start_auth_flow(&caps)(or use thePubkyAuthFlow::builder()to set a custom relay). - Show
authorization_url()(QR/deeplink) to the signing device (e.g., Pubky Ring — iOS / Android). - Await
await_approval()to obtain a session-boundPubkySession.
let pubky = Pubky::new()?;
// Read/Write capabilities for acme.app route
let caps = Capabilities::builder().read_write("pub/example.com/").finish();
// Start the flow using the default relay (see “Relay & reliability” below)
let flow = pubky.start_auth_flow(&caps, AuthFlowKind::signin())?;
println!("Scan to sign in: {}", flow.authorization_url());
// On the signing device, approve with: signer.approve_auth(flow.authorization_url()).await?;
let session = flow.await_approval().await?;
Approve an auth request
signer.approve_auth(authorization_url).await?;See the fully functional Auth Flow Example.
§Relay & reliability
- If you don’t specify a relay,
PubkyAuthFlowdefaults to a Synonym-hosted relay. If that relay is down, logins won’t complete. - For production and larger apps, run your own relay (MIT, Docker): https://httprelay.io.
The channel is derived as
base64url(hash(secret)); the token is end-to-end encrypted with thesecretand cannot be decrypted by the relay.
Custom relay example
let pubky = Pubky::new()?;
let caps = Capabilities::builder().read("pub/example.com/").finish();
let auth_flow = PubkyAuthFlow::builder(&caps, AuthFlowKind::signin())
.client(pubky.client().clone())
.relay(url::Url::parse("http://localhost:8080/link/")?) // your relay
.start()?;Tip: reuse
pubky.client()when customising the relay so the flow shares TLS and pkarr configuration with the rest of your application.
§Features
json: enableStoragehelpers (.get_json()/.put_json()) and serde on certain types.
# Cargo.toml
[dependencies]
pubky = { version = "x.y.z", features = ["json"] }§Testing locally
Spin up an ephemeral testnet (DHT + homeserver + relay) and run your tests fully offline:
let testnet = EphemeralTestnet::builder().build().await.unwrap();
let homeserver = testnet.homeserver_app();
let pubky = testnet.sdk()?;
let signer = pubky.signer(Keypair::random());
let session = signer.signup(&homeserver.public_key().into(), None).await?;
session.storage().put("/pub/my-cool-app/hello.txt", "hi").await?;
let s = session.storage().get("/pub/my-cool-app/hello.txt").await?.text().await?;
assert_eq!(s, "hi");
§Keypair and Session persistence
Encrypted Keypair secrets (.pkarr):
use pubky::Pubky;
let pubky = Pubky::new()?;
let signer = pubky.signer_from_recovery_file("/path/to/alice.pkarr", "passphrase")?;Session secrets (.sess):
use pubky::{Pubky, Keypair};
let pubky = Pubky::new()?;
let keypair = Keypair::random();
let session = pubky.signer(keypair).signin().await?;
session.write_secret_file("alice.sess").unwrap();
let restored = pubky.session_from_file("alice.sess").await?;
Security: the
.sesssecret is a bearer token. Anyone holding it can act as the user within the granted capabilities. Treat it like a password.
§Example code
Check more examples using the Pubky SDK.
§JS bindings
Find a wrapper of this crate using wasm_bindgen in npmjs.com. Or build on pubky-sdk codebase under pubky-sdk/bindings/js.
License: MIT Relay: https://httprelay.io (open source; run your own for production)
Modules§
- deep_
links - Deep link related module. Contains the following:
- errors
- Unified error types for the
pubkycrate. - prelude
- Common imports for quick starts.
- recovery_
file - Tools for encrypting and decrypting a recovery file storing user’s root key’s secret.
Macros§
- cross_
log - Cross-platform logging macro with explicit level selection.
Structs§
- Auth
Token - Implementation of the Pubky Auth spec.
- Capabilities
- A wrapper around
Vec<Capability>that controls how capabilities are serialized and built. - Capability
- A single capability: a
scopeand the allowedactionswithin it. - Keypair
- Wrapper around
pkarr::Keypairthat customizesPublicKeyrendering. - List
Builder - Unified builder for homeserver
LISTqueries (works for session & public). - Method
- The Request Method (VERB)
- Pkdns
- PKDNS actor: resolve & publish
_pubkyPKARR records. - Pubky
- High-level facade. Owns a
PubkyHttpClientand constructs the main actors. Prefer to instantiate only once and use trough your application a single sharedPubkyinstead of constructing one per request. This avoids reinitializing transports and keeps the same client available for repeated usage. - Pubky
Auth Flow - End-to-end auth flow (request + live polling) you hold on to.
- Pubky
Http Client - Transport client for Pubky homeserver APIs and generic HTTP, with PKARR-aware URL handling.
- Pubky
Http Client Builder - Configures a
PubkyHttpClientbefore construction. - Pubky
Resource - An addressed resource:
(owner: PublicKey, path: ResourcePath). - Pubky
Session - Stateful, per-identity API driver built on a shared
PubkyHttpClient. - Pubky
Signer - Key holder and signer.
- Public
Key - Wrapper around
pkarr::PublicKeythat renders with thepubkyprefix. - Public
Storage - Storage that reads public data for any user (unauthenticated).
- Resource
Path - An absolute, URL-safe homeserver path (
/…), with percent-encoding where needed. - Resource
Stats - Typed metadata for a stored object (from a
HEADrequest). - Session
Storage - Storage that acts as the signed-in user (authenticated).
- Status
Code - An HTTP status code (
status-codein RFC 9110 et al.).
Enums§
- Auth
Flow Kind - The kind of authentication flow to perform.
- Build
Error - Errors that can occur while building a
crate::PubkyHttpClient. - Error
- The crate’s top-level error type.
Constants§
- DEFAULT_
HTTP_ RELAY - Default HTTP relay base when none is supplied.
- DEFAULT_
RELAYS - Default Relays.
- DEFAULT_
STALE_ AFTER - Default staleness window for homeserver
_pubkyPkarr records (1 hour).
Traits§
- Into
Pubky Resource - Convert common input types into a normalized, addressed
PubkyResource. - Into
Resource Path - Convert common input types into a normalized
ResourcePath(absolute).
Functions§
- resolve_
pubky - Resolve a Pubky identifier (either
pubky://orpubky<pk>/…) into a transport URL.
Type Aliases§
- Result
- A specialized
Resulttype forpubkyoperations.