Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions packages/public-api/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,3 @@ export const DEFAULT_AFFILIATE_BPS = '60'
// API server config
export const API_PORT = parseInt(process.env.PORT || '3001', 10)
export const API_HOST = process.env.HOST || '0.0.0.0'

// Static API keys for testing (in production these would come from a database)
export const STATIC_API_KEYS: Record<string, { name: string; feeSharePercentage: number }> = {
'test-api-key-123': { name: 'Test Partner', feeSharePercentage: 50 },
}
12 changes: 0 additions & 12 deletions packages/public-api/src/docs/openapi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ export const registry = new OpenAPIRegistry()
// We should probably define the response schemas with Zod too, but for now we'll do best effort with the request schemas
// and basic response structures.

// Security Schemes
registry.registerComponent('securitySchemes', 'apiKeyAuth', {
type: 'apiKey',
in: 'header',
name: 'X-API-Key',
})

// --- Definitions ---

// Asset
Expand Down Expand Up @@ -305,7 +298,6 @@ registry.registerPath({
description:
'Get informative swap rates from all available swappers. This does not create a transaction.',
tags: ['Swaps'],
security: [{ apiKeyAuth: [] }],
request: {
query: RatesRequestSchema,
},
Expand All @@ -332,7 +324,6 @@ registry.registerPath({
description:
'Get an executable quote for a swap, including transaction data. Requires a specific swapper name.',
tags: ['Swaps'],
security: [{ apiKeyAuth: [] }],
request: {
body: {
content: {
Expand Down Expand Up @@ -405,9 +396,6 @@ POST /v1/swap/quote
### 5. Execute the Swap
Use the returned \`transactionData\` to build and sign a transaction with the user's wallet, then broadcast it to the network.

## Authentication
Include your API key in the \`X-API-Key\` header for all swap endpoints.

## Asset IDs
Assets use CAIP-19 format: \`{chainId}/{assetNamespace}:{assetReference}\`
- Native ETH: \`eip155:1/slip44:60\`
Expand Down
27 changes: 11 additions & 16 deletions packages/public-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import express from 'express'

import { initAssets } from './assets'
import { API_HOST, API_PORT } from './config'
import { apiKeyAuth, optionalApiKeyAuth } from './middleware/auth'
import { getAssetById, getAssetCount, getAssets } from './routes/assets'
import { getChainCount, getChains } from './routes/chains'
import { docsRouter } from './routes/docs'
Expand Down Expand Up @@ -38,26 +37,26 @@ app.get('/', (_req, res) => {
})
})

// Health check (no auth required)
// Health check
app.get('/health', (_req, res) => {
res.json({ status: 'ok', timestamp: Date.now() })
})

// API v1 routes
const v1Router = express.Router()

// Swap endpoints (require API key)
v1Router.get('/swap/rates', apiKeyAuth, getRates)
v1Router.post('/swap/quote', apiKeyAuth, getQuote)
// Swap endpoints
v1Router.get('/swap/rates', getRates)
v1Router.post('/swap/quote', getQuote)

// Chain endpoints (optional auth)
v1Router.get('/chains', optionalApiKeyAuth, getChains)
v1Router.get('/chains/count', optionalApiKeyAuth, getChainCount)
// Chain endpoints
v1Router.get('/chains', getChains)
v1Router.get('/chains/count', getChainCount)

// Asset endpoints (optional auth)
v1Router.get('/assets', optionalApiKeyAuth, getAssets)
v1Router.get('/assets/count', optionalApiKeyAuth, getAssetCount)
v1Router.get('/assets/:assetId(*)', optionalApiKeyAuth, getAssetById)
// Asset endpoints
v1Router.get('/assets', getAssets)
v1Router.get('/assets/count', getAssetCount)
v1Router.get('/assets/:assetId(*)', getAssetById)

app.use('/v1', v1Router)
app.use('/docs', docsRouter)
Expand Down Expand Up @@ -90,10 +89,6 @@ Available endpoints:
GET /v1/assets - List supported assets
GET /v1/assets/count - Get asset count
GET /v1/assets/:assetId - Get single asset by ID

Authentication:
Include 'X-API-Key' header with your API key for /v1/swap/* endpoints.
Test API key: test-api-key-123
`)
})
}
Expand Down
83 changes: 0 additions & 83 deletions packages/public-api/src/middleware/auth.ts

This file was deleted.

6 changes: 0 additions & 6 deletions packages/public-api/src/routes/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ router.use(
hideDownloadButton: true,
darkMode: true,
defaultOpenAllTags: true,
authentication: {
preferredSecurityScheme: 'apiKeyAuth',
apiKey: {
token: 'test-api-key-123',
},
},
customCss: `
.sidebar { --theme-color-1: #383838; }
`,
Expand Down
48 changes: 5 additions & 43 deletions packages/public-api/src/server-standalone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,53 +7,25 @@
*/

import cors from 'cors'
import crypto from 'crypto'
import express from 'express'
import { v4 as uuidv4 } from 'uuid'

const API_PORT = parseInt(process.env.PORT || '3001', 10)
const API_HOST = process.env.HOST || '0.0.0.0'

// Static API keys for testing
const STATIC_API_KEYS: Record<string, { name: string; feeSharePercentage: number }> = {
'test-api-key-123': { name: 'Test Partner', feeSharePercentage: 50 },
}

const app = express()

// Middleware
app.use(cors())
app.use(express.json())

// API key auth middleware
const apiKeyAuth = (req: express.Request, res: express.Response, next: express.NextFunction) => {
const apiKey = req.header('X-API-Key')

if (!apiKey) {
return res.status(401).json({ error: 'API key required', code: 'MISSING_API_KEY' })
}

const partnerInfo = STATIC_API_KEYS[apiKey]
if (!partnerInfo) {
return res.status(401).json({ error: 'Invalid API key', code: 'INVALID_API_KEY' })
}

;(req as any).partner = {
id: crypto.createHash('sha256').update(apiKey).digest('hex').substring(0, 16),
name: partnerInfo.name,
feeSharePercentage: partnerInfo.feeSharePercentage,
}

next()
}

// Health check
app.get('/health', (_req, res) => {
res.json({ status: 'ok', timestamp: Date.now() })
})

// Mock rates endpoint
app.get('/v1/swap/rates', apiKeyAuth, (req, res) => {
app.get('/v1/swap/rates', (req, res) => {
const { sellAssetId, buyAssetId, sellAmountCryptoBaseUnit } = req.query

if (!sellAssetId || !buyAssetId || !sellAmountCryptoBaseUnit) {
Expand Down Expand Up @@ -108,7 +80,7 @@ app.get('/v1/swap/rates', apiKeyAuth, (req, res) => {
})

// Mock quote endpoint
app.post('/v1/swap/quote', apiKeyAuth, (req, res) => {
app.post('/v1/swap/quote', (req, res) => {
const { sellAssetId, buyAssetId, sellAmountCryptoBaseUnit, receiveAddress, swapperName } =
req.body

Expand Down Expand Up @@ -209,34 +181,24 @@ app.use((_req, res) => {
// Start server
app.listen(API_PORT, API_HOST, () => {
console.log(`
╔══════════════════════════════════════════════════════════════════╗
║ ShapeShift Public Swap API ║
║ (Mock/Test Server) ║
╚══════════════════════════════════════════════════════════════════╝

Server running at http://${API_HOST}:${API_PORT}

Endpoints:
GET /health - Health check (no auth)
GET /health - Health check
GET /v1/swap/rates - Get swap rates from all swappers
POST /v1/swap/quote - Get executable quote with tx data
GET /v1/assets - List supported assets

Authentication:
Include 'X-API-Key' header for /v1/swap/* endpoints
Test key: test-api-key-123

Example requests:

# Health check
curl http://localhost:${API_PORT}/health

# Get rates
curl -H "X-API-Key: test-api-key-123" \\
"http://localhost:${API_PORT}/v1/swap/rates?sellAssetId=eip155:1/slip44:60&buyAssetId=eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&sellAmountCryptoBaseUnit=1000000000000000000"
curl "http://localhost:${API_PORT}/v1/swap/rates?sellAssetId=eip155:1/slip44:60&buyAssetId=eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48&sellAmountCryptoBaseUnit=1000000000000000000"

# Get quote
curl -X POST -H "X-API-Key: test-api-key-123" -H "Content-Type: application/json" \\
curl -X POST -H "Content-Type: application/json" \\
-d '{"sellAssetId":"eip155:1/slip44:60","buyAssetId":"eip155:1/erc20:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48","sellAmountCryptoBaseUnit":"1000000000000000000","receiveAddress":"0x742d35Cc6634C0532925a3b844Bc9e7595f4EdC3","swapperName":"THORChain"}' \\
http://localhost:${API_PORT}/v1/swap/quote

Expand Down
21 changes: 0 additions & 21 deletions packages/public-api/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,6 @@ export type {
UtxoTransactionData,
}

export type PartnerConfig = {
id: string
apiKeyHash: string
name: string
feeSharePercentage: number
status: 'active' | 'suspended' | 'pending'
rateLimit: {
requestsPerMinute: number
requestsPerDay: number
}
createdAt: Date
}

export type RatesRequest = {
sellAssetId: AssetId
buyAssetId: AssetId
Expand Down Expand Up @@ -176,11 +163,3 @@ export type ErrorResponse = {
code?: string
details?: unknown
}

declare global {
namespace Express {
interface Request {
partner?: PartnerConfig
}
}
}
Loading
Loading