Reference
CLI Demo Guide
eIOU CLI Demo Guide
A step-by-step walkthrough for demonstrating eIOU CLI commands.
Table of Contents
- Overview
- Prerequisites & Installation
- Creating Containers
- Basic Wallet Commands
- Multi-Container Network Setup
- Contact Management Commands
- Transaction Commands
- System & Utility Commands
- Cleanup
- Quick Reference
- Troubleshooting
Overview
This guide provides a hands-on walkthrough for demonstrating the eIOU command-line interface (CLI). It covers container setup, wallet generation, contact management, and transaction operations.
What you will learn:
- How to pull and run the eIOU Docker image
- Two methods for creating eIOU wallets (automatic and manual)
- Essential CLI commands for daily wallet operations
- Setting up a 4-node network for P2P routing demonstrations
- Sending transactions directly and through multi-hop routing
- Best practices for secure wallet management
Target audience:
- Developers evaluating the eIOU system
- Demo presenters conducting live demonstrations
- System administrators deploying eIOU nodes
- Users learning to operate eIOU wallets
Prerequisites:
- Basic familiarity with Docker commands
- Terminal/command-line experience
- Understanding of cryptocurrency wallet concepts (helpful but not required)
Section 1: Prerequisites & Installation
System Requirements
Before running eIOU containers, ensure your system meets these requirements:
Docker Requirements:
- Docker Engine 20.10 or later
- Docker Compose v2.0 or later (for multi-node setups)
Verify Docker installation:
# Check Docker version
docker --version
# Check Docker Compose version
docker compose version
Memory Requirements:
| Configuration | RAM Required | Use Case |
|---|---|---|
| Single node | ~275 MB | Development, testing, personal wallet |
| 4-node network | ~1.1 GB | Multi-party testing, demos |
| 10-node network | ~2.8 GB | Complex routing tests, stress testing |
Disk Space:
- Base image: ~500 MB
- Per-container data: ~50 MB minimum (grows with transaction history)
Network:
- Ports 80 and 443 available (configurable)
- Outbound access to Tor network (for .onion addresses)
Pulling the eIOU Image
The fastest way to get started is pulling the pre-built image from Docker Hub.
Pull the latest image:
docker pull eiou/eiou
Verify the image was downloaded:
docker images | grep eiou
Expected output:
eiou/eiou latest abc123def456 2 days ago 498MB
Building from Source (Alternative)
If you need to customize the image or are contributing to development, build from source.
Clone and build:
# Clone the repository
git clone https://gitlab.com/eiou-org/eiou-docker.git
cd eiou-docker
# Build the image
docker build -f eiou.dockerfile -t eiou/eiou .
Verify the build:
docker images | grep eiou
Loading from a .tar File
If you have a pre-built image as a .tar archive (e.g., for offline installation or air-gapped environments):
Load the image:
# Load from a .tar file
docker load -i eiou-image.tar
# Or load from a compressed .tar.gz file
docker load -i eiou-image.tar.gz
Expected output:
Loaded image: eiou/eiou:latest
Verify the image was loaded:
docker images | grep eiou
Creating a .tar file (for distribution):
If you need to export an image to share with others:
# Save image to .tar file
docker save -o eiou-image.tar eiou/eiou:latest
# Or save with compression
docker save eiou/eiou:latest | gzip > eiou-image.tar.gz
Section 2: Creating Containers
eIOU wallet generation and restoration happens at container startup via environment variables.
HTTP/HTTPS Mode vs Tor-Only Mode
| Mode | Transport | Use Case |
|---|---|---|
EIOU_HOST=<hostname> set |
HTTP + HTTPS + Tor | Standard usage, demos, most deployments |
EIOU_HOST omitted |
Tor only | Privacy-focused, no HTTP/HTTPS exposure |
- With
EIOU_HOSTset: The container starts with HTTP, HTTPS, and Tor addresses. The value you provide becomes the HTTP/HTTPS address. - Without
EIOU_HOST: The container starts with only a Tor (.onion) address. No HTTP or HTTPS is configured.
Creating a New Wallet (HTTP/HTTPS Mode)
Setting the EIOU_HOST environment variable generates a new wallet with HTTP/HTTPS when the container starts.
What setting EIOU_HOST does automatically:
- Generates a new BIP39 seed phrase (24 words)
- Creates wallet keys from the seed phrase
- Configures the node hostname for HTTP and HTTPS
- Generates SSL certificates for HTTPS
- Starts Tor and generates .onion address
- Initializes the database
- Starts all background processors
Persistent node command:
docker run -d --restart unless-stopped --name alice \
-p 80:80 -p 443:443 -e EIOU_HOST=alice \
-v alice-mysql-data:/var/lib/mysql \
-v alice-config:/etc/eiou/config \
-v alice-plugins:/etc/eiou/plugins \
-v alice-plugin-scratch:/var/lib/eiou/plugin-scratch \
-v alice-backups:/var/lib/eiou/backups \
-v alice-backup-locks:/var/lib/eiou/backup-locks \
-v alice-ssl-cert:/var/lib/eiou/ssl \
eiou/eiou:latest
Volume descriptions:
| Volume | Purpose | Backup Priority |
|---|---|---|
alice-mysql-data |
Database (transactions, contacts, balances) | CRITICAL |
alice-config |
Wallet keys, userconfig.json, encryption data | CRITICAL |
alice-plugins |
Operator-installed plugin directories | IMPORTANT |
alice-plugin-scratch |
Durable private runtime state for sandboxed plugins | CRITICAL |
alice-backups |
Encrypted database backups | CRITICAL |
alice-backup-locks |
Backup lifecycle lock and pending archive-snapshot state | CRITICAL |
alice-ssl-cert |
TLS certificates and certbot state | LOW |
View container logs to see wallet information:
docker logs -f alice
Important: The seed phrase is displayed in the logs only once during initial generation. Copy and store it securely before the container restarts.
Accessing the CLI:
The CLI is accessed via docker exec <container> eiou:
# Access the CLI (shows help/usage)
docker exec alice eiou
# Run a specific command
docker exec alice eiou info
docker exec alice eiou help
Restoring an Existing Wallet
To restore a wallet from an existing seed phrase, use the RESTORE or RESTORE_FILE environment variables at container startup.
Method 1: RESTORE_FILE (Recommended - more secure):
Create a file containing your 24-word seed phrase, then mount it:
echo "word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12 word13 word14 word15 word16 word17 word18 word19 word20 word21 word22 word23 word24" > /tmp/seed.txt
docker run -d --restart unless-stopped --name alice \
-p 80:80 -p 443:443 -e EIOU_HOST=alice \
-e RESTORE_FILE=/restore/seed -v /tmp/seed.txt:/restore/seed:ro \
-v alice-mysql-data:/var/lib/mysql \
-v alice-config:/etc/eiou/config \
-v alice-plugins:/etc/eiou/plugins \
-v alice-plugin-scratch:/var/lib/eiou/plugin-scratch \
-v alice-backups:/var/lib/eiou/backups \
-v alice-backup-locks:/var/lib/eiou/backup-locks \
-v alice-ssl-cert:/var/lib/eiou/ssl \
eiou/eiou:latest
After successful restoration, delete the seed file:
rm /tmp/seed.txt
Why RESTORE_FILE is more secure:
- Seed phrase does not appear in
docker inspectoutput - Seed phrase does not appear in environment variable listings
- File can be deleted after container starts
Method 2: RESTORE (Convenient but less secure):
Pass the seed phrase directly as an environment variable:
docker run -d --restart unless-stopped --name alice \
-p 80:80 -p 443:443 -e EIOU_HOST=alice \
-e "RESTORE=word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12 word13 word14 word15 word16 word17 word18 word19 word20 word21 word22 word23 word24" \
-v alice-mysql-data:/var/lib/mysql \
-v alice-config:/etc/eiou/config \
-v alice-plugins:/etc/eiou/plugins \
-v alice-plugin-scratch:/var/lib/eiou/plugin-scratch \
-v alice-backups:/var/lib/eiou/backups \
-v alice-backup-locks:/var/lib/eiou/backup-locks \
-v alice-ssl-cert:/var/lib/eiou/ssl \
eiou/eiou:latest
Warning: The RESTORE environment variable remains visible via docker inspect. Use RESTORE_FILE for production.
Changing Hostname After Creation
If you need to add or change the HTTP/HTTPS hostname after the wallet is already created, use changesettings:
# Add or change hostname
docker exec alice eiou changesettings hostname http://alice
Setting the HTTP hostname automatically derives the HTTPS version (e.g., http://alice also configures https://alice). The SSL certificate is regenerated when the hostname changes.
Tor-Only Mode
For privacy-focused deployments with only Tor access (no HTTP/HTTPS), omit the EIOU_HOST variable:
docker run -d --restart unless-stopped --name alice-tor \
-v alice-tor-mysql-data:/var/lib/mysql \
-v alice-tor-config:/etc/eiou/config \
-v alice-tor-plugins:/etc/eiou/plugins \
-v alice-tor-plugin-scratch:/var/lib/eiou/plugin-scratch \
-v alice-tor-backups:/var/lib/eiou/backups \
-v alice-tor-backup-locks:/var/lib/eiou/backup-locks \
-v alice-tor-ssl-cert:/var/lib/eiou/ssl \
eiou/eiou:latest
Note: Without EIOU_HOST, the container:
- Generates a wallet with only a Tor (.onion) address
- Has no HTTP or HTTPS hostname configured
- Is only accessible via the Tor network
You can add an HTTP/HTTPS hostname later using eiou changesettings hostname.
Summary
| Scenario | Environment Variables |
|---|---|
| New wallet (HTTP/HTTPS + Tor) | EIOU_HOST=<hostname> |
| New wallet (Tor only) | No EIOU_HOST |
| Restore wallet (secure) | EIOU_HOST=<hostname> + RESTORE_FILE=/restore/seed |
| Restore wallet (simple) | EIOU_HOST=<hostname> + RESTORE="24 word phrase" |
| Change hostname later | Use eiou changesettings hostname <url> |
Section 3: Basic Wallet Commands
This section covers the essential wallet commands for viewing information, managing settings, and getting help.
3.1 info - Wallet Information
The info command displays comprehensive wallet information including addresses, authentication status, and public key.
Basic Usage
docker exec alice eiou info
Expected Output:
=== Wallet Information ===
Locators:
HTTP: http://alice
HTTPS: https://alice
Tor: abc123...xyz.onion
Authentication Code: [REDACTED]
Public Key: 04a1b2c3d4e5f6...
Tip: Use --show-auth to securely retrieve your authentication code
Detailed Information
docker exec alice eiou info detail
Shows balance breakdowns in addition to basic info.
Showing the Authentication Code
docker exec alice eiou info --show-auth
Security Note: The auth code is never displayed directly in command output. Instead, it is stored in a secure temporary file at /dev/shm/ with a 5-minute TTL.
JSON Output
docker exec alice eiou info --json
3.2 overview - Dashboard Summary
The overview command provides a quick dashboard view of your wallet status.
# Default overview (5 recent transactions)
docker exec alice eiou overview
# Show 10 recent transactions
docker exec alice eiou overview 10
Expected Output:
=== Wallet Overview ===
Total Balances:
VWL: 150.00
Active Contacts: 3
Pending Requests: 1
=== Recent Transactions (5) ===
#1 2026-01-26 10:15 SENT -50.00 VWL -> Bob
#2 2026-01-26 09:30 RECEIVED +75.00 VWL <- Charlie
...
3.3 viewsettings - Current Settings
Display all current wallet configuration options.
docker exec alice eiou viewsettings
Expected Output:
=== Wallet Settings ===
Currency & Fees:
Default Currency: VWL
Minimum Fee: 0
Default Fee: 0%
Maximum Fee: 5.0%
Credit & Limits:
Default Credit Limit: 100
P2P Routing:
Max P2P Level: 3
P2P Expiration: 300 seconds
Automation:
Auto-Refresh Enabled: true
Auto-Backup Enabled: true
3.4 changesettings - Modify Settings
Change wallet configuration directly or interactively.
# View current settings
docker exec alice eiou viewsettings
# Change P2P routing level
docker exec alice eiou changesettings maxP2pLevel 5
# Change default fee
docker exec alice eiou changesettings defaultFee 1.5
# Change hostname (derives HTTPS automatically)
docker exec alice eiou changesettings hostname http://alice
Available Settings:
| Setting | Description | Valid Values |
|---|---|---|
defaultFee |
Default routing fee percentage for new contacts; default 0 (no fee) |
Decimal (e.g., 0, or 0.01 for 0.01%) |
defaultCreditLimit |
Default credit limit for new contacts | Integer (e.g., 100) |
defaultCurrency |
Default currency code | VWL (only VWL currently supported) |
minFee |
Minimum fee floor; default 0 = free. Set non-zero to ensure a tiny transfer still covers your routing costs |
Decimal (e.g., 0, or 0.00000001 for a 1-satoshi floor) |
maxFee |
Maximum fee percentage | Decimal (e.g., 5.0) |
maxP2pLevel |
Maximum P2P routing hops | Integer 1-10 |
p2pExpiration |
P2P request expiration time (seconds) | Integer (e.g., 300) |
maxOutput |
Maximum lines of output to display | Integer or all |
defaultTransportMode |
Default transport type | http, https, tor |
autoRefreshEnabled |
Enable auto-refresh for pending transactions | true, false |
autoAcceptTransaction |
Auto-accept P2P transactions when route found | true, false |
hostname |
Node hostname (derives HTTPS automatically) | URL (e.g., http://alice) |
3.5 help - Getting Help
# General help (lists all top-level commands)
docker exec alice eiou help
# Help for top-level commands (info, send, viewbalances, history, overview,
# viewsettings, changesettings, sync, updatecheck, shutdown, start, …)
docker exec alice eiou help info
docker exec alice eiou help send
docker exec alice eiou help viewbalances
docker exec alice eiou help history
docker exec alice eiou help overview
docker exec alice eiou help viewsettings
docker exec alice eiou help changesettings
docker exec alice eiou help sync
Namespaced subcommand help. Every namespace that owns a CLI subtree — apikey, contact, chaindrop, payback — delegates eiou help <namespace> straight into that namespace’s own help. eiou help <ns> and eiou <ns> (or eiou <ns> help) print the exact same subcommand tree, so help lives in one place per namespace and never drifts.
# Each pair below prints identical output:
docker exec alice eiou contact ; docker exec alice eiou help contact
docker exec alice eiou apikey help ; docker exec alice eiou help apikey
docker exec alice eiou chaindrop help ; docker exec alice eiou help chaindrop
docker exec alice eiou payback help ; docker exec alice eiou help payback
# Sub-namespace `contact currency` also delegates:
docker exec alice eiou contact currency ; docker exec alice eiou help contact currency
# Other discoverable namespaces:
docker exec alice eiou backup help
docker exec alice eiou request # subcommand list for payment requests
docker exec alice eiou p2p # P2P approval list (also doubles as the syntax discoverer)
docker exec alice eiou plugin # plugin list (and via `--help` per registered plugin)
There is no eiou help contact add (or any per-subcommand) form — drill down with eiou contact (full tree) and copy the subcommand line you want.
3.6 Global Options
All CLI commands support these global options:
| Option | Description |
|---|---|
--json, -j |
Output results in JSON format |
--no-metadata |
Exclude metadata (timestamp, node_id) from JSON output |
Example with jq:
# Extract just the HTTP locator
docker exec alice eiou info --json | jq -r '.data.locators.http'
Section 4: Multi-Container Network Setup
Understanding the 4-Node Topology
The eIOU 4-node setup creates a linear chain of containers for demonstrating peer-to-peer routing:
Alice <---> Bob <---> Carol <---> Daniel
Key Characteristics:
- Line topology: Each node only knows its immediate neighbors
- P2P routing: Transactions can traverse the chain through intermediary nodes
- No pre-configured contacts: Nodes start independently; connections must be established manually
Why This Matters: If Alice wants to transact with Daniel, the transaction must route through Bob and Carol. This demonstrates eIOU’s peer-to-peer relay capabilities.
The bundled compose topology explicitly sets EIOU_ALLOW_PRIVATE_DELIVERY=true on each node because private-address HTTP(S) delivery is blocked by default. Use that opt-in only for intentional private Docker meshes.
Starting the 4-Node Environment
Step 1: Navigate to the eiou-docker Directory
cd /path/to/eiou-docker
Step 2: Clean Up Any Existing Setup
docker compose -f tests/old/compose-files/docker-compose-4line.yml down -v
Step 3: Start the Topology
docker compose -f tests/old/compose-files/docker-compose-4line.yml up -d --build
Step 4: Wait for Initialization
This step is critical. Each node needs time to initialize.
# Wait for all nodes to initialize (2 minutes recommended)
sleep 120
For WSL2 or slow environments, wait up to 180 seconds.
Step 5: Verify All Containers Are Running
docker compose -f tests/old/compose-files/docker-compose-4line.yml ps
Expected output:
NAME STATUS
alice Up 2 minutes (healthy)
bob Up 2 minutes (healthy)
carol Up 2 minutes (healthy)
daniel Up 2 minutes (healthy)
Verifying Each Node
# Verify each node
docker exec alice eiou info
docker exec bob eiou info
docker exec carol eiou info
docker exec daniel eiou info
Quick verification script:
for node in alice bob carol daniel; do
echo "=== $node ==="
docker exec $node eiou info | head -10
echo ""
done
Network Architecture
Within the Docker network, containers resolve each other by hostname:
| From | Can Reach | Via URL |
|---|---|---|
| alice | bob | http://bob |
| bob | alice, carol | http://alice, http://carol |
| carol | bob, daniel | http://bob, http://daniel |
| daniel | carol | http://carol |
Important: Contacts are NOT pre-configured. You must manually add contacts to establish the chain (covered in Section 5).
Section 5: Contact Management Commands
Understanding eIOU Contacts
eIOU contacts form the trust network that enables value transfer.
Bidirectional Requirement
A contact relationship requires mutual agreement — but only one side runs add. The other side runs accept (or apply for multi-currency) on the incoming request. Conceptually:
Alice: eiou contact add http://bob Bob --fee 0.1 --credit 1000 --currency VWL
↓ (sends a contact request to Bob)
Bob: eiou contact pending # see Alice's pending request, copy the pubkey-hash
eiou contact accept <alice-hash> --currency VWL --fee 0.1 --credit 1000
↓ (Bob's accept finalizes the relationship on both sides)
Both nodes now show the contact as ACCEPTED.
For multi-currency relationships, Bob can accept several currencies in one call (--currency VWL --fee … --credit … --currency EUR --fee … --credit …) or use eiou contact apply with a batched payload of accept/decline/defer decisions.
Mutual-add convenience: if both sides happen to run
contact add(each not knowing the other already sent a request), the dispatcher recognises the cross-request and short-circuits toacceptedfor the matching currency. This is convenient but hides the per-currency knobs — useaccept/applywhen you actually want to set fee/credit on the receiving side. See §5.10 for per-currency lifecycle.
Contact Parameters
| Parameter | Flag | Description | Example |
|---|---|---|---|
address |
positional | Node’s network address | http://bob |
name |
positional | Display name | Bob |
fee |
--fee |
Transaction fee percentage you charge to relay this contact’s transactions | 0.1 (0.1%) |
credit |
--credit |
Credit limit you extend. 0 allows the relationship without enabling transactions through you |
1000 |
currency |
--currency |
Currency code for the per-currency row (default VWL) |
VWL |
requested_credit |
--requested-credit |
Credit limit you’d like the receiver to extend to you in this currency. Sent over the wire as requested_credit_limit in the contact payload — the receiver sees it as a suggestion when accepting (the GUI shows it; POST /api/v1/contacts accepts it as requested_credit_limit). The receiver still chooses what to actually grant. |
500 |
message |
--message |
Optional short note attached to the request (E2E or transport-encrypted) | "Hey, it's Dave" |
Flags can appear in any order and in any position relative to the positional <address> <name>.
Contact States
| State | Description |
|---|---|
| Pending (incoming) | Someone requested a contact relationship; you can accept, apply, or decline |
| Pending (outgoing) | You sent a request and are waiting for the other side to accept |
| Accepted | Both sides finalized at least one currency (transactions can flow on accepted currencies) |
| Blocked | Incoming transactions and routing are rejected |
5.1 contact add - Adding Contacts
Syntax:
eiou contact add <address> <name> [--fee F --credit C --currency CCY] [--requested-credit RC] [--message M]
Sends an outbound contact request. The receiving node sees this as a pending incoming request (eiou contact pending) until they accept (or apply). --requested-credit puts a requested_credit_limit field on the wire so the receiver knows the credit limit you’d like them to extend (they still choose what to actually grant on accept).
Creating the A<->B<->C<->D Chain
The canonical flow is add on one side, accept on the other. Below, alice/bob/carol/daniel each issue an outbound add, and the receiving node confirms with accept. We use a small --json | jq snippet to grab the requester’s pubkey-hash because accept keys off the hash, not the address.
# A → B (Alice adds Bob)
docker exec alice eiou contact add http://bob Bob --fee 0.1 --credit 1000 --currency VWL
# B accepts Alice's request
ALICE_HASH=$(docker exec bob eiou contact pending --json | jq -r '.data.incoming[0].pubkey_hash')
docker exec bob eiou contact accept "$ALICE_HASH" --currency VWL --fee 0.1 --credit 1000
# B → C
docker exec bob eiou contact add http://carol Carol --fee 0.1 --credit 1000 --currency VWL
BOB_HASH=$(docker exec carol eiou contact pending --json | jq -r '.data.incoming[0].pubkey_hash')
docker exec carol eiou contact accept "$BOB_HASH" --currency VWL --fee 0.1 --credit 1000
# C → D
docker exec carol eiou contact add http://daniel Daniel --fee 0.1 --credit 1000 --currency VWL
CAROL_HASH=$(docker exec daniel eiou contact pending --json | jq -r '.data.incoming[0].pubkey_hash')
docker exec daniel eiou contact accept "$CAROL_HASH" --currency VWL --fee 0.1 --credit 1000
Mutual-add shortcut: if both nodes run
contact addagainst each other (without usingaccept), the dispatcher recognises the cross-request and finalizes the matching currency toacceptedautomatically. This is what the integration test suite does for speed (tests/testfiles/addContactsTest.sh). It works, but it forces both sides to publish the same fee/credit; useadd + acceptwhen the receiving side wants different terms.
Verifying the Chain
# List accepted contacts on each node
docker exec alice eiou contact list --status accepted
docker exec bob eiou contact list --status accepted
docker exec carol eiou contact list --status accepted
docker exec daniel eiou contact list --status accepted
Cross-Currency Contact Requests
When each side wants to use a different currency, they each issue their own contact add and accept the other’s incoming request per currency. Use contact currency accept (or batched contact apply) — not contact add, which is for outbound new currencies, not for accepting incoming ones.
# Alice requests VWL from Bob
docker exec alice eiou contact add http://bob Bob --fee 0.1 --credit 1000 --currency VWL
# Bob requests GBY from Alice
docker exec bob eiou contact add http://alice Alice --fee 0.2 --credit 4000 --currency GBY
Each side now sees:
- Alice: outgoing VWL (awaiting Bob), incoming GBY (from Bob — can accept/decline)
- Bob: outgoing GBY (awaiting Alice), incoming VWL (from Alice — can accept/decline)
# Bob accepts Alice's incoming VWL request (use the per-currency accept)
docker exec bob eiou contact currency accept Alice VWL --fee 0.2 --credit 4000
# Alice accepts Bob's incoming GBY request
docker exec alice eiou contact currency accept Bob GBY --fee 0.1 --credit 1000
For multiple currencies in one call use contact accept <hash> --currency CCY --fee F --credit C repeated, or contact apply with --accept CCY:fee:credit flags or a JSON file payload.
5.2 contact accept - Accepting Incoming Requests
Accept a pending incoming contact request, optionally for several currencies in one shot.
# Find the requester's pubkey-hash
docker exec bob eiou contact pending
# Single-currency accept
docker exec bob eiou contact accept <pubkey-hash> --currency VWL --fee 0.1 --credit 1000
# Multi-currency accept
docker exec bob eiou contact accept <pubkey-hash> \
--currency VWL --fee 0.1 --credit 1000 \
--currency EUR --fee 0.05 --credit 500
Decline (all pending currencies on the request):
docker exec bob eiou contact decline <pubkey-hash>
Batched accept/decline/defer (contact apply):
# Per-decision flags
docker exec bob eiou contact apply <pubkey-hash> \
--accept VWL:0.1:1000 --accept EUR:0.05:500 --decline GBP --defer XRP
# Or pipe a JSON payload (modal payload shape)
echo '[{"currency":"VWL","action":"accept","fee":"0.1","credit":"1000"}]' \
| docker exec -i bob eiou contact apply <pubkey-hash> --from -
pubkey-hash is the stable identifier; it’s what eiou contact pending --json reports under incoming[].pubkey_hash. Names and addresses also resolve, but the hash is what doesn’t churn across restores.
5.3 contact pending - Viewing Pending Requests
docker exec alice eiou contact pending
# Filter to one direction
docker exec alice eiou contact pending --incoming
docker exec alice eiou contact pending --outgoing
# Scriptable form
docker exec alice eiou contact pending --json
The hint text printed for each incoming request shows a paste-ready eiou contact accept / eiou contact decline line.
5.4 contact search / list - Finding Contacts
# List all contacts grouped by status
docker exec alice eiou contact list
# Filter to one bucket
docker exec alice eiou contact list --status accepted
docker exec alice eiou contact list --status pending
docker exec alice eiou contact list --status blocked
# Substring search by name
docker exec bob eiou contact search Alice
# JSON for scripting
docker exec alice eiou contact list --json
5.5 contact view - Contact Details
# View by name
docker exec alice eiou contact view Bob
# View by address
docker exec bob eiou contact view http://alice
# View by pubkey-hash (most stable identifier)
docker exec alice eiou contact view <pubkey-hash>
Shows contact details including balance, fee, credit limit, and bidirectional available credit:
- Your Available Credit: How much credit you can use through this contact (received via ping, refreshed ~5 min)
- Their Available Credit: How much credit this contact can use through you (calculated from balances + credit limit)
5.6 contact update - Modifying Contacts
The update form is flag-based — same shape as contact add, all fields optional. --currency is required only when --fee or --credit is set (those are stored per-currency).
# Update contact name
docker exec alice eiou contact update Bob --name Robert
# Update fee for VWL
docker exec alice eiou contact update Bob --fee 0.5 --currency VWL
# Update credit limit for EUR
docker exec alice eiou contact update Bob --credit 2000 --currency EUR
# Update multiple fields in one command
docker exec alice eiou contact update Bob --name Robert --fee 0.2 --credit 1500 --currency VWL
Updates are local-only — the contact is not notified. Multi-field updates fan out to one service call per touched field (not atomic). For atomic updates, use PUT /api/v1/contacts/:address.
5.7 contact ping - Checking Online Status
docker exec alice eiou contact ping Bob
Expected output:
Pinging Bob (http://bob)...
Status: ONLINE
Response Time: 45ms
Chain Valid: Yes
Ping also exchanges per-currency available credit and chain validity with the contact. After a ping, eiou contact view will show the latest per-currency available credit values (stored in contact_credit table). Mismatched chain heads trigger a sync, and unrecoverable gaps auto-propose a tx drop.
5.8 contact block/unblock - Blocking Contacts
# Block a contact
docker exec alice eiou contact block Bob
# Verify blocked status
docker exec alice eiou contact view Bob
# Unblock the contact
docker exec alice eiou contact unblock Bob
Effects of blocking:
- They cannot send transactions to you
- They cannot route transactions through you
- Existing balances remain unchanged
5.9 contact delete - Removing Contacts
docker exec alice eiou contact delete OldContact
Warning: Deletion is permanent. Outstanding balances should be settled before deletion.
5.10 contact currency - Per-currency Operations
Once a contact is accepted on one currency, additional currencies are negotiated on the same contact_currencies row, not by re-running contact add. The contact currency namespace handles this lifecycle.
# Propose a new currency on an already-accepted contact
docker exec alice eiou contact currency add Bob EUR --fee 0.05 --credit 500
# Accept an incoming per-currency proposal
docker exec bob eiou contact currency accept Alice EUR --fee 0.05 --credit 500
# Decline an incoming per-currency proposal
docker exec bob eiou contact currency decline Alice EUR
# List every currency configured for a contact (status + direction)
docker exec alice eiou contact currency list Bob
# Locally remove a currency configuration (does NOT notify the remote — use `decline` for that)
docker exec alice eiou contact currency remove Bob EUR
currency decline sends a contact_currency_declined message so the requester’s outgoing-pending row drops on the spot. currency remove is a local cleanup hatch only.
Section 6: Transaction Commands
6.1 send - Sending Transactions
Prerequisite: Ensure contacts have been added as described in Section 5.1. The A<->B<->C<->D chain must be established before sending transactions.
Syntax:
eiou send <address|name> <amount> <currency> [--best]
Direct Transactions
# Alice sends 100 VWL to Bob (direct contact)
docker exec alice eiou send Bob 100 VWL
# Wait for processing
sleep 5
# Verify with balance check
docker exec alice eiou viewbalances
Note: Tor transport is slower than HTTP/HTTPS. If a transaction or balance doesn’t appear immediately, wait a few more seconds and re-check. Results may take longer to propagate over Tor.
Expected output:
Transaction sent successfully.
Recipient: Bob
Amount: 100.00 VWL
Type: standard
6.2 viewbalances - Checking Balances
# View all balances
docker exec alice eiou viewbalances
# View balance with specific contact
docker exec alice eiou viewbalances Bob
Understanding Balance Output:
| Field | Description |
|---|---|
| Sent | Total amount you have sent |
| Received | Total amount received |
| Net Balance | Difference (negative = you owe them) |
6.3 history - Transaction History
# View all transaction history
docker exec alice eiou history
# View history with specific contact
docker exec alice eiou history Bob
# View all (no limit)
docker exec alice eiou history all
6.4 Multi-Hop P2P Routing
This demonstrates eIOU’s key feature: sending transactions to contacts you don’t directly know.
Prerequisite: The full A<->B<->C<->D contact chain from Section 5.1 must be established for P2P routing to work.
How P2P Routing Works
In the 4-node topology:
Alice <--> Bob <--> Carol <--> Daniel
Alice and Daniel cannot transact directly. When Alice sends to Daniel:
- Transaction broadcasts to Alice’s contacts (Bob)
- Relays through Bob to Carol
- Delivers from Carol to Daniel
- Response returns along the route
Demonstration
Step 1: Verify Alice cannot directly reach Daniel
docker exec alice eiou contact search Daniel
# Expected: No contacts found matching "Daniel"
Step 2: Send transaction via P2P routing
docker exec alice eiou send Daniel 100 VWL
Expected output:
Transaction sent via P2P routing.
Recipient: Daniel
Amount: 100.00 VWL
Type: p2p
Route: alice -> bob -> carol -> daniel
Step 3: Wait for P2P propagation
sleep 15
Note: P2P routing takes longer than direct transactions. Over Tor, this can take significantly longer. If balances don’t appear immediately, wait and re-check.
Step 4: Verify balances across all nodes
docker exec alice eiou viewbalances
docker exec bob eiou viewbalances
docker exec carol eiou viewbalances
docker exec daniel eiou viewbalances
Step 5: Check Daniel’s history
docker exec daniel eiou history
Understanding P2P Fees
Fees are added to the sender’s amount, not deducted from the recipient. The P2P request travels forward to find a route, then on the return path (rp2p) the fees are calculated and communicated back to the sender.
Assuming each relay operator has set a 0.01% fee (the default is 0 — no fee), when Alice sends 100 VWL to Daniel:
| Step | Description | Fee (0.01%) |
|---|---|---|
| Alice -> Bob | Direct send (no relay fee) | 0.00 |
| Bob -> Carol | Bob relays | 0.01 |
| Carol -> Daniel | Carol relays | 0.01 |
| Total fees | 0.02 |
Alice sends: 100.02 VWL (100 + relay fees) Daniel receives: 100.00 VWL
Note: Both defaults ship at
0— the default contact fee andminFee— so a fresh node charges nothing for routing; the 0.01% above is an operator-set fee shown for illustration. When an operator does set a small percentage fee, on tiny amounts it can fall below the internal 8-decimal precision (10⁻⁸) and round to zero; an operator who wants the transfer to still cover their routing costs (electricity and the like) can setminFeeto a non-zero floor, which is applied whenever the percentage fee rounds below it.
Only relay nodes charge fees. The sender’s direct contact (Bob) and the recipient (Daniel) do not add relay fees.
Best-Fee Routing (Experimental)
By default, P2P uses fast mode: the first route found is accepted immediately. With --best, the system collects responses from all available routes and selects the one with the lowest accumulated fee.
# Send with best-fee routing
docker exec alice eiou send Daniel 100 VWL --best
Best-fee mode is useful in mesh topologies where multiple routes exist with different fee structures. It adds latency (the system waits for all routes to respond) but may find a cheaper path.
Section 7: System & Utility Commands
7.1 sync - Synchronizing Data
# Full sync
docker exec alice eiou sync
# Sync specific data types
docker exec alice eiou sync contacts
docker exec alice eiou sync transactions
docker exec alice eiou sync balances
When to use sync:
- After network outage
- Balance discrepancy
- Missing transactions
- After container restart
7.2 backup - Backup Management
Checking Backup Status
docker exec alice eiou backup status
Creating Manual Backups
docker exec alice eiou backup create
Listing Backups
docker exec alice eiou backup list
Verifying Backups
docker exec alice eiou backup verify backup_20260126_103045.eiou.enc
Enabling/Disabling Auto-Backup
docker exec alice eiou backup enable
docker exec alice eiou backup disable
Cleanup Old Backups
docker exec alice eiou backup cleanup
Restoring from Backup
# Stop the original node and keep its volumes untouched for rollback.
# Start a separately configured candidate that mounts a new, empty MySQL
# volume and its paired new backup-locks volume, plus the other five volumes
# restored from the same recovery point.
EIOU_BOOT_RECOVERY_BACKUP=backup_20260126_030000.eiou.enc docker compose up
Note: v0.1.18-alpha restore is an internal pre-service boot operation and
cannot run through an ordinary docker exec. It requires the original seed
phrase or surviving config volume, all seven volumes from one recovery point,
and an authenticated v3 backup. See the
Upgrade Guide for the complete candidate
validation and promotion procedure.
7.3 apikey - API Key Management
API keys allow external applications to interact with your eIOU wallet programmatically.
Creating an API Key
# Create with default permissions
docker exec alice eiou apikey create myapp
# Create with specific permissions
docker exec alice eiou apikey create myapp wallet:read,contacts:read
Available permissions:
wallet:read- Read wallet balance and transactionswallet:send- Send transactionscontacts:read- List and view contactscontacts:write- Add, update, delete contactssystem:read- View system status and metricsadmin- Full administrative accessall- All permissions (same as admin)
Listing API Keys
docker exec alice eiou apikey list
Disabling/Enabling an API Key
# Disable (key remains but cannot be used)
docker exec alice eiou apikey disable <key_id>
# Re-enable a disabled key
docker exec alice eiou apikey enable <key_id>
Deleting an API Key
docker exec alice eiou apikey delete <key_id>
API Key Help
docker exec alice eiou apikey help
Security Notes:
- Store API keys securely - they provide access to wallet functions
- Use minimal permissions for each application
- Disable keys when not in active use
- Delete keys for applications no longer needed
Section 8: Cleanup
Stopping Containers (Preserving Data)
docker compose -f tests/old/compose-files/docker-compose-4line.yml down
This stops containers but preserves all data volumes.
Complete Cleanup (Remove All Data)
docker compose -f tests/old/compose-files/docker-compose-4line.yml down -v
Warning: The -v flag removes all Docker volumes. This permanently deletes:
- All transaction history
- All contact relationships
- Wallet private keys
- All encrypted backups
Verifying Cleanup
# Check no containers remain
docker ps | grep -E "alice|bob|carol|daniel"
# Check no volumes remain
docker volume ls | grep -E "alice|bob|carol|daniel"
Expected: No results (empty output) indicates complete cleanup.
Cleaning Up Single Containers
If you created standalone containers:
# Stop and remove container
docker rm -f demo-node
# Remove all seven associated durable volumes
docker volume rm \
demo-mysql-data demo-config demo-plugins demo-plugin-scratch \
demo-backups demo-backup-locks demo-ssl-cert
Quick Reference
Command Summary Table
| Category | Command | Description |
|---|---|---|
| Wallet | eiou info [detail] [--show-auth] |
Wallet information |
eiou overview [limit] |
Dashboard summary | |
| Contacts (lifecycle) | eiou contact add <addr> <name> [--fee F --credit C --currency CCY] [--message M] |
Send outbound contact request |
eiou contact accept <hash> --currency CCY --fee F --credit C [--currency …] |
Accept incoming request (single- or multi-currency) | |
eiou contact apply <hash> [--accept CCY:F:C ...] [--decline CCY] [--defer CCY] |
Batched accept/decline/defer (or --from <file|-> JSON) |
|
eiou contact decline <hash> |
Decline every pending currency on an incoming request | |
eiou contact pending [--incoming|--outgoing] [--json] |
Show pending requests | |
| Contacts (ops) | eiou contact list [--status accepted|pending|blocked] |
List contacts grouped by status |
eiou contact view <name|address|hash> |
View contact details | |
eiou contact search [query] |
Substring search by name | |
eiou contact ping <name|address> |
Check online status + chain heads | |
eiou contact update <name|address> [--name N] [--fee F] [--credit C] [--currency CCY] |
Update contact (local-only; multi-field, non-atomic) | |
eiou contact block <name|address> / eiou contact unblock <name|address> |
Block / unblock contact | |
eiou contact delete <name|address> |
Delete contact (permanent) | |
| Per-currency | eiou contact currency add <contact> <CCY> --fee F --credit C |
Propose a new currency on an accepted contact |
eiou contact currency accept <contact> <CCY> --fee F --credit C |
Accept an incoming per-currency proposal | |
eiou contact currency decline <contact> <CCY> |
Decline an incoming per-currency proposal | |
eiou contact currency list <contact> |
Show all currencies + status + direction | |
eiou contact currency remove <contact> <CCY> |
Locally remove a currency (no remote notify) | |
| Transactions | eiou send <name|addr> <amount> <CCY> [description] [--best] |
Send transaction (direct or P2P-relayed) |
eiou viewbalances [name|addr] |
View balances | |
eiou history [name|addr] [limit] |
Transaction history | |
| Settings | eiou viewsettings |
View settings |
eiou changesettings <key> <value> |
Change setting | |
| System | eiou sync [contacts|transactions|balances] |
Synchronize data |
eiou backup <action> |
Backup management | |
eiou chaindrop <action> |
Tx drop / chain gap resolution | |
eiou help [command] |
Display top-level help (namespaced help comes from the namespace itself, e.g. eiou contact) |
Global Options
| Option | Description |
|---|---|
--json, -j |
Output in JSON format |
--no-metadata |
Exclude metadata from JSON |
Docker Compose Commands
| Command | Description |
|---|---|
docker-compose -f <file>.yml up -d |
Start containers |
docker-compose -f <file>.yml down |
Stop, preserve data |
docker-compose -f <file>.yml down -v |
Stop, remove all data |
docker-compose -f <file>.yml logs -f |
Follow logs |
docker-compose -f <file>.yml ps |
Show status |
Troubleshooting
Container Not Starting
Solutions:
# Check logs
docker logs alice
# Reset and rebuild
docker compose -f tests/old/compose-files/docker-compose-4line.yml down -v
docker compose -f tests/old/compose-files/docker-compose-4line.yml up -d --build
Contact Stuck in Pending
Solutions:
# Check if both nodes are online
docker exec alice eiou contact ping Bob
# Trigger sync on both nodes
docker exec alice eiou sync
docker exec bob eiou sync
Transaction NO_VIABLE_ROUTE Error
Solutions:
# Verify contact is accepted
docker exec alice eiou contact view Bob
# Check contact is online
docker exec alice eiou contact ping Bob
# Sync both nodes
docker exec alice eiou sync
Backup Restore Fails
Solutions:
# Verify wallet is restored first
docker exec alice eiou info
# Verify backup is valid
docker exec alice eiou backup verify <filename>
See Also
- CLI Reference - Complete CLI command documentation
- Docker Configuration - Environment variables and volumes
- API Reference - REST API documentation
- Error Codes - Complete error code reference