Skip to content

Commit 75a444b

Browse files
authored
Merge pull request #1 from wrappedcbdc/develop
init files ngn/usd rate from chainlink oracle on base
2 parents cfb8d04 + 0f8ae5a commit 75a444b

File tree

8 files changed

+3485
-0
lines changed

8 files changed

+3485
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.env
2+
3+
node_modules/

api.js

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
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+
});

oracle.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Import required dependencies
2+
const { ethers } = require('ethers');
3+
require('dotenv').config();
4+
const NGNUSDOracle = require('./src/core/NGNUSDOracle');
5+
6+
// Main execution
7+
async function main() {
8+
let oracle;
9+
10+
try {
11+
// For read-only operations, you can use a dummy private key
12+
const privateKey = process.env.PRIVATE_KEY || '0x0000000000000000000000000000000000000000000000000000000000000001';
13+
14+
// Initialize oracle
15+
oracle = new NGNUSDOracle(privateKey);
16+
17+
// Get oracle description
18+
const description = await oracle.getDescription();
19+
console.log(`\n📌 Connected to: ${description}`);
20+
console.log(`📍 Contract: ${process.env.ORACLE_CONTRACT_ADDRESS}\n`);
21+
22+
// Get current price
23+
console.log('Fetching current NGN/USD rate...');
24+
const currentPrice = await oracle.getCurrentPrice();
25+
console.log('Current Price Data:', {
26+
usdToNgn: currentPrice.usdToNgn.toFixed(2),
27+
ngnToUsd: currentPrice.ngnToUsd.toFixed(6),
28+
formattedPrice: currentPrice.formattedPrice,
29+
reversePrice: currentPrice.reversePrice
30+
});
31+
32+
// Get latest round data
33+
try {
34+
const roundData = await oracle.getLatestRoundData();
35+
console.log('\nLatest Round Data:', {
36+
roundId: roundData.roundId,
37+
formattedPrice: roundData.formattedPrice,
38+
reversePrice: roundData.reversePrice,
39+
updatedAt: roundData.updatedAtFormatted
40+
});
41+
} catch (error) {
42+
console.error('Could not fetch round data:', error.message);
43+
}
44+
45+
// Setup event listeners
46+
oracle.setupEventListeners();
47+
48+
// Query recent events with reduced block range
49+
const recentEvents = await oracle.queryHistoricalEvents(50); // Reduced from 500 to 50
50+
if (recentEvents.length > 0) {
51+
console.log('\nRecent Price Updates:');
52+
recentEvents.slice(0, 3).forEach((event, index) => {
53+
console.log(`${index + 1}. ${event.formattedPrice} (${event.reversePrice}) at ${event.updatedAtFormatted}`);
54+
});
55+
}
56+
57+
// Start monitoring with longer interval
58+
await oracle.monitorPrice(120000); // Check every 2 minutes instead of 30 seconds
59+
60+
// Keep the script running
61+
console.log('\n✅ Oracle monitor is running. Press Ctrl+C to exit.');
62+
63+
} catch (error) {
64+
console.error('Main execution error:', error);
65+
process.exit(1);
66+
}
67+
}
68+
69+
// Run the script
70+
main();
71+
72+
// Handle graceful shutdown
73+
process.on('SIGINT', () => {
74+
console.log('\n\nShutting down oracle monitor...');
75+
if (global.oracle) {
76+
global.oracle.stopMonitoring();
77+
}
78+
process.exit(0);
79+
});

0 commit comments

Comments
 (0)