2 changed files with 102 additions and 0 deletions
@ -0,0 +1,13 @@ |
|||||||
|
const express = require('express'); |
||||||
|
const oracleRoutes = require('./routes'); |
||||||
|
|
||||||
|
const app = express(); |
||||||
|
const HOST = process.env.ORACLE_HOST || '127.0.0.1'; |
||||||
|
const PORT = Number(process.env.ORACLE_PORT || 3210); |
||||||
|
|
||||||
|
app.use(express.json()); |
||||||
|
app.use('/api', oracleRoutes); |
||||||
|
|
||||||
|
app.listen(PORT, HOST, () => { |
||||||
|
console.log(`OTB Oracle test server listening on http://${HOST}:${PORT}/api`); |
||||||
|
}); |
||||||
@ -0,0 +1,89 @@ |
|||||||
|
const express = require('express'); |
||||||
|
const { |
||||||
|
listAssets, |
||||||
|
getPrices, |
||||||
|
buildQuote, |
||||||
|
getStatus |
||||||
|
} = require('./price_engine'); |
||||||
|
|
||||||
|
const router = express.Router(); |
||||||
|
|
||||||
|
function sendError(res, status, message, extra = {}) { |
||||||
|
return res.status(status).json({ |
||||||
|
ok: false, |
||||||
|
error: message, |
||||||
|
...extra |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
router.get('/health', (req, res) => { |
||||||
|
try { |
||||||
|
return res.json({ |
||||||
|
ok: true, |
||||||
|
service: 'otb-oracle', |
||||||
|
version: '0.1.0', |
||||||
|
time_utc: new Date().toISOString(), |
||||||
|
status: 'healthy' |
||||||
|
}); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 500, 'health_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
router.get('/assets', (req, res) => { |
||||||
|
try { |
||||||
|
return res.json(listAssets()); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 500, 'assets_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
router.get('/prices', (req, res) => { |
||||||
|
try { |
||||||
|
return res.json(getPrices()); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 500, 'prices_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
router.get('/price/:pairKey', (req, res) => { |
||||||
|
try { |
||||||
|
const pairKey = String(req.params.pairKey || '').trim().toUpperCase(); |
||||||
|
const prices = getPrices(); |
||||||
|
const asset = prices.assets?.[pairKey]; |
||||||
|
|
||||||
|
if (!asset) { |
||||||
|
return sendError(res, 404, 'asset_not_found', { pair_key: pairKey }); |
||||||
|
} |
||||||
|
|
||||||
|
return res.json(asset); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 500, 'price_lookup_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
router.get('/quote', (req, res) => { |
||||||
|
try { |
||||||
|
const fiat = req.query.fiat || 'CAD'; |
||||||
|
const amount = req.query.amount; |
||||||
|
|
||||||
|
if (amount === undefined || amount === null || amount === '') { |
||||||
|
return sendError(res, 400, 'missing_amount'); |
||||||
|
} |
||||||
|
|
||||||
|
const quote = buildQuote({ fiat, amount }); |
||||||
|
return res.json(quote); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 400, 'quote_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
router.get('/status', (req, res) => { |
||||||
|
try { |
||||||
|
return res.json(getStatus()); |
||||||
|
} catch (err) { |
||||||
|
return sendError(res, 500, 'status_failed', { detail: err.message }); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
module.exports = router; |
||||||
Loading…
Reference in new issue