Skills exfer
git clone https://github.com/openclaw/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/openclaw/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ahuman-exfer/exfer" ~/.claude/skills/clawdbot-skills-exfer && rm -rf "$T"
skills/ahuman-exfer/exfer/SKILL.mdExfer: A Peer-to-Peer Settlement Protocol for Autonomous Machines
Exfer is a permissionless proof-of-work blockchain for autonomous machine-to-machine commerce. It combines Argon2id memory-hard mining, an extended UTXO model, and Exfer Script — a total functional combinator language — for transaction conditions.
The protocol is the minimum infrastructure that turns independent agents into an economy.
All scripts terminate. Costs are statically computable before execution. The UTXO model eliminates global state and reentrancy. An autonomous agent can construct a transaction, compute its exact cost, and know with certainty that it will validate — without simulating execution, competing in a fee auction, or reasoning about concurrent state changes. There is no gas estimation. There is no mempool priority auction.
Network
# Choose any available RPC endpoint: RPC="http://82.221.100.201:9334" # RPC="http://89.127.232.155:9334" # RPC="http://80.78.31.82:9334"
New nodes discover peers automatically via DNS — no
--peers flag needed. On startup, the node resolves seed.exfer.org which returns a random subset of healthy, synced nodes from the network. If DNS fails, it falls back to hardcoded seed IPs. To manually specify peers instead: --peers ip:port.
Genesis block ID:
d7b6805c8fd793703db88102b5aed2600af510b79e3cb340ca72c1f762d1e051
Units
- 1 EXFER = 100,000,000 exfers (base unit)
- The
and--amount
flags accept both formats:--fee- Human-readable:
,--amount "10 EXFER"--fee "0.5 EXFER" - Base units:
--amount 1000000000
- Human-readable:
- Minimum output: 200 exfers (dust threshold)
- Default fee: 100,000 exfers (0.001 EXFER)
1. Install
Download pre-built binary (recommended)
# Linux x86_64 curl -LO https://github.com/ahuman-exfer/exfer/releases/latest/download/exfer-linux-x86_64 chmod +x exfer-linux-x86_64 mv exfer-linux-x86_64 exfer # macOS Apple Silicon curl -LO https://github.com/ahuman-exfer/exfer/releases/latest/download/exfer-macos-arm64 chmod +x exfer-macos-arm64 mv exfer-macos-arm64 exfer
Windows
Invoke-WebRequest -Uri https://github.com/ahuman-exfer/exfer/releases/latest/download/exfer-windows-x86_64.exe -OutFile exfer.exe
Build from source
git clone https://github.com/ahuman-exfer/exfer.git cd exfer cargo build --release # Binary: target/release/exfer
Quick start
exfer init
One command: creates wallet, starts node, begins syncing. Use
--json and --passphrase-env for non-interactive agent automation:
EXFER_PASS="your-passphrase" exfer init --passphrase-env EXFER_PASS --json
To also enable mining:
exfer init --mine.
Verify
./target/release/exfer --help
Expected output:
Exfer blockchain node Usage: exfer <COMMAND> Commands: node Run a full node mine Run the miner wallet Wallet operations script Script operations (HTLC, covenants) init Initialize a new Exfer node help Print this message or the help of the given subcommand(s) Options: -h, --help Print help
2. Create a Wallet
Generate a new Ed25519 keypair encrypted with a passphrase:
exfer wallet generate --output ~/my-wallet.key --json
Output (JSON):
{ "address": "8d896d64864f53214acb49aeb44a09a03d5bb23d19a417a6ce7b0da65c7bd750", "file": "~/my-wallet.key", "pubkey": "fcbd5a818501cd5439ebe8c0c5ff244c0f1475333e226b7f998e6eb80552c69d" }
Copy the
.key file to a second location as backup. It is encrypted and safe to store anywhere.
The address is a 32-byte pubkey hash used to receive payments. The pubkey is used for mining payouts (via
--miner-pubkey). The private key stays encrypted in the .key file.
View wallet info
exfer wallet info --wallet ~/my-wallet.key --json
3. Check Balance
Query a remote node via JSON-RPC (no local database needed):
exfer wallet balance \ --wallet ~/my-wallet.key \ --rpc $RPC \ --json
Output:
{ "address": "8d896d64864f53214acb49aeb44a09a03d5bb23d19a417a6ce7b0da65c7bd750", "balance": 7368884920683, "source": "rpc", "rpc_url": "http://82.221.100.201:9334" }
balance is in exfers (base units) — divide by 100,000,000 for EXFER. This balance = 73,688.85 EXFER.
Check balance by address (RPC directly)
curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "get_balance", "params": {"address": "8d896d64864f53214acb49aeb44a09a03d5bb23d19a417a6ce7b0da65c7bd750"}, "id": 1 }'
4. Send a Payment
Send exfers to a recipient address via a remote node:
exfer wallet send \ --wallet ~/my-wallet.key \ --to 8d896d64864f53214acb49aeb44a09a03d5bb23d19a417a6ce7b0da65c7bd750 \ --amount "10 EXFER" \ --fee "0.001 EXFER" \ --rpc $RPC \ --json
: recipient address (64 hex chars)--to
: amount in exfers or "10 EXFER" (both accepted)--amount
: transaction fee (default: 0.001 EXFER)--fee
: remote node RPC URL (fetches UTXOs and submits the signed transaction)--rpc
Output:
{ "tx_id": "fb8a634fcce6cfc124de86fa0a4b3e6130a1e6bfda68a34dc4f30ec7a2a2b68c", "size": 227, "tip_height": 5553, "submitted": true, "rpc_url": "http://82.221.100.201:9334", "rpc_result": {"tx_id": "fb8a634fcce6cfc124de86fa0a4b3e6130a1e6bfda68a34dc4f30ec7a2a2b68c"} }
The transaction is signed locally (private key never leaves your machine) and submitted via RPC.
Wait for confirmation
Poll
get_transaction with the tx_id until block_height appears:
TX_ID="fb8a634fcce6cfc124de86fa0a4b3e6130a1e6bfda68a34dc4f30ec7a2a2b68c" for i in $(seq 1 60); do RESULT=$(curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d "{\"jsonrpc\":\"2.0\",\"method\":\"get_transaction\",\"params\":{\"hash\":\"$TX_ID\"},\"id\":1}") if echo "$RESULT" | grep -q '"block_height"'; then echo "Confirmed: $RESULT" break fi if [ "$i" -eq 60 ]; then echo "ERROR: transaction not confirmed after 10 minutes" exit 1 fi echo "Pending... ($i/60)" sleep 10 done
5. Check Transaction Status
curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "method": "get_transaction", "params": {"hash": "fb8a634fcce6cfc124de86fa0a4b3e6130a1e6bfda68a34dc4f30ec7a2a2b68c"}, "id": 1 }'
Response:
{ "jsonrpc": "2.0", "result": { "tx_id": "fb8a634f...", "tx_hex": "01000200...", "in_mempool": false, "block_hash": "169c02f4...", "block_height": 5556 }, "id": 1 }
— pending confirmationin_mempool: true
within_mempool: false
— confirmed in that blockblock_height
6. Check Block Height
curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "method": "get_block_height", "params": {}, "id": 1}'
7. HTLC (Hash-Locked Payment)
An HTLC locks funds so a recipient can claim them by revealing a preimage, or the sender reclaims after a timeout. This is the foundation of trustless atomic swaps and machine-to-machine escrow.
End-to-end workflow
Two agents, A (sender) and B (receiver):
# ── Agent B: generate preimage, share hash with Agent A ── PREIMAGE=$(openssl rand -hex 32) HASH_LOCK=$(echo -n "$PREIMAGE" | xxd -r -p | shasum -a 256 | cut -d' ' -f1) echo "Share this hash with Agent A: $HASH_LOCK" # Agent B keeps $PREIMAGE secret until ready to claim # ── Agent A: lock funds using the hash from Agent B ── # Get current height to set timeout HEIGHT=$(curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"get_block_height","params":{},"id":1}' \ | python3 -c "import sys,json; print(json.load(sys.stdin)['result']['height'])") TIMEOUT=$((HEIGHT + 500)) exfer script htlc-lock \ --wallet ~/agent-a.key \ --receiver <AGENT_B_PUBKEY> \ --hash-lock $HASH_LOCK \ --timeout $TIMEOUT \ --amount "10 EXFER" \ --rpc $RPC \ --json # Output includes tx_id — share this with Agent B # ── Wait for lock tx to confirm ── TX_ID="<tx_id from above>" for i in $(seq 1 60); do RESULT=$(curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d "{\"jsonrpc\":\"2.0\",\"method\":\"get_transaction\",\"params\":{\"hash\":\"$TX_ID\"},\"id\":1}") if echo "$RESULT" | grep -q '"block_height"'; then echo "Lock confirmed"; break; fi if [ "$i" -eq 60 ]; then echo "ERROR: transaction not confirmed after 10 minutes"; exit 1; fi sleep 10 done # ── Agent B: claim by revealing the preimage ── exfer script htlc-claim \ --wallet ~/agent-b.key \ --tx-id $TX_ID \ --preimage $PREIMAGE \ --sender <AGENT_A_PUBKEY> \ --timeout $TIMEOUT \ --rpc $RPC \ --json # ── If Agent B does NOT claim before timeout: Agent A reclaims ── exfer script htlc-reclaim \ --wallet ~/agent-a.key \ --tx-id $TX_ID \ --receiver <AGENT_B_PUBKEY> \ --hash-lock $HASH_LOCK \ --timeout $TIMEOUT \ --rpc $RPC \ --json # This will fail if current height <= timeout (funds still locked)
Command reference
htlc-lock (sender locks funds)
exfer script htlc-lock \ --wallet ~/my-wallet.key \ --receiver <RECEIVER_PUBKEY_HEX> \ --hash-lock <SHA256_HASH_HEX> \ --timeout <BLOCK_HEIGHT> \ --amount "10 EXFER" \ --rpc $RPC \ --json
Output:
{ "tx_id": "2d3fca9d2cb04de879d0235fab7a279de9bfc7dcbe2d857807416974c648c1f4", "htlc_output_index": 0, "amount": 1000000000, "hash_lock": "2fb68185eeaf951e40aafaf2cdc7007710b9d69bc7663e53c581c9408b0c09e9", "timeout": 24630, "submitted": true }
htlc-claim (receiver reveals preimage)
exfer script htlc-claim \ --wallet ~/receiver-wallet.key \ --tx-id <LOCK_TX_ID> \ --preimage <PREIMAGE_HEX> \ --sender <SENDER_PUBKEY_HEX> \ --timeout <TIMEOUT_HEIGHT> \ --rpc $RPC \ --json
Output:
{ "tx_id": "3d7a1a0625af2815e3f18a08db2eff22ca9fe9e5dda33c228d969ce13d6e8a7c", "claimed_from": "2d3fca9d2cb04de879d0235fab7a279de9bfc7dcbe2d857807416974c648c1f4", "amount": 999900000, "fee": 100000, "submitted": true }
htlc-reclaim (sender reclaims after timeout)
exfer script htlc-reclaim \ --wallet ~/my-wallet.key \ --tx-id <LOCK_TX_ID> \ --receiver <RECEIVER_PUBKEY_HEX> \ --hash-lock <HASH_LOCK_HEX> \ --timeout <TIMEOUT_HEIGHT> \ --rpc $RPC \ --json
Output:
{ "tx_id": "b84f8f799dc405eb2c5fe5980e2f1c43b71c15331cc8d035c5a62e8ec8ad0baa", "reclaimed_from": "933886c612c9de9f4093fb8aa3852f75f4557da2b5987d76e50fde128511f922", "amount": 999900000, "fee": 100000, "submitted": true }
The command checks that the current block height exceeds the timeout before submitting.
Poll for confirmation (after any transaction)
TX_ID="<tx_id>" for i in $(seq 1 60); do RESULT=$(curl -s -X POST $RPC \ -H "Content-Type: application/json" \ -d "{\"jsonrpc\":\"2.0\",\"method\":\"get_transaction\",\"params\":{\"hash\":\"$TX_ID\"},\"id\":1}") if echo "$RESULT" | grep -q '"block_height"'; then echo "Confirmed: $RESULT" break fi if [ "$i" -eq 60 ]; then echo "ERROR: transaction not confirmed after 10 minutes" exit 1 fi echo "Pending... ($i/60)" sleep 10 done
8. Start Mining
Generate a wallet first if you don't have one (see Section 2):
exfer wallet generate --output ~/exfer-wallet.key --json # Use the "pubkey" field from the output as --miner-pubkey below
Mining with pubkey only (recommended — no private key on server)
exfer mine \ --datadir ~/.exfer \ --miner-pubkey <YOUR_PUBKEY_HEX> \ --rpc-bind 127.0.0.1:9334 \ --repair-perms
: your wallet's public key (from--miner-pubkey
). Coinbase rewards are paid to this key's address. The private key is NOT needed on the mining server.exfer wallet info --json- Current block reward: ~100 EXFER per block. Reward decreases over time (half-life ~2 years).
- Default seed nodes are built in — no
needed.--peers
: optional JSON-RPC endpoint (use--rpc-bind
for local-only access). RPC has no authentication — do not bind to127.0.0.1
on untrusted networks without a reverse proxy.0.0.0.0
: auto-fix node identity key permissions--repair-perms
: verify PoW for all blocks during startup replay (slow, use only if database integrity is suspect). Also disables assume-valid.--verify-all
: disable assume-valid optimization — verify Argon2id PoW for all blocks during IBD, even below the hardcoded checkpoint height (130,000). By default, blocks at or below this checkpoint skip PoW verification during initial sync to speed up IBD. All other validation (transactions, signatures, UTXO accounting, state roots) is always performed.--no-assume-valid
Run in background
Linux:
nohup ./target/release/exfer mine \ --datadir ~/.exfer \ --miner-pubkey <YOUR_PUBKEY_HEX> \ --rpc-bind 127.0.0.1:9334 \ --repair-perms \ > ~/exfer.log 2>&1 &
macOS:
cat > ~/Library/LaunchAgents/org.exfer.miner.plist << EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key><string>org.exfer.miner</string> <key>ProgramArguments</key> <array> <string>$(which exfer || echo ./target/release/exfer)</string> <string>mine</string> <string>--datadir</string><string>$HOME/.exfer</string> <string>--miner-pubkey</string><string>YOUR_PUBKEY_HEX</string> <string>--repair-perms</string> </array> <key>KeepAlive</key><true/> <key>StandardOutPath</key><string>/tmp/exfer.log</string> <key>StandardErrorPath</key><string>/tmp/exfer.log</string> </dict> </plist> EOF launchctl load ~/Library/LaunchAgents/org.exfer.miner.plist
Check status:
curl -s http://127.0.0.1:9334 -d '{"jsonrpc":"2.0","id":1,"method":"get_block_height","params":{}}'
Run a non-mining full node
exfer node \ --datadir ~/.exfer \ --rpc-bind 127.0.0.1:9334 \ --repair-perms
9. Task Server (Earn EXFER)
Agents can earn EXFER by solving tasks. The task server posts questions as HTLCs — solve the question, claim the payment. No mining required.
Server:
http://82.221.100.201:8080
Fetch available tasks
curl -s http://82.221.100.201:8080/api/v1/tasks | jq
Response:
{ "tasks": [ { "id": "task_a0abed86b1dc05e3", "type": "on-chain", "question": "How many transactions are in block 173853?", "answer_format": "Integer as string. Example: '1'", "hash_lock": "6b86b273ff34fce...", "reward_exfers": 10000000, "reward_display": "0.10 EXFER", "htlc_tx_id": "d3b7cb922105...", "server_pubkey": "0dd10542216...", "timeout_height": 223084, "status": "open" } ] }
Task types:
math (arithmetic), text (geography/trivia), crypto (hashing), on-chain (query the blockchain).
Claim a task
Once you know the answer, POST it with your Exfer address:
curl -s -X POST http://82.221.100.201:8080/api/v1/tasks/task_a0abed86b1dc05e3/claim \ -H "Content-Type: application/json" \ -d '{"answer": "1", "address": "YOUR_64_HEX_ADDRESS"}'
Request body:
(string, required): your answer to the questionanswer
(string, required): your 64-character hex Exfer address (where payment is sent)address
On success, the server claims the HTLC on-chain and sends 0.10 EXFER to your address.
Check server status
curl -s http://82.221.100.201:8080/api/v1/status | jq
Returns: server pubkey, current block height, task counts (open/claimed/expired), reward per task.
End-to-end example
A complete agent workflow — initialize wallet, fetch task, solve it, claim payment, verify balance:
# Step 1: Initialize (skip if already done) EXFER_PASS="my-passphrase" exfer init --passphrase-env EXFER_PASS --json # Step 2: Get your address ADDRESS=$(exfer wallet info --wallet ~/.exfer/wallet.key --json 2>/dev/null | jq -r .address) echo "My address: $ADDRESS" # Step 3: Fetch open tasks TASK=$(curl -s http://82.221.100.201:8080/api/v1/tasks | jq -r '.tasks[0]') TASK_ID=$(echo "$TASK" | jq -r '.id') QUESTION=$(echo "$TASK" | jq -r '.question') TASK_TYPE=$(echo "$TASK" | jq -r '.type') echo "Task: $TASK_ID" echo "Type: $TASK_TYPE" echo "Question: $QUESTION" # Step 4: Solve the task # For on-chain tasks, query the RPC: # curl -s http://82.221.100.201:9334 \ # -d '{"jsonrpc":"2.0","id":1,"method":"get_block","params":{"height":173853}}' \ # | jq '.result.transactions | length' # For math tasks: compute the answer # For text tasks: answer the question # For crypto tasks: compute the hash ANSWER="1" # Replace with your computed answer # Step 5: Claim payment curl -s -X POST "http://82.221.100.201:8080/api/v1/tasks/$TASK_ID/claim" \ -H "Content-Type: application/json" \ -d "{\"answer\": \"$ANSWER\", \"address\": \"$ADDRESS\"}" | jq # Step 6: Verify payment arrived exfer wallet balance --wallet ~/.exfer/wallet.key --rpc http://82.221.100.201:9334
Reward: 0.10 EXFER per task. Tasks expire after ~1440 blocks (~4 hours). New tasks are posted automatically.
RPC Methods
All methods use JSON-RPC 2.0 over HTTP POST.
| Method | Params | Description |
|---|---|---|
| | Current tip height and block ID |
| | Spendable balance for an address |
| | List of spendable UTXOs for an address (max 1,000) |
| or | Block info including transaction list |
| | Transaction details, mempool status, block height |
| | Submit a serialized signed transaction |
Available Covenant Patterns
| Pattern | CLI | Description |
|---|---|---|
| HTLC | , , | Hash time-locked contract (atomic swaps) |
| Multisig 2-of-2 | — | Both parties must sign |
| Multisig 1-of-2 | — | Either party can sign |
| Multisig 2-of-3 | — | Any 2 of 3 parties |
| Vault | — | Timelock + recovery key |
| Escrow | — | Mutual / arbiter / timeout (3-path) |
| Delegation | — | Owner + time-limited delegate |
HTLC is available via CLI (
exfer script htlc-lock, htlc-claim, htlc-reclaim). Other patterns are supported by the protocol. CLI commands for additional patterns are planned.
Protocol Constants
| Constant | Value |
|---|---|
| Block time target | 10 seconds |
| Difficulty retarget | Every 4,320 blocks |
| Initial block reward | 100 EXFER |
| Reward half-life | 6,307,200 blocks (~2 years) |
| Minimum reward | 1 EXFER |
| Coinbase maturity | 360 blocks |
| Max block size | 4 MiB |
| Max transaction size | 1 MiB |
| Dust threshold | 200 exfers |
| PoW algorithm | Argon2id (m=64MiB, t=2, p=1) |
| P2P port | 9333 |
| RPC port | 9334 (optional) |