Skip to content

Commit

Permalink
Merge pull request #3 from omnia-network/release/0.3.1
Browse files Browse the repository at this point in the history
release/0.3.1
  • Loading branch information
ilbertt authored Dec 4, 2023
2 parents a0007cd + f1a4838 commit 736a4e1
Show file tree
Hide file tree
Showing 16 changed files with 1,565 additions and 1,208 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ on:
branches:
- main
pull_request:
types:
- opened
- synchronize
- reopened
- ready_for_review

jobs:
test:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
with:
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![mops](https://oknww-riaaa-aaaam-qaf6a-cai.raw.ic0.app/badge/mops/ic-websocket-cdk)](https://mops.one/ic-websocket-cdk)

This repository contains the Motoko implementation of IC WebSocket CDK. For more information about IC WebSockets, see [IC WebSocket Gateway](https://github.com/omnia-network/ic-websocket-gateway).
This repository contains the Motoko implementation of IC WebSocket CDK and is basically a mirror of the [Rust CDK](https://github.com/omnia-network/ic-websocket-cdk-rs). For more information about IC WebSockets, see [IC WebSocket Gateway](https://github.com/omnia-network/ic-websocket-gateway).

## Installation

Expand All @@ -14,16 +14,16 @@ mops add ic-websocket-cdk

## Usage

Refer to the [ic-websockets-pingpong-mo](https://github.com/iamenochchirima/ic-websockets-pingpong-mo) repository for an example of how to use this library.
Refer to the [ic-websockets-pingpong-mo](https://github.com/iamenochchirima/ic-websockets-pingpong-mo) and/or [ic-websockets-chat-mo](https://github.com/iamenochchirima/ic-websockets-chat-mo) repositories for examples of how to use this library.

### Candid interface
In order for the frontend clients and the Gateway to work properly, the canister must expose some specific methods in its Candid interface, between the custom methods that you've implemented for your logic. A valid Candid interface for the canister is the following:

```
import "./ws_types.did";
// define here your message type
type MyMessageType = {
// define your message type here
type MyMessageType = record {
some_field : text;
};
Expand Down Expand Up @@ -53,7 +53,7 @@ Clone the repo with submodules:
git clone --recurse-submodules https://github.com/omnia-network/ic-websocket-cdk-mo.git
```

Integration tests are imported from the [IC WebSocket Rust CDK](https://github.com/omnia-network/ic-websocket-cdk-rs.git), linked to this repo from the `ic-websocket-cdk-rs` submodule in the [tests](./tests/) folder.
Integration tests are imported from the [IC WebSocket Rust CDK](https://github.com/omnia-network/ic-websocket-cdk-rs.git), linked to this repo through the [`ic-websocket-cdk-rs`](./tests/ic-websocket-cdk-rs) submodule.

There's a script that runs the integration tests, taking care of installing dependencies and setting up the local environment. To run the script, execute the following command:

Expand Down
2 changes: 1 addition & 1 deletion did/service.example.did
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./ws_types.did";

// define your message type here
type MyMessageType = {
type MyMessageType = record {
some_field : text;
};

Expand Down
3 changes: 3 additions & 0 deletions did/ws_types.did
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
type ClientPrincipal = principal;
type GatewayPrincipal = principal;
type ClientKey = record {
client_principal : ClientPrincipal;
client_nonce : nat64;
Expand All @@ -22,10 +23,12 @@ type CanisterOutputCertifiedMessages = record {
messages : vec CanisterOutputMessage;
cert : blob;
tree : blob;
is_end_of_queue : bool;
};

type CanisterWsOpenArguments = record {
client_nonce : nat64;
gateway_principal : GatewayPrincipal;
};

type CanisterWsOpenResult = variant {
Expand Down
2 changes: 1 addition & 1 deletion mops.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ic-websocket-cdk"
version = "0.3.0"
version = "0.3.1"
description = "IC WebSocket Motoko CDK"
repository = "https://github.com/omnia-network/ic-websocket-cdk-mo"
keywords = ["ic", "websocket", "motoko", "cdk"]
Expand Down
2 changes: 1 addition & 1 deletion scripts/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ export TEST_CANISTER_WASM_PATH="$(pwd)/bin/test_canister.wasm"

cd tests/ic-websocket-cdk-rs

RUST_BACKTRACE=1 cargo test --package ic-websocket-cdk --lib -- tests::integration_tests --test-threads 1
cargo test --package ic-websocket-cdk --lib -- tests::integration_tests --test-threads 1
21 changes: 21 additions & 0 deletions src/Constants.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
module {
/// The label used when constructing the certification tree.
public let LABEL_WEBSOCKET : Blob = "websocket";
/// The default maximum number of messages returned by [ws_get_messages] at each poll.
public let DEFAULT_MAX_NUMBER_OF_RETURNED_MESSAGES : Nat = 50;
/// The default interval at which to send acknowledgements to the client.
public let DEFAULT_SEND_ACK_INTERVAL_MS : Nat64 = 300_000; // 5 minutes
/// The default timeout to wait for the client to send a keep alive after receiving an acknowledgement.
public let DEFAULT_CLIENT_KEEP_ALIVE_TIMEOUT_MS : Nat64 = 60_000; // 1 minute

/// The initial nonce for outgoing messages.
public let INITIAL_OUTGOING_MESSAGE_NONCE : Nat64 = 0;
/// The initial sequence number to expect from messages coming from clients.
/// The first message coming from the client will have sequence number `1` because on the client the sequence number is incremented before sending the message.
public let INITIAL_CLIENT_SEQUENCE_NUM : Nat64 = 1;
/// The initial sequence number for outgoing messages.
public let INITIAL_CANISTER_SEQUENCE_NUM : Nat64 = 0;

/// The number of messages to delete from the outgoing messages queue every time a new message is added.
public let MESSAGES_TO_DELETE_COUNT : Nat = 5;
};
88 changes: 88 additions & 0 deletions src/Errors.mo
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Principal "mo:base/Principal";
import Nat64 "mo:base/Nat64";

import Types "Types";

module {
public type WsError = {
#AnonymousPrincipalNotAllowed;
#ClientKeyAlreadyConnected : {
client_key : Types.ClientKey;
};
#ClientKeyMessageMismatch : {
client_key : Types.ClientKey;
};
#ClientKeyNotConnected : {
client_key : Types.ClientKey;
};
#ClientNotRegisteredToGateway : {
client_key : Types.ClientKey;
gateway_principal : Types.GatewayPrincipal;
};
#ClientPrincipalNotConnected : {
client_principal : Types.ClientPrincipal;
};
#DecodeServiceMessageContent : {
err : Text;
};
#ExpectedIncomingMessageToClientNumNotInitialized : {
client_key : Types.ClientKey;
};
#GatewayNotRegistered : {
gateway_principal : Types.GatewayPrincipal;
};
#InvalidServiceMessage;
#IncomingSequenceNumberWrong : {
expected_sequence_num : Nat64;
actual_sequence_num : Nat64;
};
#OutgoingMessageToClientNumNotInitialized : {
client_key : Types.ClientKey;
};
};

public func to_string(err : WsError) : Text {
switch (err) {
case (#AnonymousPrincipalNotAllowed) {
"Anonymous principal is not allowed";
};
case (#ClientKeyAlreadyConnected({ client_key })) {
"Client with key " # Types.clientKeyToText(client_key) # " already has an open connection";
};
case (#ClientKeyMessageMismatch({ client_key })) {
"Client with principal " # Principal.toText(client_key.client_principal) # " has a different key than the one used in the message";
};
case (#ClientKeyNotConnected({ client_key })) {
"Client with key " # Types.clientKeyToText(client_key) # " doesn't have an open connection";
};
case (#ClientNotRegisteredToGateway({ client_key; gateway_principal })) {
"Client with key " # Types.clientKeyToText(client_key) # " was not registered to gateway " # Principal.toText(gateway_principal);
};
case (#ClientPrincipalNotConnected({ client_principal })) {
"Client with principal " # Principal.toText(client_principal) # " doesn't have an open connection";
};
case (#DecodeServiceMessageContent({ err })) {
"Error decoding service message content: " # err;
};
case (#ExpectedIncomingMessageToClientNumNotInitialized({ client_key })) {
"Expected incoming message to client num not initialized for client key " # Types.clientKeyToText(client_key);
};
case (#GatewayNotRegistered({ gateway_principal })) {
"Gateway with principal " # Principal.toText(gateway_principal) # " is not registered";
};
case (#InvalidServiceMessage) {
"Invalid service message";
};
case (#IncomingSequenceNumberWrong({ expected_sequence_num; actual_sequence_num })) {
"Expected incoming sequence number " # Nat64.toText(expected_sequence_num) # " but got " # Nat64.toText(actual_sequence_num);
};
case (#OutgoingMessageToClientNumNotInitialized({ client_key })) {
"Outgoing message to client num not initialized for client key " # Types.clientKeyToText(client_key);
};
};
};

public func to_string_result(err : WsError) : Types.Result<(), Text> {
#Err(to_string(err));
};
};
8 changes: 0 additions & 8 deletions src/Logger.mo

This file was deleted.

Loading

0 comments on commit 736a4e1

Please sign in to comment.