A TypeScript server for executing token swaps via COWSwap, designed to run in a Trusted Execution Environment (TEE). Creates one-time use deposit addresses for trustless, non-custodial swaps.
# Install dependencies
bun install
# Start the database
bun run db:up
# Push the schema to the database
DATABASE_URL=postgres://tee_swapper:tee_swapper_dev@localhost:5432/tee_swapper bun run db:push
# Start the development server
DATABASE_URL=postgres://tee_swapper:tee_swapper_dev@localhost:5432/tee_swapper bun run dev| Command | Description |
|---|---|
bun run dev |
Start development server with hot reload |
bun run start |
Start production server |
bun run worker:refund-intent |
Run external BTC refund intent polling worker |
bun run test |
Run all tests |
bun run test:db |
Alias for bun run test (compatibility command) |
bun run db:up |
Start PostgreSQL via Docker |
bun run db:down |
Stop PostgreSQL |
bun run db:push |
Push schema to database |
bun run db:generate |
Generate migrations |
bun run db:migrate |
Run migrations |
GET /health
POST /quote
{
"chainId": 1,
"buyToken": { "type": "erc20", "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" },
"sellAmount": "100000000"
}
POST /order
{
"chainId": 1,
"buyToken": { "type": "erc20", "address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" },
"recipientAddress": "0x...",
"refundAddress": "bc1q...",
"execution": { "type": "market" }
}
POST /order
{
"chainId": 1,
"buyToken": { "type": "erc20", "address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" },
"recipientAddress": "0x...",
"refundAddress": "bc1q...",
"execution": {
"type": "limit",
"price": {
"buyAmount": "2000000",
"sellAmount": "100000000"
}
}
}
GET /order/:id
POST /order/:id/cancel
{
"authorization": {
"deadline": 1760000000,
"signature": "0x..."
}
}
GET /order/refund/eligible?limit=25
GET /order/:id/refund/intent
POST /order/:id/refund/submit
{
"txHash": "0x...",
"executor": "0x..."
}
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | Required |
ETH_RPC_URL |
Ethereum RPC URL | https://eth.drpc.org |
BASE_RPC_URL |
Base RPC URL | https://base.drpc.org |
PORT |
Server port | 3000 |
RIFT_RFQ_BASE_URL |
RFQ API base URL for BTC refund flow | Required for BTC refund flow |
RIFT_OTC_BASE_URL |
OTC API base URL for BTC refund flow | Required for BTC refund flow |
RIFT_RFQ_API_KEY |
RFQ API key for BTC refund intent generation | Required for BTC refund intent |
SWAPPER_API_URL |
API URL used by refund worker | http://localhost:3000 |
REFUND_WORKER_PRIVATE_KEY |
EVM key used by refund worker to submit intent txs | Required for worker |
REFUND_INTENT_WORKER_POLL_MS |
Poll interval in ms for refund worker | 1800000 |
REFUND_INTENT_WORKER_BOOTSTRAP_POLL_MS |
How often the worker rehydrates missed refund jobs from swap state | REFUND_INTENT_WORKER_POLL_MS |
REFUND_INTENT_WORKER_BATCH_SIZE |
Max swaps processed per poll tick | 25 |
For production-style BTC refund execution as a separate process, use:
docker compose -f etc/compose.refund-worker.yml up -dNotes:
- This worker does not expose an HTTP port.
- By default it expects the main tee-swapper API container to be reachable at
http://cbbtc-swapper-server:3000on the external Docker networkswapper-network. - Override
SWAPPER_API_URLif you want the worker to target a different tee-swapper API endpoint.
For Railway, use Dockerfile.refund-worker instead of the main API Dockerfile.
# Run all tests
bun test
# Compatibility alias
bun run test:dbSee TODO.md for remaining implementation tasks.