Verify stream payload request using account secret

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;