Authentication Failed Trying to Connect with Coinbase Websocket

Hello below is my code, when I try to connect to the websocket, I get the authentication error, please what am I doing wrong?



class CoinbaseWebSocket {

    constructor() {
  
        this.API_KEY = '';
        this.SIGNING_KEY = '';
        this.algorithm = 'ES256';
        this.CHANNEL_NAMES = {
            level2: 'level2',
            user: 'user',
            tickers: 'ticker',
            ticker_batch: 'ticker_batch',
            status: 'status',
            market_trades: 'market_trades',
            candles: 'candles',
        };
        this.WS_API_URL = 'wss://advanced-trade-ws.coinbase.com';
        this.connections = [];
        this.sentUnsub = false;
    }

    timestampAndSign(message, channel, products = []) {
        console.log('Zombies');
        console.log(this.API_KEY);
        const timestamp = Math.floor(Date.now() / 1000).toString();
        const jwt = sign(
            {
                aud: ['public_websocket_api'],
                iss: 'coinbase-cloud',
                nbf: Math.floor(Date.now() / 1000),
                exp: Math.floor(Date.now() / 1000) + 120,
                sub: this.API_KEY,
            },
            this.SIGNING_KEY,
            {
                algorithm: this.algorithm,
                header: {
                    kid: this.API_KEY,
                    nonce: crypto.randomBytes(16).toString('hex'),
                },
            }
        );

        console.log('main');
        console.log({ jwt: jwt, timestamp: timestamp });

        return { ...message, jwt: jwt, timestamp: timestamp };
    }

    async subscribeToProducts(products, channelName, ws) {
        console.log(`------ Trying to subscribe -------`);
        console.log(channelName);
        console.log(products);
        return new Promise((resolve, reject) => {
            const message = {
                type: 'subscribe',
                channel: channelName,
                product_ids: products,
            };
            const subscribeMsg = this.timestampAndSign(message, channelName, products);
            ws.send(JSON.stringify(subscribeMsg), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    async unsubscribeToProducts(products, channelName, ws) {
        return new Promise((resolve, reject) => {
            const message = {
                type: 'unsubscribe',
                channel: channelName,
                product_ids: products,
            };
            const subscribeMsg = this.timestampAndSign(message, channelName, products);
            ws.send(JSON.stringify(subscribeMsg), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    onMessage(data) {
        const parsedData = JSON.parse(data);
        fs.appendFile('Output1.txt', data, (err) => {
            if (err) throw err;
        });
    }

    async setupConnection() {
        const ws = new WebSocket(this.WS_API_URL);

        ws.on('message', async (data) => {
            const date2 = new Date(new Date().toUTCString());
            const diffTime = Math.abs(date2 - this.date1);
            if (diffTime > 5000 && !this.sentUnsub) {
                await this.unsubscribeToProducts(['BTC-USD'], this.CHANNEL_NAMES.level2, ws);
                this.sentUnsub = true;
            }

            const parsedData = JSON.parse(data);
            console.log({parsedData});
            fs.appendFile('Output1.txt', data, (err) => {
                if (err) throw err;
            });
        });

        ws.on('open', async () => {
            const products = ['BTC-USD'];
            await this.subscribeToProducts(products, this.CHANNEL_NAMES.level2, ws);
        });

        this.connections.push(ws);
    }

    startConnections() {
        this.date1 = new Date(new Date().toUTCString());
        for (let i = 0; i < 1; i++) {
            this.setupConnection();
        }
    }
}

module.exports = CoinbaseWebSocket

Does your API key works with REST API?

Maybe newlines are causing problems? From:

Replace key name and key secret with your key name and private key. key secret is a multi-line key and newlines must be preserved to properly parse the key. Do this on one line with \n escaped newlines, or with a multi-line string.

Hi thanks for your response, I figured out this a while back the existing issue I have now is that the onMessage is not returning anything, here’s the code. Please am I doing anything wrong?

let WS_API_URL = 'wss://advanced-trade-ws.coinbase.com';
let ws = new WebSocket(WS_API_URL);


class CoinbaseWebSocket {

    timestampAndSign() {

        let API_KEY = '';
        let SIGNING_KEY = '';

        const timestamp = Math.floor(Date.now() / 1000).toString();
        const jwt = sign(
            {
                aud: ['public_websocket_api'],
                iss: 'coinbase-cloud',
                nbf: Math.floor(Date.now() / 1000),
                exp: Math.floor(Date.now() / 1000) + 120,
                sub: API_KEY,
            },
            SIGNING_KEY,
            {
                algorithm: 'ES256',
                header: {
                    kid: API_KEY,
                    nonce: crypto.randomBytes(16).toString('hex'),
                },
            }
        );

       
        return { jwt: jwt, timestamp: timestamp };
    }

    async subscribeToProducts() {

        console.log(`------ Trying to subscribe -------`);

        return new Promise((resolve, reject) => {

            const subscribeMsg = this.timestampAndSign();
            const message = {
                type: 'subscribe',
                channel: "level2",
                // product_ids: products,
                product_ids: [
                    "BTC-USD",
                    "ETH-EUR"
                ],
                "jwt": subscribeMsg.jwt,
                "timestamp": subscribeMsg.timestamp
            };

            console.log(`Finished Product`);
            console.log(message);

            ws.send(JSON.stringify(message), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    async unsubscribeToProducts(products, channelName) {
        return new Promise((resolve, reject) => {
            const message = {
                type: 'unsubscribe',
                channel: channelName,
                product_ids: products,
            };
            const subscribeMsg = this.timestampAndSign(message, channelName, products);
            ws.send(JSON.stringify(subscribeMsg), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    onMessage(data) {
        const parsedData = JSON.parse(data);
        console.log({parsedData});
        fs.appendFile('Output1.txt', data, (err) => {
            if (err) throw err;
        });
    }

    async setupConnection() {
        const ws = new WebSocket(WS_API_URL);

        ws.on('message', async (data) => {
            const date2 = new Date(new Date().toUTCString());
            const diffTime = Math.abs(date2 - this.date1);
            if (diffTime > 5000 && !this.sentUnsub) {
                console.log('trying to unsubscribe');
                await this.unsubscribeToProducts(['BTC-USD'], 'level2', ws);
                this.sentUnsub = true;
            }

            console.log('Resources -----');
            const parsedData = JSON.parse(data);
            console.log({ parsedData });
            fs.appendFile('Output1.txt', data, (err) => {
                if (err) throw err;
            });
        });

        ws.on('open', async () => {
            const products = ['BTC-USD'];
            await this.subscribeToProducts(products, 'level2', ws);
        });
    }

    startConnections() {
        this.date1 = new Date(new Date().toUTCString());
        for (let i = 0; i < 1; i++) {
            this.setupConnection();
        }
    }
}

module.exports = CoinbaseWebSocket

From code you posted you are not using CoinbaseWebSocket! Should not you have something like:

(new CoinbaseWebSocket()).startConnections();

I have a controller than calls the Coinbase class and StartConnection Function which connects well without any errors like I used to.

Why do you have this above your class when you are creating ws instances inside setupConnection? Maybe it is causing your new problem?

Add more debug messages to help you find place where things stops working. For example is your open callback called? Also you are not using onMessage function in your code…

Did this and it brought me right back to the authentication problem again and yes, I have verified that the keys connects with the Rest API, here is the updated code snippet.

 constructor() {
        this.WS_API_URL = 'wss://advanced-trade-ws.coinbase.com';
    }

    timestampAndSign() {

        let API_KEY = '';
        let SIGNING_KEY = ''

        const timestamp = Math.floor(Date.now() / 1000).toString();
        const jwt = sign(
            {
                aud: ['public_websocket_api'],
                iss: 'coinbase-cloud',
                nbf: Math.floor(Date.now() / 1000),
                exp: Math.floor(Date.now() / 1000) + 120,
                sub: API_KEY,
            },
            SIGNING_KEY,
            {
                algorithm: 'ES256',
                header: {
                    kid: API_KEY,
                    nonce: crypto.randomBytes(16).toString('hex'),
                },
            }
        );

       
        return { jwt: jwt, timestamp: timestamp };
    }

    async subscribeToProducts(ws) {

        console.log(`------ Trying to subscribe -------`);

        return new Promise((resolve, reject) => {

            const subscribeMsg = this.timestampAndSign();
            const message = {
                type: 'subscribe',
                channel: "level2",
                // product_ids: products,
                product_ids: [
                    "BTC-USD",
                    "ETH-EUR"
                ],
                "jwt": subscribeMsg.jwt,
                "timestamp": subscribeMsg.timestamp
            };

            console.log(`Finished Product`);
            console.log(message);

            ws.send(JSON.stringify(message), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    async unsubscribeToProducts(products, channelName) {
        return new Promise((resolve, reject) => {
            const message = {
                type: 'unsubscribe',
                channel: channelName,
                product_ids: products,
            };
            const subscribeMsg = this.timestampAndSign(message, channelName, products);
            ws.send(JSON.stringify(subscribeMsg), (error) => {
                if (error) reject(error);
                else resolve();
            });
        });
    }

    onMessage(data) {
        const parsedData = JSON.parse(data);
        console.log({parsedData});
        fs.appendFile('Output1.txt', data, (err) => {
            if (err) throw err;
        });
    }

    async setupConnection() {

        const ws = new WebSocket(this.WS_API_URL);

        ws.on('message', async (data) => {
            const date2 = new Date(new Date().toUTCString());
            const diffTime = Math.abs(date2 - this.date1);
            if (diffTime > 5000 && !this.sentUnsub) {
                console.log('Unsubscriber');
                await this.unsubscribeToProducts(["BTC-USD","ETH-EUR"], 'level2', ws);
                this.sentUnsub = true;
            }

            const parsedData = JSON.parse(data);
            console.log({ parsedData });
            fs.appendFile('Output1.txt', data, (err) => {
                if (err) throw err;
            });
        });

        ws.on('open', async () => {
            const products = ["BTC-USD","ETH-EUR"];
            await this.subscribeToProducts(ws);
        });

        // connections.push(ws);

        // console.log({connections});
    }

    startConnections() {
        this.date1 = new Date(new Date().toUTCString());
        for (let i = 0; i < 1; i++) {
            this.setupConnection();
        }
    }
}

module.exports = CoinbaseWebSocket

Can you show how your generated subscribe message looks? Remove generated token from it before posting.

Thank you so much, I found the issue it was my Ip that changed as a result of my wifi. one last question please how do I determine the frequency on how the price pop in, like come once every 60 seconds instead of every price change

You can not as far as I know! For every 60 seconds you can probably just use REST API.