-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver-example.js
More file actions
136 lines (113 loc) · 4.21 KB
/
Copy pathserver-example.js
File metadata and controls
136 lines (113 loc) · 4.21 KB
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
// server-example.js
// Example server implementation for Soulbound Auth
const express = require('express');
const ethers = require('ethers');
const jwt = require('jsonwebtoken');
const sqlite3 = require('sqlite3');
const app = express();
app.use(express.json());
// Configuration
const CONFIG = {
SBT_CONTRACT: process.env.SBT_CONTRACT || '0x...',
RPC_URL: process.env.RPC_URL || 'http://localhost:8545',
JWT_SECRET: process.env.JWT_SECRET || 'change-this-secret',
PORT: process.env.PORT || 3000
};
// Initialize database (no address storage)
const db = new sqlite3.Database(':memory:');
db.run(`
CREATE TABLE accounts (
account_id TEXT PRIMARY KEY,
created_at INTEGER,
eula_hash TEXT,
role TEXT DEFAULT 'user'
)
`);
// Minimal Contract ABI
const SBT_ABI = [
"function getAccountInfo(address) view returns (bool, bytes32, uint256)"
];
// Initialize provider and contract
const provider = new ethers.providers.JsonRpcProvider(CONFIG.RPC_URL);
const sbtContract = new ethers.Contract(CONFIG.SBT_CONTRACT, SBT_ABI, provider);
// POST /auth - Authenticate user
app.post('/auth', async (req, res) => {
try {
const { address, signature, message } = req.body;
// Verify signature
const recovered = ethers.utils.verifyMessage(message, signature);
if (recovered.toLowerCase() !== address.toLowerCase()) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Check SBT on-chain
const [hasSBT, accountId] = await sbtContract.getAccountInfo(address);
// Generate JWT (no address stored)
const token = jwt.sign(
{
hasSBT,
accountId: hasSBT ? accountId : null,
timestamp: Date.now()
},
CONFIG.JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({ token, hasSBT, accountId: hasSBT ? accountId : null });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// POST /confirm-mint - Confirm SBT minting
app.post('/confirm-mint', async (req, res) => {
try {
const { address, signature, eulaHash, txHash } = req.body;
// Verify signature
const message = `Confirm SBT mint: ${txHash}`;
const recovered = ethers.utils.verifyMessage(message, signature);
if (recovered.toLowerCase() !== address.toLowerCase()) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Get account ID from chain
const [hasSBT, accountId] = await sbtContract.getAccountInfo(address);
if (!hasSBT) {
return res.status(400).json({ error: 'SBT not found' });
}
// Store account (NOT address)
db.run(
`INSERT OR IGNORE INTO accounts (account_id, created_at, eula_hash)
VALUES (?, ?, ?)`,
[accountId, Date.now(), eulaHash]
);
// Return new JWT with account ID
const token = jwt.sign(
{ hasSBT: true, accountId, timestamp: Date.now() },
CONFIG.JWT_SECRET,
{ expiresIn: '24h' }
);
res.json({ token, accountId });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// GET /account - Get account info (requires JWT)
app.get('/account', (req, res) => {
try {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });
const decoded = jwt.verify(token, CONFIG.JWT_SECRET);
if (!decoded.hasSBT) return res.status(403).json({ error: 'No SBT' });
db.get(
`SELECT * FROM accounts WHERE account_id = ?`,
[decoded.accountId],
(err, row) => {
if (err || !row) return res.status(404).json({ error: 'Not found' });
res.json(row);
}
);
} catch (error) {
res.status(401).json({ error: 'Invalid token' });
}
});
app.listen(CONFIG.PORT, () => {
console.log(`Server running on port ${CONFIG.PORT}`);
console.log('No addresses will be stored');
});