Splash! is a decentralized network for sharing Offers across the Chia ecosystem based on Rusts libp2p with DHT peer discovery.
Every connected peer receives all offers broadcasted from other peers. There is no centralized connection; peers connect to each other and are aware of each other, enabling true peer-to-peer DeFi. It also provides privacy, as it is difficult to trace where an offer in the network originated.
The Splash! command line tool acts as a proxy between your application and the Splash! network. It will broadcast your offers to the network and relay offers from other peers to your local application through a local HTTP API.
You can download prebuilt binaries in the releases section.
You can also build and install from source (requires the latest stable [Rust] compiler.)
cargo install splash
Usage: splash [OPTIONS]
Options:
-k, --known-peer <MULTIADDR>
Set initial peer, if missing use dexies DNS introducer
-l, --listen-address <MULTIADDR>
Set listen address, defaults to all interfaces, use multiple times for multiple addresses
-i, --identity-file <IDENTITY_FILE>
Store and reuse peer identity (only useful for known peers)
-t, --testnet
Use Testnet
--offer-hook <OFFER_HOOK>
HTTP endpoint where incoming offers are posted to, sends JSON body {"offer":"offer1..."} (defaults to STDOUT)
--listen-offer-submission <HOST:PORT>
Start a HTTP API for offer submission, expects JSON body {"offer":"offer1..."}
--listen-metrics <HOST:PORT>
Start a HTTP API for metrics
-h, --help
Print help
-V, --version
Print version
Start the node and listen on all interfaces (will use dexies DNS introducer):
./splash
Start a node and open local webserver for offer submission on port 4000:
./splash --listen-offer-submission 127.0.0.1:4000
Start a node and post incoming offers to a HTTP hook:
./splash --offer-hook http://yourApi/v1/offers
Start a node and bootstrap from a known peer (will not use dexies DNS introducer):
./splash --known-peer /ip6/::1/tcp/12345/p2p/12D3K...
Start a node and listen on a specific interface/port:
./splash --listen-address /ip6/::1/tcp/12345
Start a node and reuse identity:
./splash --identity-file identity.json
docker run -p 11511:11511 -p 4000:4000 dexiespace/splash:latest \
--listen-offer-submission 0.0.0.0:4000 \
--listen-address /ip4/0.0.0.0/tcp/11511
# send the request
curl -X POST -H "Content-Type: application/json" -d '{"offer":"offer1..."}' http://localhost:4000
If you run a permanent node, it is recommended that you become a stable peer. This requires opening an inbound port in your firewall. Then, start your node with the --listen-address
option, specifying your public interface and the selected port (e.g., 11511
).
./splash --listen-address /ip6/2001:db8::1/tcp/11511 --listen-address /ip4/1.2.3.4/tcp/11511
Note: If you run Splash behind a NAT, make sure to forward the port to your local IP and listen on that local IP. Splash will detect and announce your external IP accordingly.
Splash is designed to be lightweight, does not require disk I/O, and should run on basically any hardware, including a 1st-gen Raspberry Pi. Network bandwidth usage is minimal but will increase with the number of broadcasted offers.
To keep Splash as lightweight as possible, it does not index or store any offers it receives; they are simply forwarded to all connected peers or to the local HTTP hook. To find past offers or their status, you need to track them locally or use a service that indexes the offers.
One such service is dexie.space. dexie observes the Splash network, indexes all offers for easy search and retrieval, and keeps the index up to date. You can use the dexie API to search for offers, get offer details, and more.
Splash can be integrated into any Rust project. Here's how to do it:
- Add Splash and tokio to your
Cargo.toml
:
cargo add splash tokio
- In your Rust code, initialize Splash and listen for events:
use splash::{Splash, SplashEvent, SplashContext};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let SplashContext { node, mut events } = Splash::new().build().await?;
// Submit an offer
// node.broadcast_offer("offer1...").await?;
// Process events
while let Some(event) = events.recv().await {
match event {
SplashEvent::Initialized(peer_id) => println!("Our Peer ID: {}", peer_id),
SplashEvent::NewListenAddress(address) => println!("Listening on: {}", address),
SplashEvent::PeerConnected(peer_id) => println!("Connected to peer: {}", peer_id),
SplashEvent::PeerDisconnected(peer_id) => println!("Disconnected from peer: {}", peer_id),
SplashEvent::OfferReceived(offer) => println!("Received offer: {}", offer),
SplashEvent::OfferBroadcasted(offer) => println!("Broadcasted offer: {}", offer),
SplashEvent::OfferBroadcastFailed(err) => println!("Failed to broadcast offer: {}", err),
}
}
Ok(())
}
The Splash network is based on libp2p, meaning any libp2p library should be able to connect to the network. Use the following identifiers:
- Kademlia Protocol:
/splash/kad/1
- Identify Protocol:
/splash/id/1
- Gossipsub Subscription:
/splash/offers/1
An optional list of initially reachable peers can be requested via DNS TXT from _dnsaddr.splash.dexie.space
.