pub struct Client(/* private fields */);Expand description
Pkarr client for publishing and resolving SignedPackets over mainline Dht and/or Relays.
Implementations§
Source§impl Client
impl Client
Sourcepub fn as_blocking(&self) -> ClientBlocking
pub fn as_blocking(&self) -> ClientBlocking
Returns a blocking (synchronous ) version of Client.
Source§impl Client
impl Client
Sourcepub fn builder() -> ClientBuilder
pub fn builder() -> ClientBuilder
Returns a builder to edit config before creating Client.
You can use ClientBuilder::no_default_network to start from a clean slate and decide which networks to use.
Sourcepub fn dht(&self) -> Option<Dht>
pub fn dht(&self) -> Option<Dht>
Returns a reference to the internal mainline::Dht node.
Gives you access to methods like mainline::Dht::info, mainline::Dht::bootstrapped, and mainline::Dht::to_bootstrap among the rest of the API.
Sourcepub async fn publish(
&self,
signed_packet: &SignedPacket,
cas: Option<Timestamp>,
) -> Result<(), PublishError>
pub async fn publish( &self, signed_packet: &SignedPacket, cas: Option<Timestamp>, ) -> Result<(), PublishError>
Publishes a SignedPacket to the mainline Dht and or Relays.
§Lost Update Problem
Mainline DHT and remote relays form a distributed network, and like all distributed networks, it is vulnerable to Write–write conflict.
§Read first
To mitigate the risk of lost updates, you should call the Self::resolve_most_recent method then start authoring the new SignedPacket based on the most recent as in the following example:
use pkarr::{Client, SignedPacket, Keypair};
// For local testing
use pkarr::mainline::Testnet;
#[tokio::main]
async fn run() -> anyhow::Result<()> {
let testnet = Testnet::new_async(3).await?;
let client = Client::builder()
// Disable the default network settings (builtin relays and mainline bootstrap nodes).
.no_default_network()
.bootstrap(&testnet.bootstrap)
.build()?;
let keypair = Keypair::random();
let (signed_packet, cas) = if let Some(most_recent) = client
.resolve_most_recent(&keypair.public_key()).await
{
let mut builder = SignedPacket::builder();
// 1. Optionally inherit all or some of the existing records.
for record in most_recent.all_resource_records() {
let name = record.name.to_string();
if name != "foo" && name != "sercert" {
builder = builder.record(record.clone());
}
};
// 2. Optionally add more new records.
let signed_packet = builder
.txt("foo".try_into()?, "bar".try_into()?, 30)
.a("secret".try_into()?, 42.into(), 30)
.sign(&keypair)?;
(
signed_packet,
// 3. Use the most recent [SignedPacket::timestamp] as a `CAS`.
Some(most_recent.timestamp())
)
} else {
(
SignedPacket::builder()
.txt("foo".try_into()?, "bar".try_into()?, 30)
.a("secret".try_into()?, 42.into(), 30)
.sign(&keypair)?,
None
)
};
client.publish(&signed_packet, cas).await?;
Ok(())
}§Errors
This method may return on of these errors:
- QueryError: when the query fails, and you need to retry or debug the network.
- ConcurrencyError: when an write conflict (or the risk of it) is detedcted.
If you get a ConcurrencyError; you should resolver the most recent packet again, and repeat the steps in the previous example.
Sourcepub async fn resolve(&self, public_key: &PublicKey) -> Option<SignedPacket>
pub async fn resolve(&self, public_key: &PublicKey) -> Option<SignedPacket>
Returns a SignedPacket from the cache even if it is expired. If there is no packet in the cache, or if the cached packet is expired, it will make a DHT query in a background query and caches any more recent packets it receives.
If you want to get the most recent version of a SignedPacket, you should use Self::resolve_most_recent.
Sourcepub async fn resolve_most_recent(
&self,
public_key: &PublicKey,
) -> Option<SignedPacket>
pub async fn resolve_most_recent( &self, public_key: &PublicKey, ) -> Option<SignedPacket>
Returns the most recent SignedPacket found after querying all mainline Dht nodes and or Relays.
Useful if you want to read the most recent packet before publishing a new packet.
This is a best effort, and doesn’t guarantee consistency.
Trait Implementations§
Source§impl PkarrClientExt for Client
Available on crate features dht or http only.
impl PkarrClientExt for Client
dht or http only.Source§async fn resolve(&self, did: &DidPkarr) -> Result<DidPkarrDocument, ResolveErr>
async fn resolve(&self, did: &DidPkarr) -> Result<DidPkarrDocument, ResolveErr>
pkarr::Client::resolve but for DIDs.Source§async fn resolve_most_recent(
&self,
did: &DidPkarr,
) -> Result<DidPkarrDocument, ResolveErr>
async fn resolve_most_recent( &self, did: &DidPkarr, ) -> Result<DidPkarrDocument, ResolveErr>
pkarr::Client::resolve_most_recent but for DIDs.Source§async fn publish(
&self,
doc: &DidPkarrDocument,
timestamp: Option<Timestamp>,
signing_key: &SigningKey,
) -> Result<(), PublishErr>
async fn publish( &self, doc: &DidPkarrDocument, timestamp: Option<Timestamp>, signing_key: &SigningKey, ) -> Result<(), PublishErr>
pkarr::Client::publish but for DIDs.