Skip to content

Instantly share code, notes, and snippets.

@bennyhodl
Created December 12, 2024 20:38
Show Gist options
  • Save bennyhodl/5eadf4eeb0e00b4abf83ee2f135099cc to your computer and use it in GitHub Desktop.
Save bennyhodl/5eadf4eeb0e00b4abf83ee2f135099cc to your computer and use it in GitHub Desktop.
TabConf DlcDevKit Presentation
title author theme
Dlc Dev Kit - Application SDK for DLCs
benny b
name override
catppuccin-mocha
footer
style left center right
template
@bennyhodl
DlcDevKit - Application SDK for DLCs
{current_slide} / {total_slides}

Why does ddk exist?

image:width:100%

Creating a DLC application is complex. Existing libraries provided excellent core functionality but were fragmented.

Developers had to manage multiple components manually:

  • Contract creation and management
  • Contract storage
  • Message handling
  • Wallet integration
  • No unified solution for quick prototyping

Developers had to spend time integrating different pieces

Focus shifted from building applications to managing Bitcoin functionality

Solution: Dlc Dev Kit

A library that brings everything together

  • Contract Management
  • Contract Execution
  • Contract Storage
  • DLC Messaging
  • Wallet

Uses rust-dlc and bdk under the hood

Allows developers to focus on application logic rather than DLC internals

How to use DlcDevKit

Ready to go example node

cargo install ddk-node
# or latest
cargo install --git https://github.com/bennyhodl/dlcdevkit.git ddk-node

Build your own

cargo add ddk
# or latest
cargo add --git https://github.com/bennyhodl/dlcdevkit.git ddk

Built around three main traits:

  • Transport
  • Storage
  • Oracle Client

DDK Application

Create a fully featured DLC app with ~15 lines

cargo add ddk --features lightning
use std::sync::Arc;
use ddk::builder::Builder;
use ddk::storage::SledStorage;
use ddk::transport::lightning::LightningTransport;
use ddk::oracle::KormirOracleClient;
use bitcoin::Network;

type ApplicationDdk = ddk::DlcDevKit<LightningTransport, SledStorage, KormirOracleClient>;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let transport = Arc::new(LightningTransport::new([0u8;32], 9735, Network::Regtest)?);
    let storage = Arc::new(SledStorage::new("/tmp/ddk")?);
	let oracle = Arc::new(KormirOracleClient::new("http://127.0.0.1:8080").await?);

    let ddk: ApplicationDdk = Builder::new()
        .set_seed_bytes([0u8;32])
        .set_network(Network::Regtest)
        .set_storage_path("/tmp/ddk")
        .set_esplora_path("http://127.0.0.1:3000")
        .set_transport(transport.clone())
        .set_storage(storage.clone())
        .set_oracle(oracle_client.clone())
        .finish()?;

    ddk.start()?;
}

Transport

DDK sets up a listener to handle DLC communication to pass to the DLC manager.

/// Allows ddk to open a listening connection and send/receive dlc messages functionality.
pub trait Transport {
    /// Name for the transport service.
    fn name(&self) -> String;

    /// Open an incoming listener for DLC messages from peers.
    async fn listen(&self);

    /// Get messages that have not been processed yet.
    async fn receive_messages<S: Storage, O: Oracle>(
        &self,
        manager: Arc<DlcDevKitDlcManager<S, O>>,
    );

    /// Send a message to a specific counterparty.
    fn send_message(&self, counterparty: PublicKey, message: Message);

    /// Connect to another peer
    async fn connect_outbound(&self, pubkey: PublicKey, host: &str);
}

Lightning

https://github.com/bennyhodl/dlcdevkit/blob/master/ddk/src/transport/lightning/mod.rs

Storage

Storage of contracts, wallet, and counterparties.

/// Storage for DLC contracts.
pub trait Storage: dlc_manager::Storage + DeriveSigner {
	/// Instantiate the storage for the BDK wallet.
    fn initialize_bdk(&self) -> Result<ChangeSet, WalletError>;
	/// Save changeset to the wallet storage.
    fn persist_bdk(&self, changeset: &ChangeSet) -> Result<(), WalletError>;
	/// Connected counterparties.
    fn list_peers(&self) -> Result<Vec<PeerInformation>, Error>;
	/// Persist counterparty.
    fn save_peer(&self, peer: PeerInformation) -> Result<(), Error>;

	/// Marketplace methods
    #[cfg(feature = "marketplace")]
    fn save_announcement(&self, announcement: OracleAnnouncement) -> Result<(), Error>;
    #[cfg(feature = "marketplace")]
    fn get_marketplace_announcements(&self) -> Result<Vec<OracleAnnouncement>, Error>;
}

Sled

https://github.com/bennyhodl/dlcdevkit/tree/master/ddk/src/storage/sled

Oracle

Interacting with oracles

/// Oracle client
pub trait Oracle: dlc_manager::Oracle {
    fn name(&self) -> String;
}

rust-dlc trait

/// Oracle trait provides access to oracle information.
pub trait Oracle {
    /// Returns the public key of the oracle.
    fn get_public_key(&self) -> XOnlyPublicKey;
    /// Returns the announcement for the event with the given id if found.
    fn get_announcement(&self, event_id: &str) -> Result<OracleAnnouncement, Error>;
    /// Returns the attestation for the event with the given id if found.
    fn get_attestation(&self, event_id: &str) -> Result<OracleAttestation, Error>;
}

Kormir

https://github.com/bennyhodl/dlcdevkit/blob/master/ddk/src/oracle/kormir.rs

Use Cases

Servers

  • gRPC servers
  • REST API services
  • P2P networking
  • Client/Server model
  • Document or relational database

Mobile

  • Nostr communication
  • Matrix communication
  • IndexedDB storage
  • Browser based
  • Mobile applications

Future Plans

Language Bindings

Written in 🦀. Ability for library consumers to use DDK in the language and platform they are comfortable with.

Nostr integration

Finalize and comply to NIP-88.

  • Nostr transport module
  • IndexedDB storage module
  • Oracle Announcement marketplace

rust-dlc

Desktop App

There is an example node that is available via crates.io. But I would like to have a desktop application for beginners. Ideally, installable to node-in-a-box solutions.

Check out DDK!

github.com

crates.io

docs.rs

twitter

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment