Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,9 @@ dist/
**/.DS_Store

# Logs
logs/*
logs/*

/.simplicity-dex.config.toml
/.cache
taker/
simplicity-dex
6 changes: 6 additions & 0 deletions .simplicity-dex.example/.simplicity-dex.config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Keypair can be generated here: https://start.nostr.net/
nostr_keypair = "keypair..."
relays = [
"wss://relay.damus.io",
"wss://nostr.wine/",
]
1 change: 0 additions & 1 deletion .simplicity-dex.example/keypair.txt

This file was deleted.

1 change: 0 additions & 1 deletion .simplicity-dex.example/relays.txt

This file was deleted.

27 changes: 20 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,36 @@ version = "0.1.0"
edition = "2024"
rust-version = "1.91.0"
authors = ["Blockstream"]
readme = "README.md"
readme = "Readme.md"


[workspace.dependencies]
anyhow = { version = "1.0.100" }
bincode = { version = "2.0.1" }
chrono = { version = "0.4.42" }
clap = { version = "4.5.49", features = ["derive"] }
dirs = {version = "6.0.0"}
config = { version = "0.15.18" }
contracts = { git = "https://github.com/BlockstreamResearch/simplicity-contracts.git", rev = "baa8ab7", package = "contracts" }
contracts-adapter = { git = "https://github.com/BlockstreamResearch/simplicity-contracts.git", rev = "baa8ab7", package = "contracts-adapter" }
dex-nostr-relay = { path = "./crates/dex-nostr-relay" }
dirs = { version = "6.0.0" }
dotenvy = { version = "0.15.7" }
elements = { version = "0.26.1" }
futures-util = { version = "0.3.31" }
global-utils = { path = "crates/global-utils" }
global-utils = { path = "./crates/global-utils" }
hex = { version = "0.4.3" }
humantime = { version = "2.3.0" }
nostr = { version = "0.43.1", features = ["std"] }
nostr-sdk = { version = "0.43.0" }
dex-nostr-relay = { path = "./crates/dex-nostr-relay"}
serde = { version = "1.0.228", features = ["derive"] }
proptest = { version = "1.9.0" }
serde = { version = "1.0.228" }
serde_json = { version = "1.0.145" }
simplicity-lang = { version = "0.6.0" }
simplicityhl = { version = "0.2.0" }
simplicityhl-core = { git = "https://github.com/BlockstreamResearch/simplicity-contracts.git", rev = "baa8ab7", package = "simplicityhl-core", features = ["encoding"] }
sled = { version = "0.34.7" }
thiserror = { version = "2.0.17" }
tokio = { version = "1.48.0", features = ["macros", "test-util", "rt", "rt-multi-thread"] }
tokio = { version = "1.48.0", features = ["macros", "test-util", "rt", "rt-multi-thread", "tracing" ] }
tracing = { version = "0.1.41" }
tracing-appender = { version = "0.2.3" }
tracing-subscriber = { version = "0.3.19", features = ["env-filter"] }
url = { version = "2.5.7" }
164 changes: 164 additions & 0 deletions Guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Simplicity DEX — Developer Guide

This short guide helps contributors understand, build, test and extend the project. It focuses on practical commands and
the patterns used across crates (not exhaustive; follow Rust and crate docs for deeper dives).

## Project layout

- crates/dex-cli — command line client and UX helpers
- crates/dex-nostr-relay — relay logic, event parsing and storage
- crates/global-utils — other helpers

## Prerequisites

- Install Rust
- Create your nostr keypair (Can be generated here: https://start.nostr.net/)

## Quick start

1. Build:
- cargo build -r
2. Run CLI (local dev):
- `cargo build -r`
- `mkdir -p ./demo`
- `mv ./target/release/simplicity-dex ./demo/simplicity-dex`
- `cp ./.simplicity-dex.example/.simplicity-dex.config.toml ./demo/.simplicity-dex.config.toml`
- `echo SEED_HEX=ffff0123456789abcdef0123456789abcdef0123456789abcdef0123456789ab > ./demo/.env`
3. Insert your valid nostr keypair into `.simplicity-dex.config.toml`

## Commands example execution

Overall trading for dcd contracts can be split in two sides: taker and maker.

Maker and Taker responsible for taking such steps:

1) Maker initializes contract in Liquid;
2) Maker funds contract with collateral and settlement tokens. (by now for test **collateral** = LBTC-Testnet, **settlement** = minted token from scratch)
3) Taker funds contract with collateral tokens and takes contract parameters from already discovered maker event_id.
4) Maker now can make:
* Early collateral termination
* Early settlement termination
5) Taker now can make:
* Early termination
6) After `settlement-height` both maker and taker can use settlement exit to receive their tokens (collateral or settlement) depending on the settlement token price, which is signed with oracle.

1. Create your own contract with your values. For example can be taken

* `taker-funding-start-time` 1764328373 (timestamp can be taken from https://www.epochconverter.com/)
* `taker-funding-end-time` 1764358373 (Block time when taker funding period ends)
* `contract-expiry-time` 1764359373 (Block time when contract expires)
* `early-termination-end-time` 1764359373 (Block time when early termination is no longer allowed)
* `settlement-height` 2169368 (Block height at which oracle price is attested)
* `principal-collateral-amount` 2000 (Base collateral amount)
* `incentive-basis-points` 1000 (Incentive in basis points (1 bp = 0.01%))
* `filler-per-principal-collateral` 100 (Filler token ratio)
* `strike-price` 25 (Oracle strike price for settlement)
* `settlement-asset-entropy` `0ffa97b7ee6fcaac30b0c04803726f13c5176af59596874a3a770cbfd2a8d183` (Asset entropy (hex) for settlement)
* `oracle-pubkey` `757f7c05d2d8f92ab37b880710491222a0d22b66be83ae68ff75cc6cb15dd2eb` (`./simplicity-dex helpers address --account-index 5`)

Actual command in cli:
```bash
./simplicity-dex maker init
--utxo-1 <FIRST_LBTC_UTXO>
--utxo-2 <SECOND_LBTC_UTXO>
--utxo-3 <THIRD_LBTC_UTXO>
--taker-funding-start-time <TAKER_FUNDING_START_TIME>
--taker-funding-end-time <TAKER_FUNDING_END_TIME>
--contract-expiry-time <CONTRACT_EXPIRY_TIME>
--early-termination-end-time <EARLY_TERMINATION_END_TIME>
--settlement-height <SETTLEMENT_HEIGHT>
--principal-collateral-amount <PRINCIPAL_COLLATERAL_AMOUNT>
--incentive-basis-points <INCENTIVE_BASIS_POINTS>
--filler-per-principal-collateral <FILLER_PER_PRINCIPAL_COLLATERAL>
--strike-price <STRIKE_PRICE>
--settlement-asset-entropy <SETTLEMENT_ASSET_ENTROPY>
--oracle-pubkey <ORACLE_PUBLIC_KEY>
```

2. Maker fund cli command:
```bash
./simplicity-dex maker fund
--filler-utxo <FILLER_TOKEN_UTXO>
--grant-coll-utxo <GRANTOR_COLLATERAL_TOKEN_UTXO>
--grant-settl-utxo <GRANTOR_SETTLEMENT_TOKEN_UTXO>
--settl-asset-utxo <SETTLEMENT_ASSET_UTXO>
--fee-utxo <FEE_UTXO>
--taproot-pubkey-gen <DCD_TAPROOT_PUBKEY_GEN>
```

3. Taker has to fund

```bash
./simplicity-dex taker fund
--filler-utxo <FILLER_TOKEN_UTXO>
--collateral-utxo <COLLATERAL_TOKEN_UTXO>
--collateral-amount-deposit <COLLATERAL_AMOUNT_TO_DEPOSIT>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

4. Taker can wait for specific `settlement-height` and gracefully exit contract:
```bash
./simplicity-dex taker settlement
--filler-utxo <FILLER_TOKEN_UTXO>
--asset-utxo <ASSET_UTXO>
--fee-utxo <FEE_UTXO>
--filler-to-burn <FILLER_AMOUNT_TO_BURN>
--price-now <PRICE_AT_CURRENT_BLOCK_HEIGHT>
--oracle-sign <ORACLE_SIGNATURE>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

5. Maker can wait for specific `settlement-height` and gracefully exit contract:
```bash
./simplicity-dex maker settlement
--grant-collateral-utxo <GRANTOR_COLLATERAL_TOKEN_UTXO>
--grant-settlement-utxo <GRANTOR_SETTLEMENT_TOKEN_UTXO>
--asset-utxo <ASSET_UTXO>
--fee-utxo <FEE_UTXO>
--grantor-amount-burn <GRANTOR_AMOUNT_TO_BURN>
--price-now <PRICE_AT_CURRENT_BLOCK_HEIGHT>
--oracle-sign <ORACLE_SIGNATURE>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

* Maker or Taker depending on the can use Merge(2/3/4) command to merge collateral tokens.
This is made exactly for combining outs into one to eliminate execution of contract with usage of little fragments
```bash
./simplicity-dex helpers merge-tokens4
--token-utxo-1 <TOKEN_UTXO_1>
--token-utxo-2 <TOKEN_UTXO_2>
--token-utxo-3 <TOKEN_UTXO_3>
--token-utxo-4 <TOKEN_UTXO_4>
--fee-utxo <FEE_UTXO>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

* For early collateral termination Maker can use command:
```bash
./simplicity-dex maker termination-collateral
--grantor-collateral-utxo <GRANTOR_COLLATERAL_TOKEN_UTXO>
--collateral-utxo <COLLATERAL_TOKEN_UTXO>
--fee-utxo <FEE_UTXO>
--grantor-collateral-burn <GRANTOR_COLLATERAL_AMOUNT_TO_BURN>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

* For early settlement termination Maker can use command:
```bash
./simplicity-dex maker termination-settlement
--settlement-asset-utxo <SETTLEMENT_ASSET_UTXO>
--grantor-settlement-utxo <GRANTOR_SETTLEMENT_TOKEN_UTXO>
--fee-utxo <FEE_UTXO>
--grantor-settlement-amount-burn <GRANTOR_SETTLEMENT_AMOUNT_TO_BURN>
--maker-order-event-id <MAKER_ORDER_EVENT_ID>
```

* For early termination Taker can use command:
```bash
./simplicity-dex taker termination-early
--filler-utxo <FILLER_TOKEN_UTXO>
--collateral-utxo <COLLATERAL_TOKEN_UTXO>
--fee-utxo <FEE_UTXO>
--filler-to-return <FILLER_TOKEN_AMOUNT_TO_RETURN>
--maker-order-event-id <MAKER_ORDER_EVENT_ID
```
27 changes: 0 additions & 27 deletions Makefile

This file was deleted.

63 changes: 43 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Simplicity DEX

A distributed exchange built on the NOSTR protocol, leveraging Simplicity smart contracts and the PACT (PACT for Auditable Contract Transactions) messaging protocol.
A distributed exchange built on the NOSTR protocol, leveraging Simplicity smart contracts and the PACT (PACT for
Auditable Contract Transactions) messaging protocol.

## Overview

Simplicity DEX is a decentralized exchange that combines the power of Simplicity smart contracts with the distributed messaging capabilities of NOSTR. By utilizing the PACT protocol, we enable secure, auditable, and transparent trading of digital assets without relying on centralized intermediaries.
Simplicity DEX is a decentralized exchange that combines the power of Simplicity smart contracts with the distributed
messaging capabilities of NOSTR. By utilizing the PACT protocol, we enable secure, auditable, and transparent trading of
digital assets without relying on centralized intermediaries.

## Key Features

Expand All @@ -16,34 +19,53 @@ Simplicity DEX is a decentralized exchange that combines the power of Simplicity

## DEX Messaging Protocol

The core of our DEX is the **PACT (PACT for Auditable Contract Transactions)** protocol, which defines the format of trading offers. This protocol is fully adapted to be compatible with the NOSTR event structure.
The core of our DEX is the **PACT (PACT for Auditable Contract Transactions)** protocol, which defines the format of
trading offers. This protocol is fully adapted to be compatible with the NOSTR event structure.

### Offer Structure

A PACT offer is implemented as a standard NOSTR event with kind `30078` (non-standard, ephemeral event kind for DEX offers). The event structure maps to PACT requirements as follows:
A PACT offer is implemented as a standard NOSTR event with kind `30078` (non-standard, ephemeral event kind for DEX
offers). The event structure maps to PACT requirements as follows:

| NOSTR Field | PACT Field | Data Type | Required | Description |
|-------------|------------|-----------|----------|-------------|
| `id` | Event ID | string (64-char hex) | Yes | SHA-256 hash of canonical serialized event data (excluding `sig`). Serves as unique, content-addressed identifier |
| `pubkey` | Maker Key | string (64-char hex) | Yes | 32-byte x-only Schnorr public key of market maker. Must be registered in on-chain Maker Identity Registry |
| `created_at` | Timestamp | integer | Yes | Unix timestamp (seconds) when offer was created |
| `description` | Description | string | No | Human-readable description of instrument and complex terms |
| `kind` | Event Type | integer | Yes | Event type identifier. Value `1` reserved for standard offers. Enables future protocol extensions |
| `tags` | Metadata | array of arrays | Yes | Structured machine-readable metadata for filtering and discovery |
| `content` | Contract Code | string | Yes | Stringified JSON containing full Simplicity contract code |
| `sig` | Signature | string (128-char hex) | Yes | 64-byte Schnorr signature proving authenticity and integrity |
| NOSTR Field | PACT Field | Data Type | Required | Description |
|---------------|---------------|-----------------------|----------|-------------------------------------------------------------------------------------------------------------------|
| `id` | Event ID | string (64-char hex) | Yes | SHA-256 hash of canonical serialized event data (excluding `sig`). Serves as unique, content-addressed identifier |
| `pubkey` | Maker Key | string (64-char hex) | Yes | 32-byte x-only Schnorr public key of market maker. Must be registered in on-chain Maker Identity Registry |
| `created_at` | Timestamp | integer | Yes | Unix timestamp (seconds) when offer was created |
| `description` | Description | string | No | Human-readable description of instrument and complex terms |
| `kind` | Event Type | integer | Yes | Event type identifier. Value `1` reserved for standard offers. Enables future protocol extensions |
| `tags` | Metadata | array of arrays | Yes | Structured machine-readable metadata for filtering and discovery |
| `content` | Contract Code | string | Yes | Stringified JSON containing full Simplicity contract code |
| `sig` | Signature | string (128-char hex) | Yes | 64-byte Schnorr signature proving authenticity and integrity |

### Tag Examples

The `tags` field contains structured metadata as key-value pairs:

```json
[
["asset_to_sell", "<liquid_asset_id>"],
["asset_to_buy", "<liquid_asset_id>"],
["price", "1000000", "sats_per_contract"],
["expiry", "1735689600"],
["compiler", "simplicity-v1.2.3", "deterministic_build_hash"]
[
"asset_to_sell",
"<liquid_asset_id>"
],
[
"asset_to_buy",
"<liquid_asset_id>"
],
[
"price",
"1000000",
"sats_per_contract"
],
[
"expiry",
"1735689600"
],
[
"compiler",
"simplicity-v1.2.3",
"deterministic_build_hash"
]
]
```

Expand Down Expand Up @@ -99,4 +121,5 @@ This project is licensed under the MIT License - see the LICENSE file for detail

## Disclaimer

This software is experimental and should be used with caution. Always verify contract code and understand the risks before trading.
This software is experimental and should be used with caution. Always verify contract code and understand the risks
before trading.
Loading