Getting Started

Build the XE CLI, create a wallet, request XE from the testnet faucet, and make your first transactions.


This guide covers building the XE CLI from source, creating a wallet, funding it from the testnet faucet, and making your first transactions.

[!WARNING] Work in progress — not everything here works today XE is pre-1.0 and this is a testnet. Commands are added, changed and broken as development goes, and parts of the network go down. Two things are not available right now:

  • XUSD is not issued. Only XE exists on this testnet. The stablecoin that prices compute leases has no issuance path yet, so leasing arrives with it.
  • No compute providers are online. xe providers returns an empty list, so xe lease has nobody to accept a lease and xe ssh has nothing to connect to.

Prerequisites

  • Go 1.25+
  • Git

Building from Source

The source is public at github.com/xeprotocol/xe, licensed under the GPL-3.0 — use it, modify it, redistribute it, provided you pass on the same freedoms and publish the source of anything you distribute. No release binary has been tagged yet, so building is the way to get one.

git clone https://github.com/xeprotocol/xe.git
cd xe
make build          # produces ./xe

make is the single definition of how the binary is built. Builds are reproducible — pinned toolchain (.go-version), -trimpath, -buildvcs=false, CGO_ENABLED=0 — so the same commit produces the same bytes on any machine. make verify-repro proves it locally.

One binary does everything: xe node runs the daemon, and every other subcommand is a client that talks to a node's HTTP API.

Running a Node

Start a node with default settings: libp2p on port 9000, HTTP API on port 8080, data in ./data.

./xe node

Connecting to the Testnet

A node's identity is its genesis, not its binary. A stock build embeds a placeholder genesis (network_id: "testnet") that no live network uses, and peers ban a node whose network ID does not match theirs. Point the node at the published genesis bundle instead, and it joins the live network without a rebuild:

./xe node \
  --data ./data \
  --genesis-dir ./genesis/testnet-0001 \
  --dial /ip4/45.77.226.208/tcp/9000/p2p/12D3KooWJg4PQYGSfNCupBWZdEWbKj7pgdp5MmmUXbPdBcp6YDtT,/ip4/144.202.4.117/tcp/9000/p2p/12D3KooWEqv1BRZkSntgcgbrJh7bobFRSkBdRupubvNZLEx8hZLA

Confirm what you are about to join before you join it:

./xe verify-genesis --genesis-dir ./genesis/testnet-0001

The current network is testnet-0001, ledger genesis e813eefe3b61…1ed68, statechain genesis 41946029…33a29. There are three bootstrap nodes:

NodeAPIp2p
Londonhttps://ldn.core.test.network/ip4/45.77.226.208/tcp/9000/p2p/12D3KooWJg4PQYGSfNCupBWZdEWbKj7pgdp5MmmUXbPdBcp6YDtT
Frankfurthttps://ffm.core.test.network/ip4/144.202.4.117/tcp/9000/p2p/12D3KooWEqv1BRZkSntgcgbrJh7bobFRSkBdRupubvNZLEx8hZLA
New Yorkhttps://nyc.core.test.network/ip4/192.248.176.245/tcp/9000/p2p/12D3KooWEbQ5zDvSz6kKE5ppzwBXKRFsnZbHNjRx94QZFaPeGA4e

Peer IDs are derived from each node's key and change if that key is regenerated. Fetch the current one from the node's API:

curl -s https://ldn.core.test.network/node | jq -r .id

There is no ambient peer discovery: mDNS only reaches your LAN and the DHT only resolves peer IDs already known, so the bootstrap list you configure is your node's view of the network. Use more than one. Check that it worked:

curl -s localhost:8080/node | jq '{network_id, peers: (.peers | length)}'

[!NOTE] A testnet wipe retires these values testnet-0001, the genesis hashes and the bundle above are all discarded when the protocol changes and the network is re-bootstrapped. Re-check this page after a wipe.

Using the CLI

Point the CLI at a testnet node and interact without running your own:

export XE_NODE=https://ldn.core.test.network

Hello world — two wallets and a transfer

The shortest useful thing you can do: create two wallets, fund one, send to the other. Keep each wallet in its own file with XE_WALLET.

XE_WALLET=~/.xe/alice.seed xe wallet create
XE_WALLET=~/.xe/bob.seed   xe wallet create
Wallet created!
  Address:    7d27d0a34cc2a5cd08f65905a983fabec1a517baf6d3cdab0a921256ecb9af57
  Public key: 665b50f96f8a4a86e1940386cce7fa1c0592c8eba9524fe9d579254fc341f02b
  File:       /home/you/.xe/alice.seed

The address is what you hand out, and it is not the public key — it is sha256("xe/account/v1" ‖ pubkey), so identity and credential stay separate. The seed file is the account: back it up, and treat anyone who has it as the owner of the funds.

Fund Alice, then claim the grant:

XE_WALLET=~/.xe/alice.seed xe faucet
XE_WALLET=~/.xe/alice.seed xe receive
XE_WALLET=~/.xe/alice.seed xe wallet balance

Send Bob 25 XE, using the address printed for Bob above, and let Bob claim it:

XE_WALLET=~/.xe/alice.seed xe send <bob-address> 25 --asset XE --memo "hello world"
XE_WALLET=~/.xe/bob.seed   xe receive
XE_WALLET=~/.xe/bob.seed   xe wallet balance

Every transfer is two blocks — a send on the sender's chain and a receive on the recipient's — so funds sit as pending until the recipient signs for them. Nothing lands in an account without a block signed by its own key. Both sides settle in a few seconds, and neither pays a fee.

Any account is public, so you can watch the same thing from outside:

curl -s $XE_NODE/accounts/<address>/balance
curl -s $XE_NODE/accounts/<address>/chain

[!NOTE] How the faucet works xe faucet asks the faucet service (XE_FAUCET, default https://faucet.test.network) for a grant — a bare HTTP POST, no proof-of-work. It sends 1,000 XE per account per day from a pre-funded wallet; it mints nothing and holds no minter key. A repeat request inside that window returns 429 with a retry_after_seconds. The grant arrives as a pending send, so follow it with xe receive.

Compute

xe providers                                      # List compute providers
xe lease --vcpus 1 --memory 1024 --duration 300   # Create a lease
xe ssh <hash>                                     # SSH into the leased VM

[!WARNING] No providers are online xe providers returns an empty list on the live testnet today — the two testnet providers were retired and none have replaced them. A lease has nobody to accept it, so it stays open until it is cancelled, and there is no VM to SSH into. The commands work; the counterparty is missing.

Docker Deployment

The repository ships a Dockerfile and a systemd unit in deploy/ — use those rather than the sketch below if you are running a node for real. A minimal equivalent:

FROM golang:1.25-alpine AS build
ARG VERSION=dev
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -ldflags "-X main.version=${VERSION}" -o /xe ./cmd/xe/

FROM alpine:3.20
COPY --from=build /xe /usr/local/bin/xe
EXPOSE 8080 9000
ENTRYPOINT ["xe", "node"]

Web-Based Quick Start

If you prefer a browser-based experience, use the hosted web wallet at ldn.test.network/wallet:

  1. Open the wallet and create a new wallet (your seed is encrypted client-side with AES-GCM)
  2. Request testnet XE from the faucet — 1,000 XE per account per day
  3. Explore the network via the Explorer
  4. Send transactions or use chat. Leasing compute needs a provider, and none are online

Environment Variables

VariableDefaultDescription
XE_NODEhttps://ldn.core.test.networkNode API URL
XE_WALLET~/.xe/wallet.seedWallet seed file
XE_FAUCEThttps://faucet.test.networkFaucet service URL
XE_SSH_HOSTldn.test.networkSSH gateway hostname
XE_SSH_PORT2222SSH gateway port