Emercoin swap

Emercoin swap

Keyless MCP exchanger for AI agents — pay an exact amount to one deposit address, EMC delivered to any address. USDT(Tron) > EMC. Live at https://swap.emercoin.com/mcp

Category
Visit Server

README

swap — EMC cashier (USDT → EMC)

A minimal cashier exposing one primitive. All business logic stays in the calling services; swap knows nothing about NVS/DNS/subscriptions.

buy_emc(amount_usdt, destination_emc_address, callback_url, ref)
  → collect USDT on a unique deposit address
  → on confirmation, deliver EMC (fixed rate ×10) to destination
  → notify the caller with a SIGNED callback

destination is opaque to swap: it can be a service's address (the service then renders its own product on that EMC — the user only ever pays USDT and never touches a wallet) or the user's own address (raw on-ramp).

Use via MCP

An AI agent with USDT can buy EMC directly — no account, no API key, no callback. swap exposes a keyless MCP exchanger over Streamable HTTP at:

https://swap.emercoin.com/mcp

Add it to a client:

# Claude Code
claude mcp add --transport http swap https://swap.emercoin.com/mcp
  • Claude Desktop — Settings → Connectors → Add custom connector → the URL above.
  • MCP Inspectornpx @modelcontextprotocol/inspector → Streamable HTTP → the URL.

Tools:

Tool What it does
get_swap_config min/max USDT per order + the fixed EMC-per-USDT rate
buy_emc open an order → returns a deposit address + the exact USDT amount to send (+ optional idempotency_key)
get_order_status poll an order by its token until delivered
cancel_order drop an unpaid order early

Flow: get_swap_configbuy_emc(amount, your_emc_address) → send the exact returned amount (TRC20) to the deposit address → poll get_order_status by token until notified. One-way, exact-amount, no refunds. The same primitive is also available as keyed REST (for services, with a signed callback) and a keyless web page at swap.emercoin.com.

Locked decisions

Topic Decision
Rate static 1 USDT = 10 EMC
Cap / floor 5–10 USDT (floor 5: below it TRON gas dominates)
USDT rail TRC20 (TRON)
Payment match one shared deposit address + unique per-order amount tag
EMC delivery via emercoin adapter POST /wallet/send (X-Internal-Key)
Callback signature HMAC-SHA256 over canonical body, per-service secret
KYC none (amounts far below threshold)
AML minimal but mandatory — OFAC SDN + Tether freeze blacklist
Terms exact amount, single transfer, one-way (no refunds) — state in the offer

Layout

swap/
  config.py        env-driven settings (pydantic-settings)
  models.py        OrderStatus enum + request/response schemas
  states.py        order state machine (allowed transitions)
  schema.sql       DDL: services/orders/deposits/aml_checks/sweeps/callbacks
  db.py            SQLite connection + init
  repository.py    DB access layer
  auth.py          caller auth by API key
  orders.py        buy_emc business logic (shared by REST + MCP)
  main.py          FastAPI app (REST: POST /buy_emc, GET /order/{id})
  mcp_app.py       keyless MCP exchanger at /mcp (agent tools, mirrors /web)
  web.py           public keyless /web/* channel (raw on-ramp for humans)
  site/            static exchanger page + offer (index.html, oferta.html)
  clients/
    adapter.py     EMC delivery + balance via emercoin adapter
    trongrid.py    TRC20 deposit watcher source (TronGrid)
  tron/
    hd.py          HD derivation of deposit addresses (BIP44, coin 195)
  services/
    aml.py         OFAC + Tether blacklist screening
    delivery.py    deliver EMC from reserve (idempotent)
    callback.py    signed callback notifier + retries
    watcher.py     background loop: deposits → confirm → AML → deliver → notify
    sweep.py       USDT consolidation from deposit addresses

State machine

created → awaiting_payment → confirmed → emc_delivered → notified (done)
                                ↘ underpaid    (top-up or partial refund)
                                ↘ overpaid     (refund excess)
                                ↘ aml_hold     (sender blacklisted → manual)
                                ↘ deliver_failed (retry; else refund USDT)
expired — no payment before TTL

Dev

uv sync --extra dev
cp .env.example .env          # fill secrets
uv run uvicorn swap.main:app --reload --port 8002

EMC delivery and the TRON watcher need the emercoin adapter and TronGrid creds; for local end-to-end you can bring up the node+adapter from emercoin_docker (docker compose --profile dev up). TRON parts are verified in a test environment before they are wired into the watcher.

Schema changes have no migrations. db.py applies schema.sql with CREATE TABLE IF NOT EXISTS, which does not alter an existing table. After editing schema.sql in dev, reset the database: rm swap.db (then restart — it recreates the schema — and re-run scripts/register_service since the services table is wiped too). swap.db holds only local/test data.

Status: full happy path verified live end-to-end (+ 41 unit tests). On 2026-06-14 a real run took a TRC20 USDT deposit on TRON Nile testnetconfirmed → delivered real EMC on Emercoin mainnet (via the adapter /wallet/send) → signed callback verified by the receiver against the service's HMAC secret: awaiting_payment → confirmed → emc_delivered → notified. See docs/TESTNET.md for the runbook (scripts/testnet/).

AML is live: OFAC SDN addresses (TRON) loaded into memory + refreshed, and a per-deposit live Tether isBlackListed check; a hit → aml_hold (no delivery).

Payment matching: pivoted from a unique HD address per order to one shared deposit address + a unique per-order amount tag (matched by exact amount). This removes per-order sweeping and the fresh-address gas penalty; the trade-off is exact-amount, single-transfer payments (no auto under/overpaid). Collected USDT is moved to treasury / off-ramp manually at low volume. MCP exchanger: the keyless web on-ramp is also exposed as MCP tools (buy_emc, get_order_status, cancel_order, get_swap_config) over Streamable HTTP at /mcp, so an AI agent buys EMC with USDT directly — no key, no callback, same anti-spam as the web channel. No auth by design: it's a public "pay for a service" on-ramp, not an account. Tool definitions pass a pre-publication TDQS review (all tier A); see docs/TDQS.md.

Deferred: USDT sweep / TRON tx signing (services/sweep.py, kept off the hot path).

License

MIT — see LICENSE.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured