IC WebSocket: Stable Release

I’ve upgraded to JS v0.2.2 and Motoko v0.2.2, upgraded the code on the canister and generated with dfx the files for the frontend

When creating new IcWebSocket(gatewayUrl, undefined, wsConfig); I get the following error:

ws_message method must have 2 arguments
at extractApplicationMessageIdlFromActor

Do i have to make another change for this new version besides adding the createWsConfig()?

Based on what you said, you should be fine on the JS side.
You just have to update the ws_message exposed method in the canister to include a second argument with your message type, like we do in the tutorial:

- public shared ({ caller }) func ws_message(args : IcWebSocketCdk.CanisterWsMessageArguments) : async IcWebSocketCdk.CanisterWsMessageResult {
-   await ws.ws_message(caller, args);
+ public shared ({ caller }) func ws_message(args : IcWebSocketCdk.CanisterWsMessageArguments, msg_type: ?MyMessage) : async IcWebSocketCdk.CanisterWsMessageResult {
+   await ws.ws_message(caller, args, msg_type);
  };

You can also find an example in the docs of the IcWebSocket.ws_message method: https://mops.one/ic-websocket-cdk/docs/lib#IcWebSocket.ws_message.

I’ll also leave here the diff of the Rust example that shows what to change, which can be helpful.

Please remember to generate the JS declarations again after this change.

2 Likes

To those who are following the Motoko websocket implementation, I have updated the examples as well, chat and pingpong, they are now using the JS SDK v0.2.2 and Motoko CDK v0.2.0. Messages are now being sent and received without explicit serialization and deserialization.

6 Likes

IC WebSocket Gateway Docker image now available at omniadevs/ic-websocket-gateway! :tada:

8 Likes

New release, breaking changes!

Today we’re releasing new IC WebSocket versions that affect both the SDKs and the gateway.

:warning: With this release, the gateway hosted at gateway.icws.io will become incompatible with all clients running old SDKs versions! Please upgrade the SDKs!

New versions

SDKs:

Gateway:

What’s changed

The CDKs now support multiple gateways! This means that you can now specify an array of gateway principals in the CDK initialization, and those will be the gateways authorized to interact with the canister.

For the Gateway, we’ve updated the IC WebSocket protocol to meet the latest requirements and we’ve added the tracing telemetry! We’re planning make a Jaeger UI dashboard publicly available.

Actions required

  1. in JS, if you have any @dfinity/... dependency, make sure you upgrade/downgrade them to v0.20.1
  2. upgrade both JS and canister libraries to the latest versions
    In case you can’t upgrade the @dfinity/... dependencies, installing the latest ic-websocket-js version using npm install ic-websocket-js@0.3.0 --force should work as a temporary fix.
  3. if you’re using Rust in your canister, change the initialization of the WsInitParams to:
    - let params = WsInitParams::new(handlers, gateway_principal);
    + let params = WsInitParams::new(handlers, vec![gateway_principal]);
    
    and eventually include other gateways’ principals in the array.
  4. if you’re using Motoko in your canister, change the IcWebSocketState initialization to:
    - var ws_state = IcWebSocketCdk.IcWebSocketState(gateway_principal);
    + var ws_state = IcWebSocketCdk.IcWebSocketState([gateway_principal]);
    
    and eventually include other gateways’ principals in the array.

That’s all you have to do!

You can also follow the updated tutorial for reference.

Motivation

Following our Proposal: Enable canisters to pay in ICP for external services, we are moving towards a more decentralized deployment of the gateways.
We’re now experimenting with Flux and we’ve already deployed some instances of the WS Gateway there. We will follow up with instructions on how to use those gateways as well.

The hosted gateway at gateway.icws.io will remain available.

6 Likes

Is the experiment with the Flux Blockchain an isolated solution for Flux or is some integration with the IC?

2 Likes

We want to create a service in which canisters can pay for external services like servers, and we’re experimenting with Flux to do so.

In the case of IC WebSockets, we want to enable developers to simply pay some tokens to spin up their own IC WebSocket Gateway on Flux nodes. This way, the Gateway is not controlled by us and the developers do not have to self host it.

I’d suggest you to have a look at the mentioned:

3 Likes

Updated Java WS Agent according the latest spec. Working with @ilbert to resolve some issues with Keep Alive message. Thanks Luca for your help!

4 Likes

Thanks to you Roman for integrating IC WebSocket in Java and enable many more potential applications to use it!

3 Likes

The latest version of IC4J WebSocket Agent library is out. It’s compatible with the latest Gateway spec. We also resolved the problem with keep alive messages, thanks @ilbert!

4 Likes

New release!

Today we’re releasing new IC WebSocket versions that affect both the SDKs and the gateway.

New versions

SDKs:

Gateway:

What’s changed

SDKs

We suggest you to update all your SDKs to the latest version.

You don’t have to specify the gateway principals anymore in the parameters, the protocol handles it for you under the hood!

If you’re using Rust in your canister, change the initialization of the WsInitParams to:

- let params = WsInitParams::new(handlers, vec![gateway_principal]);
+ let params = WsInitParams::new(handlers);

If you’re using Motoko in your canister, import the new modules from the CDK and initialize it with:

import IcWebSocketCdk "mo:ic-websocket-cdk";
+ import IcWebSocketCdkState "mo:ic-websocket-cdk/State";
+ import IcWebSocketCdkTypes "mo:ic-websocket-cdk/Types";

actor class YourCansiter() {
+   let params = IcWebSocketCdkTypes.WsInitParams(null, null, null);

-   var ws_state = IcWebSocketCdk.IcWebSocketState([gateway_principal]);
+   let ws_state = IcWebSocketCdkState.IcWebSocketState(params);

    // on_open, on_message, on_close callbacks defined here...

-   let handlers = IcWebSocketCdk.WsHandlers(
+   let handlers = IcWebSocketCdkTypes.WsHandlers(
      ?on_open,
      ?on_message,
      ?on_close,
    );

-   let params = IcWebSocketCdk.WsInitParams(
-     handlers,
-     null,
-     null,
-     null,
-   );

-   let ws = IcWebSocketCdk.IcWebSocket(ws_state, params);
+   let ws = IcWebSocketCdk.IcWebSocket(ws_state, params, handlers);

    // expose the ws_... methods here
};

That’s all you have to do!

You can also follow the updated tutorial for reference.

Gateway

  • big refactoring of the gateway codebase, which involves the use of dashmap. Now a single state is shared across client session handlers and pollers.
  • the polling logic has been changed, so that if there are still messages in the canister’s queue, the poller immediately polls them, without waiting for the next polling iteration.
  • errors returned from the replica/canister during polling are handled in a better way, so that the poller is not always terminated when they occur
8 Likes

Apologies for the late update, to those following the Motoko examples for ic-websockets, the examples have been updated now to use the latest versions of the sdks here: chat, ping-pong.

5 Likes

New release!

Today we’re releasing new IC WebSocket versions that affect both the SDKs and the gateway.

New versions

SDKs:

Gateway:

What’s changed

SDKs

We suggest you to update all your SDKs to the latest version.

  • you can close the connection with the client from the canister using the newly introduced close CDK method:
    • Rust:
      ic_websocket_cdk::close(client_principal);
      
    • Motoko:
      await ws.close(client_principal);
      // or (but doesn't call the on_close callback):
      // await IcWebSocketCdk.close(ws_state, client_principal);
      
  • you don’t have to specify the keep alive timeout parameter anymore (if you were doing it)
    • Rust: the WsInitParams struct doesn’t have the keep_alive_timeout_ms field anymore.
    • Motoko: WsInitParams are now initialized with one argument less:
      - let params = IcWebSocketCdkTypes.WsInitParams(null, null, null);
      + let params = IcWebSocketCdkTypes.WsInitParams(null, null);
      
  • ws_send is deprecated, use send instead:
    • Rust:
      - ic_websocket_cdk::ws_send(client_principal, message_bytes);
      + ic_websocket_cdk::send(client_principal, message_bytes);
      
    • Motoko:
      - await IcWebSocketCdk.ws_send(ws_state, client_principal, msg_bytes)
      + await IcWebSocketCdk.send(ws_state, client_principal, msg_bytes)
      

You can also follow the updated tutorial for reference.

Gateway

  • fix: call ws_close when canister closes connection (even with an error)
4 Likes

Are there any changes to the protocol itself? Would i need to update the .NET client?

Yes, there are some small changes to do.

Ack message timeout

The developer cannot specify the timeout for the acknowledgement of the messages anymore, as it’s now is calculated as:

ackMessageInterval + COMMUNICATION_LATENCY_BOUND_MS

where:

  • ackMessageInterval can be configured by the developer and must be the same as the send_ack_interval_ms configured on the canister
  • COMMUNICATION_LATENCY_BOUND_MS is a fixed number (30_000, 30 seconds) that also the canister uses

Main diff reference: Comparing v0.3.1...v0.3.2 · omnia-network/ic-websocket-sdk-js · GitHub.

Open timeout

The client now has a timeout when opening the connection and waiting for the OpenMessage from the canister, calculated as:

2 * COMMUNICATION_LATENCY_BOUND_MS

Main diff reference: Comparing v0.3.1...v0.3.2 · omnia-network/ic-websocket-sdk-js · GitHub.

Close connection from canister

The connection can now be closed also from the canister side. To do so, the canister sends a WebsocketServiceMessageContent::CloseMessage(CloseMessageReason) service message variant, to which the client has to react by simply closing the WebSocket connection with the gateway.

The service message Candid types are always available in the ic-websocket-cdk-rs/src/ic-websocket-cdk/service_messages.did file.

Main diff reference: Comparing v0.3.1...v0.3.2 · omnia-network/ic-websocket-sdk-js · GitHub.

Reach me out if you need any further help.


Adding also @rdobrik to the loop, for the ic4j WebSocket client.

5 Likes

New release (minor changes)!

We’re releasing new IC WebSocket versions that affect some of the SDKs.

New versions

SDKs:

3 Likes

Hey Devs, I’m happy to announce that we’ve just completed our initial integration of IC websockets into our project, tswaanda. Our first implementaion of websockets enables real-time notifications, facilitating instant message exchanges from the marketplace to the admin dashboard clients and vice versa in our project. This includes sending messages to specific clients as well as broadcasting to all marketplace clients. We’re actively working on expanding our use cases, with more real-time features on the coming soon.

For those new to ic-websockets in Motoko and seeking inspiration, take a look at our implementation code below. If you’re seasoned in this area, we warmly welcome and appreciate any suggestions to improve our current implementation and use cases.
A huge shoutout and thanks to @ilbert and @massimoalbarello for bringing this awesome tool on IC to life, and for their support and assistance as well.

You can find the code for our implementation here.

6 Likes

We now have a status page for the IC WebSocket Gateway hosted on AWS, go check it out!

6 Likes

New release!

Today we’re releasing new IC WebSocket versions that affect all the SDKs.

New versions

SDKs:

What’s changed

SDKs

Dependencies have been updated.

For the JS SDK, we’ve bumped the @dfinity/... dependencies to v1.0.1.

3 Likes

We fixed the issue with Internet Identities: now you can pass an identity from authClient.getIdentity() to the IcWebSocket constructor.

I think this is not working.
authClient.getIdentity() return identity of type Identity but to initialize websocket we need identity of type SignIdentity.