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:
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.
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
in JS, if you have any @dfinity/... dependency, make sure you upgrade/downgrade them to v0.20.1
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 usingnpm install ic-websocket-js@0.3.0 --forceshould work as a temporary fix.
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.
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.
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.
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!
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
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.
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.
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.
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.