How to send a message in WebSockets 🔌 on the Internet Computer

Ok when U publish on ic-websocket-js on npm I will use it then I really wish to keep trying but I can’t afford this. However, thank you so much for your help and for the websocket package really great job.

1 Like

Hi @AliSci , Can you please try installing those packages
npm install crypto and npm install crypto-browserify

And then add this to you webpack.config:

crypto: require.resolve("crypto-browserify"),, under fallback.

That was the fix in my case.

3 Likes
index.js:43838 Refused to connect to 'ws://127.0.0.1:8080/' because it


1 Like

Hi @AliSci , I think @ilbert will provide a more detailed and even more correct and precise response, but for the mean time I’ll just share what I think is the issue here. Please try to revisit Step 4: on the medium tutorial, specifically the part of removing .ic-assets.json5 file, if you have already removed it, try removing the the dist directory and redeploy. Or you can try to modify the .ic-assets.json5 file by adding this ws://127.0.0.1:8080/ at the Content-Security-Policy line at connect-src 'self' like this connect-src 'self' https://icp0.io https://*.icp0.io ws://127.0.0.1:8080/. If you have 2 assets.json5, do this in both of them, and redeploy.
Also, for quick testing locally, I think you might be able to temporarily avoid this issue by using npm start instead using this local replica url, you might want to try that as well.

As for the Uncaught ReferenceError: IDL is not defined error, I’m not really sure what could be going wrong there without seeing the code.

2 Likes

@iamenochchirima you explained the Content-Security-Policy solution correctly!

Regarding this error, instead:

you just need to import IDL from @dfinity/candid to solve it:

import { IDL } from "@dfinity/candid";

The tutorial is not so clear on this point, we’re updating it.

1 Like

By the way, we’ve published the packages on the registries :tada: :

Motoko CDK will soon be published on mops.

Please expect frequent (minor) updates in the next weeks.

3 Likes

And we’ve opened a Discord server for everything related to IC WebSockets, see you also there!

1 Like

Check this out guys!

@ilbert
Oh my gosh it works now>>> thank you so much guys.
One last thing please
I want to make and update method like this

#[update]
fn send_message(text: String) {
...
}

which take a string and just send a message how can I achieve that?

2 Likes

To send a message from the canister to a connected client (you must know its principal), you can simply use the ws_send method! In your case:

#[update]
fn send_message(text: String) -> ic_websocket_cdk::CanisterWsSendResult {
    let msg_bytes = candid::encode_one(&text).unwrap();
    // here you need to get the client's principal to which you want to send the message to
    // the client must be connected to the canister via WebSocket
    let client_principal = ...;
    ic_websocket_cdk::ws_send(client_principal, msg_bytes)
}

We also did something similar for the canister that we use in the integration tests, to programmatically make the canister send a bunch of messages to a connected client:

1 Like

ok so u mean in the frontend I should

const authClient = await AuthClient.create();
const client_principal = authClient.princpal();
// then call my actor
await websocket_backend.send_message(client_principal,message);

You should record the client’s principal once it connects to the canister and the on_open callback is fired, like we do in the test canister in the gateway repo:

This way, you can map the connected clients’ principals with some data/identifiers you use in your canister, so that you can look for them later to know their principal and properly call the ic_websocket_cdk::ws_send method.

What is your use case here? Who is supposed to call the send_message update method? If it’s the client itself, it doesn’t make sense because the flow becomes:

  • client calls send_message with its principal to make the canister send a message
  • canister sends a message to that principal
  • same client receives that message :thinking:

If you instead want to send a message from the client to the canister, you should use the send method of the IcWebSocket JS instance (see the example for reference), like you would do in a traditional websocket application.

1 Like
ws.onmessage = async (event) => {
    console.log("Received message:", event.data);

    // serialize the message with candid before sending it
    const messageToSend = IDL.encode([AppMessageIdl], [
        {
            text: event.data.text + "-pong test message here",
        }
    ]);
    ws.send(new Uint8Array(messageToSend));
};

I got the event.data in form of array instead of text ? How can I parse that?

also I can do channel messages? right? because I want to a send a message to a group of people not just one person .

One more issue when I send a message it send fine , but when i send another message to the same client_principal again it shows

"client with principal yqohg-fuhxk-4j44w-rzoqt-ma5qb-fio7j-5mk26-am4ql-crjqw-z23uj-mae doesn't have an open connection"'

As we do in the example, you can do it by simply using the IDL.decode function:

const receivedMessage = IDL.decode([AppMessageIdl], event.data)[0] as unknown as AppMessage;

From the next minor release, you won’t have to do it anymore as we’ll handle serialization and deserialization automatically for you in the JS client.

1 Like

As of right now, you can’t have channels in IC WebSocket. But you can easily handle them by creating custom maps group_idclient_principal and adding clients accordingly when the on_open callback is fired. Then, when you want to send a message to a group of client, you can simply iterate on the map entries and invoke the ws_send for each client_principal. Does this help?

This is a weird error. Can you please paste here the piece of code that generates it and the full logs?
I’m expecting that on the client side there are some logs (most likely errors) that should tell you why the IC WebSocket connection has been closed.

We also send messages in batches to the same client in our integration tests, without getting any error:

1 Like

Bro thank you so much I achieved my milestone now. I will also make a video tutorial for that to help other people.

2 Likes

:tada: That’s great @AliSci! Let’s also have a chat together if you like! Feel free to book a session on my calendar: IC WebSocket | Luca Bertelli | Cal.com.