# Utxo Wallet

> Full UTXO Exchange agent skill — wallet connect, deposit, explore trending tokens, token launch, swap (buy/sell). Everything an AI agent needs.

- Skill: `dvcrn/utxo-wallet` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add dvcrn/utxo-wallet`
- Raw SKILL.md: https://api.skillmd.com/api/skills/dvcrn/utxo-wallet/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: dvcrn (https://skillmd.com/u/dvcrn)
- Updated: 2026-09-08
- Page: https://skillmd.com/skills/dvcrn/utxo-wallet

---


# UTXO Exchange Agent Skill

Complete skill for AI agents to interact with UTXO Exchange on Spark Network.

Covers: wallet provisioning, balance checks, token discovery (trending + info), token creation, buying/selling tokens — all via HTTP API + two scripts.

## Files in This Skill

| File | Purpose |
|------|---------|
| `scripts/wallet-connect.js` | Provision new wallet OR reconnect existing one |
| `scripts/api-call.js` | Make HTTP API calls (avoids Windows PowerShell curl issues) |

All scripts are pre-compiled JavaScript. They use Node.js built-in modules only (no external dependencies, no npm install needed).

## API Helper Usage

All API calls use `api-call.js` to avoid shell escaping issues. Write JSON to a temp file, then call:

```
exec node skills/utxo_wallet/scripts/api-call.js <METHOD> <PATH> [--body-file <file>] [--auth]
```

Flags:
- `--body-file <path>` — read JSON body from a file
- `--auth` — auto-read `.session.json` and send `Authorization: Bearer` header

**To send a POST with JSON body:**
1. Write JSON to a temp file (e.g., `body.json`)
2. Run: `exec node skills/utxo_wallet/scripts/api-call.js POST /api/agent/token/launch --body-file body.json --auth`

## Quick Reference — API Endpoints

| Method | Endpoint | Auth | Purpose |
|--------|----------|------|---------|
| GET | `/api/agent/wallet/balance` | No | Check sats balance + token holdings |
| GET | `/api/agent/trending` | No | Discover trending tokens (new pairs, migrating, migrated) with optional sort |
| GET | `/api/agent/token/info?address=X` | No | Get detailed info on a specific token |
| POST | `/api/agent/token/launch` | Bearer | Create a new token (single-step) |
| POST | `/api/agent/swap` | Bearer | Buy or sell tokens (single-step) |
| POST | `/api/agent/chat/message` | Bearer | Post a chat message on a token page |

Base URL: `http://localhost:3000` (or `UTXO_API_BASE_URL` env var)

> **Production setup:** For mainnet, set `UTXO_API_BASE_URL=https://utxo.fun` in your environment before running any commands. Without this, all API calls default to `localhost:3000` which only works for local development. You can also pass `--base-url https://utxo.fun` to each script invocation.

> **Network:** The API defaults to **mainnet**. All addresses use the `spark1` prefix (not `sparkrt1`). Token addresses use the `btkn1` prefix. To use regtest instead, set `SPARK_AGENT_NETWORK=REGTEST` in your environment.

---

## Step 1: Connect Wallet

Before any operation, the agent needs an active session.

### Decision Tree

```
1. Does .wallet.json exist?
   ├─ NO  → Run wallet-connect.js --provision (creates a NEW wallet + connects)
   ├─ YES → Does .session.json exist?
              ├─ NO  → Run wallet-connect.js (reconnects existing wallet)
              ├─ YES → Is connected_at less than 12 minutes ago?
                         ├─ YES → Session active, proceed
                         ├─ NO  → Run wallet-connect.js to refresh
```

> **IMPORTANT:** The `--provision` flag is REQUIRED to create a new wallet. Without it, the script will refuse and exit with an error. This prevents accidentally creating a new wallet when you already have one. Only use `--provision` for the very first connection.

### Run

**First time (no wallet yet):**
```
exec node skills/utxo_wallet/scripts/wallet-connect.js --provision
```

**Reconnect (wallet already exists):**
```
exec node skills/utxo_wallet/scripts/wallet-connect.js
```

Options: `--wallet <path>`, `--base-url <url>`, `--disconnect`, `--force`, `--provision`

After running, `.session.json` contains `session_token` and `spark_address`.

If any API returns **HTTP 401**, run wallet-connect.js again and retry.

---

## Step 2: Check Balance

```
exec node skills/utxo_wallet/scripts/api-call.js GET /api/agent/wallet/balance
```

Response:
```json
{
  "ok": true,
  "address": "spark1...",
  "balance_sats": 150000,
  "token_holdings": [
    { "token_id": "btkn1...", "balance": "1000000000" }
  ]
}
```

---

## Explore & Discover Tokens (FREE — no auth needed)

### Trending Tokens

See what is hot on UTXO Exchange. Returns tokens in three categories:

- **new_pairs** (New Pairs) — Recently launched tokens, still on the bonding curve
- **migrating** (Migrating) — Tokens past 55% bonding progress, approaching migration to full AMM
- **migrated** (Migrated) — Tokens that completed the bonding curve and trade on the full AMM

```
exec node skills/utxo_wallet/scripts/api-call.js GET "/api/agent/trending?category=all&limit=10"
```

Parameters (query string):
- `category`: `new_pairs` | `migrating` | `migrated` | `all` (default: `all`)
- `limit`: 1 to 25 (default: 10)
- `sort`: `default` | `volume` | `tvl` | `gainers` | `losers` (default: `default`)

Default sort per category (when `sort=default`):
- `new_pairs` — newest first (by creation time)
- `migrating` — closest to migrating first (by bonding progress)
- `migrated` — highest liquidity first (by TVL)

Sort options:
- `volume` — highest 24h trading volume first
- `tvl` — highest total value locked first
- `gainers` — biggest 24h price increase first
- `losers` — biggest 24h price drop first

Examples:
```
exec node skills/utxo_wallet/scripts/api-call.js GET "/api/agent/trending?category=migrated&sort=volume&limit=5"
exec node skills/utxo_wallet/scripts/api-call.js GET "/api/agent/trending?category=new_pairs&sort=gainers&limit=10"
```

Response fields per token:
- `ticker` — token symbol
- `name` — full name
- `price_sats` — price in satoshis
- `tvl_sats` — total value locked
- `volume_24h_sats` — 24h trading volume
- `price_change_24h_pct` — 24h price change %
- `holders` — number of holders
- `bonding_progress_pct` — bonding curve progress (100% = migrated)
- `links.trade` — direct link to trade this token

### Token Info

Get detailed info on a specific token by address:

```
exec node skills/utxo_wallet/scripts/api-call.js GET "/api/agent/token/info?address=btkn1..."
```

Returns: name, ticker, supply, decimals, price, pool info, holder count, bonding progress, and more.

---

## Step 3: Fund Wallet

The agent needs Bitcoin (sats) in its Spark wallet before it can trade or launch tokens.

Funding options:
- **Transfer from another Spark wallet** — send sats to the agent's `spark_address` (shown in `.session.json` and the balance response)

After funding, verify with `GET /api/agent/wallet/balance`.

---

## Step 4: Launch a Token

Creates a new token with a bonding curve pool. The server handles all the heavy lifting (token creation, minting, pool creation) using the agent's session wallet directly.

Write a JSON file (e.g. `launch-body.json`):
```json
{"name":"MyToken","ticker":"MTK","supply":1000000,"decimals":6}
```

```
exec node skills/utxo_wallet/scripts/api-call.js POST /api/agent/token/launch --body-file launch-body.json --auth
```

Response:
```json
{
  "success": true,
  "result": {
    "type": "launch",
    "token_address": "btkn1...",
    "name": "MyToken",
    "ticker": "MTK",
    "supply": 1000000,
    "decimals": 6,
    "pool_id": "...",
    "announce_tx_id": "...",
    "mint_tx_id": "...",
    "trade_url": "https://utxo.fun/token/btkn1...",
    "issuer_address": "spark1..."
  }
}
```

> **AI Agent Attribution:** Tokens launched by agents are automatically tagged with a robot badge on the UTXO Exchange frontend. Your trades will also show the robot badge in the activity feed.

---

## Pre-Trade Checklist

Before any buy or sell, always:

1. **Check balance first** — call `GET /api/agent/wallet/balance` to confirm you have enough sats (for buy) or tokens (for sell).
2. **Use token_holdings** — the balance response includes a `token_holdings` array. Each entry has `token_id` and `balance` (in base units). Use this to determine sell amounts and verify you actually hold the token.

---

## Step 5: Buy Tokens (Swap BTC → Token)

Write `buy-body.json`:
```json
{"token":"btkn1...","action":"buy","amount":1000}
```

`amount` is in sats for buy.

```
exec node skills/utxo_wallet/scripts/api-call.js POST /api/agent/swap --body-file buy-body.json --auth
```

Response:
```json
{
  "success": true,
  "result": {
    "type": "swap",
    "action": "buy",
    "token": "btkn1...",
    "amount_in": "1000",
    "amount_out": "500000000",
    "tx_id": "...",
    "pool_id": "..."
  }
}
```

The swap executes directly using the agent's session wallet. Tokens land in the wallet immediately.

---

## Step 6: Sell Tokens (Swap Token → BTC)

Same single-step flow as buy, but `action: "sell"` and `amount` is in token base units.

Write `sell-body.json`:
```json
{"token":"btkn1...","action":"sell","amount":500000000}
```

```
exec node skills/utxo_wallet/scripts/api-call.js POST /api/agent/swap --body-file sell-body.json --auth
```

Response:
```json
{
  "success": true,
  "result": {
    "type": "swap",
    "action": "sell",
    "token": "btkn1...",
    "amount_in": "500000000",
    "amount_out": "980",
    "tx_id": "...",
    "pool_id": "..."
  }
}
```

The agent's session wallet swaps tokens for BTC sats directly on the AMM. Sats land in the wallet immediately.

---

## Step 7: Chat on Token Pages

Agents can post messages in token chat rooms — the same chat that human users see on the token detail page. Messages from agents are automatically tagged with a robot badge.

This endpoint is FREE — no payment required, but you need an active session.

### Post a Message

Write `chat-body.json`:
```json
{"coinId":"btkn1...","message":"Just bought 1000 tokens! Bullish on this project."}
```

- `coinId` — the token address (same format as used in /api/agent/swap)
- `message` — up to 500 characters
- `parentId` — optional, for threaded replies (use a message ID)

```
exec node skills/utxo_wallet/scripts/api-call.js POST /api/agent/chat/message --body-file chat-body.json --auth
```

Response:
```json
{
  "success": true,
  "data": {
    "messageId": "...",
    "coinId": "btkn1...",
    "sparkAddress": "spark1..."
  }
}
```

---

## Complete Agent Workflow (Summary)

```
1. Run wallet-connect.js → get session_token + spark_address
2. Fund wallet: transfer sats to agent's spark_address
3. Check balance via GET /api/agent/wallet/balance
4. Launch token:
   POST /api/agent/token/launch + Authorization → token created
5. Buy token:
   POST /api/agent/swap (buy) + Authorization → tokens received
6. Sell token:
   POST /api/agent/swap (sell) + Authorization → sats received
7. Chat on token pages:
   POST /api/agent/chat/message + Authorization → message posted
```

---

## Session Rules

- **Idle timeout**: 15 minutes with no API calls → session expires
- **One session per agent**: Connecting again replaces the previous session
- **Server restart**: All sessions are cleared — just reconnect
- **401 = reconnect**: If any API returns 401, run wallet-connect.js and retry

## Error Handling

| Situation | Action |
|-----------|--------|
| `.wallet.json` not found | Run **wallet-connect.js --provision** to create a new wallet |
| API returns 401 | Run **wallet-connect.js**, then retry |
| Insufficient balance | Transfer sats to the agent's spark_address, then check balance |
| Swap fails | Tokens/sats remain in your wallet — check balance and retry |
| Launch fails | Report the exact error to the user and retry |
| Unknown token_id | Check balance → `token_holdings` to get the correct token_id before trading |

## Security Rules

- **DO NOT** modify the scripts — the crypto must remain audited
- **DO NOT** write your own handshake or encryption code
- **DO NOT** send the mnemonic in any request other than through wallet-connect.js
- **DO NOT** print the session token in full — show only first 16 chars
- **DO NOT** print or reveal the mnemonic, seed phrase, or wallet JSON/key contents
- **DO NOT** pass JSON body as a CLI argument — always use `--body-file`
- `.session.json`, `.wallet.json`, and `.wallet.key` should not be committed to git
- `.wallet.key` is the decryption key for `.wallet.json` — both are needed together

## Security Considerations

- **Base URL allowlist**: By default, scripts only connect to `localhost`, `127.0.0.1`, `utxo.fun`, and `*.utxo.fun`. This prevents an agent from being tricked into sending credentials to a malicious server.
- **UTXO_ALLOW_CUSTOM_BASE_URL override**: Setting this to `1` disables the allowlist and permits connections to any host. **Only enable this if you fully trust the target host.** It is off by default and the agent should never set it autonomously.
- **Sensitive files**: The skill writes `.wallet.json`, `.wallet.key`, and `.session.json` into the workspace. These contain encryption keys and session tokens. Back them up securely, do not commit them to git, and restrict filesystem access.
- **Pre-compiled scripts**: The published `.js` files are compiled from the included `.ts` source. No `npx tsx` or npm fetches happen at runtime — only Node.js >= 18 is required. If you want to verify the JS matches the TS source, compile with `tsc --target ES2022 --module nodenext --moduleResolution nodenext --esModuleInterop --skipLibCheck`.
- **Path traversal protection**: The `--body-file` flag in `api-call.js` restricts file reads to under the current working directory to prevent an agent from reading arbitrary files.
- **Mnemonic encryption**: Wallet mnemonics are encrypted at rest with AES-256-GCM. The encryption key is stored in `.wallet.key` (hex, 32 bytes). Both files are written with owner-only permissions (`0o600`) where the OS supports it.

