discord bot using javascript+websocket – error code 4003 after sending heartbeat payload

so basically im trying to make a discord bot, pretty much from scratch or “writing a custom implementation”, as discord dev calls it. I’m using Websocket and node-js to make the whole thing, however I’m now stuck at the point that initiates the heartbeat with discords api, because the connection keeps terminating due to the error status code 4003 “Not Authenticated”.

This is what is logged when the connection closes:

Terminating Connection: 4003 Not authenticated. CloseEvent {Symbol(kTarget): WebSocket, Symbol(kType): ‘close’, Symbol(kCode): 4003, Symbol(kReason): ‘Not authenticated.’, Symbol(kWasClean): true}

And finally this is my code:
{ Thank you 🙂 }

import dotenv from "dotenv";
import Websocket from "ws";
import {fetchData} from "./index.js";

const version = "v=10";
const encoding = "encoding=json";
const opcode = {
    Dispatch:"0", 
    Heartbeat:"1", 
    Identify:"2", 
    Presence_Update:"3", 
    Voice_State_Update:"4", 
    Resume:"6", 
    Reconnect:"7", 
    Req_Guild_Members:"8", 
    Invalid_Session:"9", 
    Hello:"10", 
    Heartbeat_ACK:"11"}

fetchData("/gateway/bot", {method: "GET", redirect: "follow"}) // function imported from another js file, simply gets discords wss url
    .then((url) => {
        console.log(url);
        const newurl = url+`/?${version}&${encoding}`;
        const client = new Client(newurl);
    });

class Client {
    constructor(url) {
        this.url = url;
        this.client = new Websocket(url);
        this.identified = false
        this.client.onopen = (event) => {
            console.log("Connection Established! State:", this.client.readyState); 
        };
        this.client.onclose = (event) => {
            console.log("Terminating Connection:", event.code, event.reason, event)
        };
        this.client.addEventListener("message", (event) => {
            console.log("Message Received")
            this.handle_event(event)
        })

    }

    handle_event(event) {
        let data = this.parse(event.data);
        console.log(data);
        if(data.op == opcode.Hello || opcode.Heartbeat_ACK) {
            let interval = data.heartbeat_interval;
            let jitter = Math.random();
            let heartbeatInterval = interval * jitter;
            setTimeout(() => {
                console.log("Handled message event, data:", data, "interval:", heartbeatInterval)
                this.send_event(this.payloads(opcode.Heartbeat));
            }, heartbeatInterval
        )
        }
    }

    send_event(payload) {
        if(!this.identified) {
            this.client.send(this.payloads(opcode.Identify, {
                "token":process.env.DISCORD_TOKEN, 
                "intents":515, 
                "properties": {
                    "os":"windows", 
                    "browser":"chrome", 
                    "device":"chrome"}}
                ))
            console.log("identified with:", this.payloads(opcode.Identify, {
                "token":process.env.DISCORD_TOKEN, 
                "intents":515, 
                "properties": {
                    "os":"windows", 
                    "browser":"chrome", 
                    "device":"chrome"}}
                ))
            this.identified = true
        }
        if(this.identified) {
            console.log("sending payload:", payload)
            this.client.send(payload)
        }
    }

    parse(data) {
        let dataObject = {};
        JSON.parse(data, (key, value) => {
            dataObject[key] = value;
        });
        return dataObject;
    }

    payloads(op=null, d=null, s=null, t=null) {
        let payload = {
            "op": op,
            "d": d,
            "s": s,
            "t": t
        }
        return JSON.stringify(payload)
    }

}


I’ve tried sending the identify payload along with the heartbeat payload and even tried identifying before sending the heartbeat, but both return the same error.