-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathserver.js
169 lines (135 loc) · 5.21 KB
/
server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
const express = require('express');
const { Keypair, Connection, PublicKey, clusterApiUrl, SystemProgram, Transaction } = require('@solana/web3.js');
const path = require('path');
const fs = require('fs');
const bcrypt = require('bcrypt');
const jwt = require('jsonwebtoken');
const app = express();
const PORT = 3000;
const JWT_SECRET = 'your_jwt_secret_key'; // Replace with a secure secret in production
const WALLET_DB_FILE = path.join(__dirname, 'wallets.json');
const USERS_DB_FILE = path.join(__dirname, 'users.json');
// Solana connection
const connection = new Connection(clusterApiUrl('mainnet-beta'), 'confirmed');
// Load wallets and users from files
let userWallets = fs.existsSync(WALLET_DB_FILE)
? JSON.parse(fs.readFileSync(WALLET_DB_FILE, 'utf8'))
: {};
let users = fs.existsSync(USERS_DB_FILE)
? JSON.parse(fs.readFileSync(USERS_DB_FILE, 'utf8'))
: {};
// Save wallets to file
function saveWalletsToFile() {
fs.writeFileSync(WALLET_DB_FILE, JSON.stringify(userWallets, null, 2));
}
// Save users to file
function saveUsersToFile() {
fs.writeFileSync(USERS_DB_FILE, JSON.stringify(users, null, 2));
}
// Middleware
app.use(express.json());
app.use(express.static(path.join(__dirname, 'frontend')));
// Authentication middleware
function authenticateToken(req, res, next) {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'Unauthorized' });
jwt.verify(token, JWT_SECRET, (err, user) => {
if (err) return res.status(403).json({ error: 'Invalid token' });
req.user = user;
next();
});
}
// User registration
app.post('/register', async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ error: 'Username and password are required.' });
}
if (users[username]) {
return res.status(400).json({ error: 'Username already exists.' });
}
const hashedPassword = await bcrypt.hash(password, 10);
// Create new user and wallet
users[username] = { username, password: hashedPassword };
const keypair = Keypair.generate();
userWallets[username] = {
publicKey: keypair.publicKey.toString(),
secretKey: Array.from(keypair.secretKey),
balance: 0, // Initial balance
};
saveUsersToFile();
saveWalletsToFile();
res.json({ message: 'Registration successful!' });
});
// User login
app.post('/login', async (req, res) => {
const { username, password } = req.body;
if (!username || !password) {
return res.status(400).json({ error: 'Username and password are required.' });
}
const user = users[username];
if (!user) {
return res.status(400).json({ error: 'Invalid username or password.' });
}
const passwordMatch = await bcrypt.compare(password, user.password);
if (!passwordMatch) {
return res.status(400).json({ error: 'Invalid username or password.' });
}
const token = jwt.sign({ username }, JWT_SECRET, { expiresIn: '1h' });
res.json({ message: 'Login successful!', token });
});
// Get wallet information
app.get('/wallet', authenticateToken, (req, res) => {
const { username } = req.user;
const wallet = userWallets[username];
if (!wallet) {
return res.status(404).json({ error: 'Wallet not found.' });
}
res.json({ publicKey: wallet.publicKey });
});
// Get wallet balance
app.get('/balance', authenticateToken, async (req, res) => {
const { username } = req.user;
const wallet = userWallets[username];
const publicKey = new PublicKey(wallet.publicKey);
try {
const balance = await connection.getBalance(publicKey);
res.json({ balance: balance / 1e9 });
} catch (error) {
res.status(500).json({ error: 'Failed to fetch balance.' });
}
});
// Withdraw SOL
app.post('/withdraw', authenticateToken, async (req, res) => {
const { username } = req.user;
const { recipient, amount } = req.body;
const wallet = userWallets[username];
if (!wallet || wallet.balance < amount) {
return res.status(400).json({ error: 'Insufficient balance.' });
}
const senderKeypair = Keypair.fromSecretKey(Uint8Array.from(wallet.secretKey));
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: senderKeypair.publicKey,
toPubkey: new PublicKey(recipient),
lamports: amount * 1e9,
})
);
try {
const signature = await connection.sendTransaction(transaction, [senderKeypair]);
await connection.confirmTransaction(signature);
wallet.balance -= amount;
saveWalletsToFile();
res.json({ message: 'Withdrawal successful!', signature });
} catch (error) {
res.status(500).json({ error: 'Failed to process withdrawal.' });
}
});
// Serve the frontend
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'frontend', 'index.html'));
});
// Start server
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});