Reference

CLI Demo Guide

eIOU CLI Demo Guide

A step-by-step walkthrough for demonstrating eIOU CLI commands.

Table of Contents

  1. Overview
  2. Prerequisites & Installation
  3. Creating Containers
  4. Basic Wallet Commands
  5. Multi-Container Network Setup
  6. Contact Management Commands
  7. Transaction Commands
  8. System & Utility Commands
  9. Cleanup
  10. Quick Reference
  11. 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_HOST set: 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:

  1. Generates a new BIP39 seed phrase (24 words)
  2. Creates wallet keys from the seed phrase
  3. Configures the node hostname for HTTP and HTTPS
  4. Generates SSL certificates for HTTPS
  5. Starts Tor and generates .onion address
  6. Initializes the database
  7. 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 inspect output
  • 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 to accepted for the matching currency. This is convenient but hides the per-currency knobs — use accept / apply when 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 add against each other (without using accept), the dispatcher recognises the cross-request and finalizes the matching currency to accepted automatically. 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; use add + accept when 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:

  1. Transaction broadcasts to Alice’s contacts (Bob)
  2. Relays through Bob to Carol
  3. Delivers from Carol to Daniel
  4. 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 and minFee — 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 set minFee to 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 transactions
  • wallet:send - Send transactions
  • contacts:read - List and view contacts
  • contacts:write - Add, update, delete contacts
  • system:read - View system status and metrics
  • admin - Full administrative access
  • all - 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