1+ // api.js - Express API server for NGN/USD oracle
2+ const express = require ( 'express' ) ;
3+ const cors = require ( 'cors' ) ;
4+ require ( 'dotenv' ) . config ( ) ;
5+ const NGNUSDOracle = require ( './src/core/NGNUSDOracle' ) ;
6+
7+ const app = express ( ) ;
8+ const PORT = process . env . API_PORT || 3000 ;
9+
10+ // Middleware
11+ app . use ( cors ( ) ) ;
12+ app . use ( express . json ( ) ) ;
13+
14+ // Initialize oracle
15+ let oracle ;
16+ const initializeOracle = ( ) => {
17+ const privateKey = process . env . PRIVATE_KEY || '0x0000000000000000000000000000000000000000000000000000000000000001' ;
18+ oracle = new NGNUSDOracle ( privateKey ) ;
19+ console . log ( 'Oracle initialized for API server' ) ;
20+ } ;
21+
22+ // Initialize oracle on startup
23+ initializeOracle ( ) ;
24+
25+ // Health check endpoint
26+ app . get ( '/health' , ( req , res ) => {
27+ res . json ( {
28+ status : 'ok' ,
29+ timestamp : new Date ( ) . toISOString ( ) ,
30+ oracle : oracle ? 'initialized' : 'not initialized'
31+ } ) ;
32+ } ) ;
33+
34+ // Get current price
35+ app . get ( '/api/price' , async ( req , res ) => {
36+ try {
37+ const priceData = await oracle . getCurrentPrice ( ) ;
38+ res . json ( {
39+ success : true ,
40+ data : {
41+ usdToNgn : priceData . usdToNgn ,
42+ ngnToUsd : priceData . ngnToUsd ,
43+ formattedPrice : priceData . formattedPrice ,
44+ reversePrice : priceData . reversePrice ,
45+ decimals : priceData . decimals ,
46+ description : priceData . description ,
47+ timestamp : priceData . timestamp
48+ }
49+ } ) ;
50+ } catch ( error ) {
51+ console . error ( 'Error fetching price:' , error ) ;
52+ res . status ( 500 ) . json ( {
53+ success : false ,
54+ error : 'Failed to fetch price data' ,
55+ message : error . message
56+ } ) ;
57+ }
58+ } ) ;
59+
60+ // Get latest round data
61+ app . get ( '/api/round' , async ( req , res ) => {
62+ try {
63+ const roundData = await oracle . getLatestRoundData ( ) ;
64+ res . json ( {
65+ success : true ,
66+ data : {
67+ roundId : roundData . roundId ,
68+ usdToNgn : roundData . usdToNgn ,
69+ ngnToUsd : roundData . ngnToUsd ,
70+ formattedPrice : roundData . formattedPrice ,
71+ reversePrice : roundData . reversePrice ,
72+ updatedAt : roundData . updatedAt ,
73+ updatedAtFormatted : roundData . updatedAtFormatted ,
74+ answeredInRound : roundData . answeredInRound
75+ }
76+ } ) ;
77+ } catch ( error ) {
78+ console . error ( 'Error fetching round data:' , error ) ;
79+ res . status ( 500 ) . json ( {
80+ success : false ,
81+ error : 'Failed to fetch round data' ,
82+ message : error . message
83+ } ) ;
84+ }
85+ } ) ;
86+
87+ // Convert USD to NGN
88+ app . get ( '/api/convert/usd-to-ngn/:amount' , async ( req , res ) => {
89+ try {
90+ const amount = parseFloat ( req . params . amount ) ;
91+ if ( isNaN ( amount ) ) {
92+ return res . status ( 400 ) . json ( {
93+ success : false ,
94+ error : 'Invalid amount provided'
95+ } ) ;
96+ }
97+
98+ const priceData = await oracle . getCurrentPrice ( ) ;
99+ const ngnAmount = amount * priceData . usdToNgn ;
100+
101+ res . json ( {
102+ success : true ,
103+ data : {
104+ usdAmount : amount ,
105+ ngnAmount : ngnAmount ,
106+ rate : priceData . usdToNgn ,
107+ formattedResult : `${ amount } USD = ${ ngnAmount . toFixed ( 2 ) } NGN` ,
108+ timestamp : priceData . timestamp
109+ }
110+ } ) ;
111+ } catch ( error ) {
112+ console . error ( 'Error converting USD to NGN:' , error ) ;
113+ res . status ( 500 ) . json ( {
114+ success : false ,
115+ error : 'Failed to convert currency' ,
116+ message : error . message
117+ } ) ;
118+ }
119+ } ) ;
120+
121+ // Convert NGN to USD
122+ app . get ( '/api/convert/ngn-to-usd/:amount' , async ( req , res ) => {
123+ try {
124+ const amount = parseFloat ( req . params . amount ) ;
125+ if ( isNaN ( amount ) ) {
126+ return res . status ( 400 ) . json ( {
127+ success : false ,
128+ error : 'Invalid amount provided'
129+ } ) ;
130+ }
131+
132+ const priceData = await oracle . getCurrentPrice ( ) ;
133+ const usdAmount = amount * priceData . ngnToUsd ;
134+
135+ res . json ( {
136+ success : true ,
137+ data : {
138+ ngnAmount : amount ,
139+ usdAmount : usdAmount ,
140+ rate : priceData . ngnToUsd ,
141+ formattedResult : `${ amount } NGN = ${ usdAmount . toFixed ( 6 ) } USD` ,
142+ timestamp : priceData . timestamp
143+ }
144+ } ) ;
145+ } catch ( error ) {
146+ console . error ( 'Error converting NGN to USD:' , error ) ;
147+ res . status ( 500 ) . json ( {
148+ success : false ,
149+ error : 'Failed to convert currency' ,
150+ message : error . message
151+ } ) ;
152+ }
153+ } ) ;
154+
155+ // Get historical events
156+ app . get ( '/api/history' , async ( req , res ) => {
157+ try {
158+ const blocks = parseInt ( req . query . blocks ) || 50 ;
159+ const events = await oracle . queryHistoricalEvents ( blocks ) ;
160+
161+ res . json ( {
162+ success : true ,
163+ data : {
164+ events : events ,
165+ count : events . length ,
166+ blocksQueried : blocks
167+ }
168+ } ) ;
169+ } catch ( error ) {
170+ console . error ( 'Error fetching history:' , error ) ;
171+ res . status ( 500 ) . json ( {
172+ success : false ,
173+ error : 'Failed to fetch historical data' ,
174+ message : error . message
175+ } ) ;
176+ }
177+ } ) ;
178+
179+ // Start server
180+ app . listen ( PORT , ( ) => {
181+ console . log ( `\n🚀 NGN/USD Oracle API Server running on port ${ PORT } ` ) ;
182+ console . log ( `\n📍 Available endpoints:` ) ;
183+ console . log ( ` GET /health - Health check` ) ;
184+ console . log ( ` GET /api/price - Current price data` ) ;
185+ console . log ( ` GET /api/round - Latest round data` ) ;
186+ console . log ( ` GET /api/convert/usd-to-ngn/:amount - Convert USD to NGN` ) ;
187+ console . log ( ` GET /api/convert/ngn-to-usd/:amount - Convert NGN to USD` ) ;
188+ console . log ( ` GET /api/history?blocks=50 - Historical price events\n` ) ;
189+ } ) ;
190+
191+ // Graceful shutdown
192+ process . on ( 'SIGINT' , ( ) => {
193+ console . log ( '\nShutting down API server...' ) ;
194+ if ( oracle ) {
195+ oracle . stopMonitoring ( ) ;
196+ }
197+ process . exit ( 0 ) ;
198+ } ) ;
0 commit comments