PYTHON
from flask import Flask, request, jsonify
import requests
from web3 import Web3
app = Flask(__name__)
# Force JSON parsing for all requests
@app.before_request
def force_json():
if request.method == 'POST' and not request.is_json:
if 'application/json' not in request.content_type:
request.environ['CONTENT_TYPE'] = 'application/json'
MORALIS_API_KEY = "YOUR_API_KEY"
SECRET_KEY = None # will get the secret for the account
def get_moralis_secret():
global SECRET_KEY
if SECRET_KEY is None:
headers = {'accept': 'application/json', 'X-API-Key': MORALIS_API_KEY}
response = requests.get("https://api.moralis-streams.com/settings", headers=headers)
SECRET_KEY = response.json().get('secretKey')
return SECRET_KEY
def verify_Signature(req, secret):
provided_signature = req.headers.get("x-signature")
print("Provided signature:", provided_signature)
if not provided_signature:
raise TypeError("Signature not provided")
data = req.data+secret.encode()
signature = "0x" + Web3.keccak(text=data.decode()).hex()
print("Generated signature:", signature)
if provided_signature != signature:
raise ValueError("Invalid Signature")
@app.route('/webhook', methods=['POST'])
def webhook():
try:
# Verify signature using the exact documentation method
secret = get_moralis_secret()
verify_Signature(request, secret)
# Parse JSON after verification
webhook_data = request.get_json()
print("✅ Webhook verified")
print(f"Data: {webhook_data}")
return jsonify({"status": "success"}), 200
except (TypeError, ValueError) as e:
print(f"❌ Error: {e}")
return jsonify({"error": str(e)}), 400
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3000, debug=True)
JAVASCRIPT
const express = require('express');
const axios = require('axios');
const { Web3 } = require('web3');
const app = express();
const PORT = 3000;
// Middleware to parse JSON
app.use(express.json());
const MORALIS_API_KEY = "YOUR_API_KEY";
let SECRET_KEY = null; // will get the secret for the account
async function getMoralisSecret() {
if (SECRET_KEY === null) {
try {
const headers = {
'accept': 'application/json',
'X-API-Key': MORALIS_API_KEY
};
const response = await axios.get("https://api.moralis-streams.com/settings", { headers });
SECRET_KEY = response.data.secretKey;
} catch (error) {
throw new Error(`Failed to get Moralis secret: ${error.message}`);
}
}
return SECRET_KEY;
}
function verifySignature(req, secret) {
const providedSignature = req.headers['x-signature'];
console.log("Provided signature:", providedSignature);
if (!providedSignature) {
throw new Error("Signature not provided");
}
// Generate signature using JSON.stringify + secret
const web3 = new Web3();
const generatedSignature = web3.utils.sha3(JSON.stringify(req.body) + secret);
console.log("Generated signature:", generatedSignature);
if (generatedSignature !== providedSignature) {
throw new Error("Invalid Signature");
}
}
// Custom error class for ValueError
class ValueError extends Error {
constructor(message) {
super(message);
this.name = 'ValueError';
}
}
app.post('/webhook', async (req, res) => {
try {
// Verify signature using the exact documentation method
const secret = await getMoralisSecret();
verifySignature(req, secret);
// Webhook data is already parsed by express.json()
const webhookData = req.body;
console.log("✅ Webhook verified");
console.log(`Data: ${JSON.stringify(webhookData)}`);
res.status(200).json({ status: "success" });
} catch (error) {
console.log(`❌ Error: ${error.message}`);
res.status(400).json({ error: error.message });
}
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on http://0.0.0.0:${PORT}`);
});
module.exports = app;