diff --git a/.github/workflows/maven-release.yml b/.github/workflows/maven-release.yml
index 86a4753..285117d 100644
--- a/.github/workflows/maven-release.yml
+++ b/.github/workflows/maven-release.yml
@@ -51,7 +51,7 @@ jobs:
- name: Set up JDK
uses: actions/setup-java@v1
with:
- java-version: 11
+ java-version: 17
- name: Build with Maven
run: mvn -DskipTests package
@@ -59,7 +59,7 @@ jobs:
- name: Set up Apache Maven Central
uses: actions/setup-java@v1
with: # running setup-java again overwrites the settings.xml
- java-version: 11
+ java-version: 17
server-id: ossrh
server-username: OSSRH_USERNAME
server-password: OSSRH_PASSWORD
diff --git a/pom.xml b/pom.xml
index 876fe1e..2b3c681 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.wire
helium
- 1.4.1
+ 1.5.0
Helium
User mode for Wire Bots
@@ -53,8 +53,8 @@
- 11
- 11
+ 17
+ 17
UTF-8
UTF-8
@@ -65,7 +65,7 @@
com.wire
xenon
- 1.6.2
+ 1.7.0
jakarta.ws.rs
@@ -156,7 +156,7 @@
org.apache.maven.plugins
maven-javadoc-plugin
- 3.2.0
+ 3.5.0
attach-javadocs
diff --git a/src/main/java/com/wire/helium/API.java b/src/main/java/com/wire/helium/API.java
index c7fd19b..448d756 100644
--- a/src/main/java/com/wire/helium/API.java
+++ b/src/main/java/com/wire/helium/API.java
@@ -22,14 +22,18 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.protobuf.ByteString;
import com.wire.helium.models.Connection;
+import com.wire.helium.models.model.response.FeatureConfig;
import com.wire.helium.models.NotificationList;
+import com.wire.helium.models.model.response.PublicKeysResponse;
+import com.wire.helium.models.model.request.ConversationListPaginationConfig;
+import com.wire.helium.models.model.request.ConversationListRequest;
+import com.wire.helium.models.model.response.ConversationListIdsResponse;
+import com.wire.helium.models.model.response.ConversationListResponse;
import com.wire.messages.Otr;
import com.wire.xenon.WireAPI;
import com.wire.xenon.assets.IAsset;
-import com.wire.xenon.backend.models.Conversation;
-import com.wire.xenon.backend.models.Member;
-import com.wire.xenon.backend.models.QualifiedId;
-import com.wire.xenon.backend.models.User;
+import com.wire.xenon.backend.KeyPackageUpdate;
+import com.wire.xenon.backend.models.*;
import com.wire.xenon.exceptions.AuthException;
import com.wire.xenon.exceptions.HttpException;
import com.wire.xenon.models.AssetKey;
@@ -53,6 +57,7 @@
import java.util.stream.Collectors;
public class API extends LoginClient implements WireAPI {
+ private final WebTarget versionedPath;
private final WebTarget conversationsPath;
private final WebTarget usersPath;
private final WebTarget assetsPath;
@@ -60,6 +65,8 @@ public class API extends LoginClient implements WireAPI {
private final WebTarget connectionsPath;
private final WebTarget selfPath;
private final WebTarget notificationsPath;
+ private final WebTarget clientsPath;
+ private final WebTarget mlsPath;
private final String token;
private final QualifiedId convId;
@@ -71,6 +78,7 @@ public API(Client client, QualifiedId convId, String token) {
this.token = token;
WebTarget versionedTarget = client.target(host()).path(BACKEND_API_VERSION);
+ versionedPath = versionedTarget;
conversationsPath = versionedTarget.path("conversations");
usersPath = versionedTarget.path("users");
@@ -79,6 +87,8 @@ public API(Client client, QualifiedId convId, String token) {
connectionsPath = versionedTarget.path("connections");
selfPath = versionedTarget.path("self");
notificationsPath = versionedTarget.path("notifications");
+ clientsPath = versionedTarget.path("clients");
+ mlsPath = versionedTarget.path("mls");
}
/**
@@ -347,12 +357,7 @@ public Conversation getConversation() {
throw new RuntimeException(msgError);
}
- _Conv conv = response.readEntity(_Conv.class);
- Conversation ret = new Conversation();
- ret.name = conv.name;
- ret.id = conv.id;
- ret.members = conv.members.others;
- return ret;
+ return response.readEntity(Conversation.class);
}
@Override
@@ -436,13 +441,7 @@ public Conversation createConversation(String name, UUID teamId, List
+ * To verify if MLS is enabled we need to go through 2 requests. They are:
+ *
+ *
+ * First: from GET /feature-configs there will be a `mls` object containing a `status` of type boolean
+ *
+ *
+ * Second: from GET /mls/public/keys returning a `removal` object containing public keys
+ *
+ *
+ * If the first value is false, then we already return a `false` value.
+ * If the first value is true, then we do the second request, in case it returns a 200 HTTP Code then MLS is
+ * enabled and we can return a `true` value.
+ *
+ * In case any of those requests fail (with HTTP Code >= 400) then we assume it is not enabled and log the error.
+ *
+ *
+ * @return boolean
+ */
+ @Override
+ public boolean isMlsEnabled() {
+ Response featureConfigsResponse = versionedPath
+ .path("feature-configs")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .get();
- @JsonProperty
- public String name;
+ if (isErrorResponse(featureConfigsResponse.getStatus())) {
+ String msgError = featureConfigsResponse.readEntity(String.class);
+ Logger.error("isMlsEnabled - Feature Configs error: %s, status: %d", msgError, featureConfigsResponse.getStatus());
+ return false;
+ }
- @JsonProperty
- public _Members members;
+ FeatureConfig featureConfig = featureConfigsResponse.readEntity(FeatureConfig.class);
+
+ if (featureConfig.mls.isMlsStatusEnabled()) {
+ Response mlsPublicKeysResponse = mlsPath
+ .path("public-keys")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .get();
+
+ if (isErrorResponse(featureConfigsResponse.getStatus())) {
+ String msgError = featureConfigsResponse.readEntity(String.class);
+ Logger.error("isMlsEnabled - Public Keys error: %s, status: %d", msgError, featureConfigsResponse.getStatus());
+ return false;
+ }
+
+ try {
+ PublicKeysResponse publicKeysResponse = mlsPublicKeysResponse.readEntity(PublicKeysResponse.class);
+ } catch (Exception e) {
+ Logger.error("isMlsEnabled - Public Keys Deserialization error: %s", e.getMessage());
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
}
- @JsonIgnoreProperties(ignoreUnknown = true)
- public static class _Members {
- @JsonProperty
- public List others;
+ /**
+ *
+ * To upload client public key we PUT a {@link ClientUpdate} object containing the public keys
+ * to /clients/{clientId}
+ *
+ *
+ * As there is no return, in case it fails we just map the HTTP Code and log the message.
+ *
+ *
+ * @param clientId clientId to upload the public keys
+ * @param clientUpdate the public keys
+ */
+ @Override
+ public void uploadClientPublicKey(String clientId, ClientUpdate clientUpdate) {
+ try {
+ Response response = clientsPath
+ .path(clientId)
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .put(Entity.json(clientUpdate));
+
+ if (isErrorResponse(response.getStatus())) {
+ String msgError = response.readEntity(String.class);
+ Logger.error(
+ "uploadClientPublicKey error: %s, clientId: %s, status: %d",
+ msgError, clientId, response.getStatus()
+ );
+ } else if(isSuccessResponse(response.getStatus())) {
+ Logger.info("uploadClientPublicKey success for clientId: %s", clientId);
+ }
+ } catch (Exception e) {
+ Logger.error("uploadClientPublicKey error: %s", e.getMessage());
+ }
+ }
+
+ /**
+ *
+ * To upload client key packages we POST a {@link KeyPackageUpdate} object containing a list of package keys
+ * to /mls/key-packages/self/{clientId}
+ *
+ *
+ * As there is no return, in case it fails we just map the HTTP Code and log the message.
+ *
+ *
+ * @param clientId clientId to upload the package keys
+ * @param keyPackageUpdate list of package keys
+ */
+ @Override
+ public void uploadClientKeyPackages(String clientId, KeyPackageUpdate keyPackageUpdate) {
+ try {
+ Response response = mlsPath
+ .path("key-packages")
+ .path("self")
+ .path(clientId)
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .post(Entity.json(keyPackageUpdate));
+
+ if (isErrorResponse(response.getStatus())) {
+ String msgError = response.readEntity(String.class);
+ Logger.error(
+ "getConversationGroupInfo error: %s, clientId: %s, status: %d",
+ msgError, clientId, response.getStatus()
+ );
+ } else if(isSuccessResponse(response.getStatus())) {
+ Logger.info("uploadClientKeyPackages success for clientId: %s", clientId);
+ }
+ } catch (Exception e) {
+ Logger.error("uploadClientKeyPackages, clientId: %s, error: %s", clientId, e.getMessage());
+ }
}
+ @Override
+ public byte[] getConversationGroupInfo(QualifiedId conversationId) throws RuntimeException {
+ Response response = conversationsPath
+ .path(conversationId.domain)
+ .path(conversationId.id.toString())
+ .path("groupinfo")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .accept("message/mls")
+ .get();
+
+ if (isSuccessResponse(response.getStatus())) {
+ return response.readEntity(byte[].class);
+ }
+
+ if (isErrorResponse(response.getStatus())) {
+ String msgError = response.readEntity(String.class);
+ Logger.error("getConversationGroupInfo error: %s, status: %d", msgError, response.getStatus());
+ }
+
+ throw new RuntimeException(
+ "getConversationGroupInfo failed",
+ new HttpException(response.readEntity(String.class), response.getStatus())
+ );
+ }
+
+ @Override
+ public void commitMlsBundle(byte[] commitBundle) {
+ try {
+ Response response = mlsPath
+ .path("commit-bundles")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .post(Entity.entity(commitBundle, "message/mls"));
+
+ if (isErrorResponse(response.getStatus())) {
+ String msgError = response.readEntity(String.class);
+ Logger.error("commitMlsBundle error: %s, status: %d", msgError, response.getStatus());
+ }
+
+ if (isSuccessResponse(response.getStatus())) {
+ Logger.info("commitMlsBundle success.");
+ }
+
+ } catch (Exception e) {
+ Logger.error("commitMlsBundle error: %s", e.getMessage());
+ }
+ }
+
+ /**
+ *
+ * In order to get user conversations, first we need to get all the paginated conversation ids.
+ *
+ *
+ * For getting the conversation details, we need to do a "paginated" request, as the backend has a limit of
+ * 1000 conversation ids per request.
+ *
+ *
+ * @return List of {@link Conversation} details from the fetched conversation ids.
+ */
+ @Override
+ public List getUserConversations() {
+ ConversationListPaginationConfig pagingConfig = new ConversationListPaginationConfig(
+ null,
+ 100
+ );
+
+ List conversationIds = new ArrayList<>();
+ List conversations = new ArrayList<>();
+
+ boolean hasMorePages;
+ do {
+ hasMorePages = false;
+
+ Response listIdsResponse = conversationsPath
+ .path("list-ids")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .post(Entity.entity(pagingConfig, MediaType.APPLICATION_JSON));
+
+ if (listIdsResponse.getStatus() >= 400) {
+ String msgError = listIdsResponse.readEntity(String.class);
+ Logger.error("getUserConversations - List Ids error: %s, status: %d", msgError, listIdsResponse.getStatus());
+ }
+
+ if (listIdsResponse.getStatus() == 200) {
+ ConversationListIdsResponse conversationListIds = listIdsResponse.readEntity(ConversationListIdsResponse.class);
+ hasMorePages = conversationListIds.hasMore;
+ pagingConfig.setPagingState(conversationListIds.pagingState);
+
+ conversationIds.addAll(conversationListIds.qualifiedConversations);
+
+ Logger.info("getUserConversations - List Ids success. has more pages: " + hasMorePages);
+ }
+ } while (hasMorePages);
+
+ if (!conversationIds.isEmpty()) {
+ int startIndex = 0;
+ int endIndex = 1000;
+ do {
+ if (endIndex > conversationIds.size()) {
+ endIndex = conversationIds.size();
+ }
+
+ conversations.addAll(getConversationsFromIds(conversationIds.subList(startIndex, endIndex)));
+ startIndex += 1000;
+ endIndex += 1000;
+ } while (endIndex < conversationIds.size() + 1000);
+ }
+
+ return conversations;
+ }
+
+ private List getConversationsFromIds(List conversationIds) {
+ Response conversationListResponse = conversationsPath
+ .path("/list")
+ .request(MediaType.APPLICATION_JSON)
+ .header(HttpHeaders.AUTHORIZATION, bearer(token))
+ .post(Entity.entity(
+ new ConversationListRequest(conversationIds),
+ MediaType.APPLICATION_JSON
+ ));
+
+ if (conversationListResponse.getStatus() == 200) {
+ ConversationListResponse result = conversationListResponse.readEntity(ConversationListResponse.class);
+
+ return result.found;
+ }
+
+ if (conversationListResponse.getStatus() >= 400) {
+ String msgError = conversationListResponse.readEntity(String.class);
+ Logger.error("getUserConversations - Conversation List error: %s, status: %d", msgError, conversationListResponse.getStatus());
+ }
+
+ return List.of();
+ }
+
+ private boolean isErrorResponse(int statusCode) {
+ return Response.Status.Family.familyOf(statusCode).equals(Response.Status.Family.CLIENT_ERROR)
+ || Response.Status.Family.familyOf(statusCode).equals(Response.Status.Family.SERVER_ERROR);
+ }
+
+ private boolean isSuccessResponse(int statusCode) {
+ return Response.Status.Family.familyOf(statusCode).equals(Response.Status.Family.SUCCESSFUL);
+ }
+
+ /**
+ * @deprecated This class is deprecated and in case there is any work related to _Service,
+ * {@link Service} can be used instead.
+ */
@JsonIgnoreProperties(ignoreUnknown = true)
static class _Service {
public UUID service;
diff --git a/src/main/java/com/wire/helium/models/model/request/ConversationListPaginationConfig.java b/src/main/java/com/wire/helium/models/model/request/ConversationListPaginationConfig.java
new file mode 100644
index 0000000..087b0fc
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/request/ConversationListPaginationConfig.java
@@ -0,0 +1,32 @@
+package com.wire.helium.models.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ConversationListPaginationConfig {
+ @JsonProperty("paging_state")
+ public String pagingState;
+
+ @JsonProperty("size")
+ public int size;
+
+ public ConversationListPaginationConfig(String pagingState, int size) {
+ this.pagingState = pagingState;
+ this.size = size;
+ }
+
+ public String getPagingState() {
+ return pagingState;
+ }
+
+ public void setPagingState(String pagingState) {
+ this.pagingState = pagingState;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public void setSize(int size) {
+ this.size = size;
+ }
+}
diff --git a/src/main/java/com/wire/helium/models/model/request/ConversationListRequest.java b/src/main/java/com/wire/helium/models/model/request/ConversationListRequest.java
new file mode 100644
index 0000000..88c96ed
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/request/ConversationListRequest.java
@@ -0,0 +1,15 @@
+package com.wire.helium.models.model.request;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.wire.xenon.backend.models.QualifiedId;
+
+import java.util.List;
+
+public class ConversationListRequest {
+ @JsonProperty("qualified_ids")
+ public List qualifiedIds;
+
+ public ConversationListRequest(List qualifiedIds) {
+ this.qualifiedIds = qualifiedIds;
+ }
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/ConversationListIdsResponse.java b/src/main/java/com/wire/helium/models/model/response/ConversationListIdsResponse.java
new file mode 100644
index 0000000..dc2fc74
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/ConversationListIdsResponse.java
@@ -0,0 +1,19 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.wire.xenon.backend.models.QualifiedId;
+
+import java.util.List;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ConversationListIdsResponse {
+ @JsonProperty("has_more")
+ public boolean hasMore;
+
+ @JsonProperty("paging_state")
+ public String pagingState;
+
+ @JsonProperty("qualified_conversations")
+ public List qualifiedConversations;
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/ConversationListResponse.java b/src/main/java/com/wire/helium/models/model/response/ConversationListResponse.java
new file mode 100644
index 0000000..1c3dedc
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/ConversationListResponse.java
@@ -0,0 +1,20 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.wire.xenon.backend.models.Conversation;
+import com.wire.xenon.backend.models.QualifiedId;
+
+import java.util.List;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class ConversationListResponse {
+ @JsonProperty("failed")
+ public List failed;
+
+ @JsonProperty("found")
+ public List found;
+
+ @JsonProperty("not_found")
+ public List notFound;
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/FeatureConfig.java b/src/main/java/com/wire/helium/models/model/response/FeatureConfig.java
new file mode 100644
index 0000000..6126728
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/FeatureConfig.java
@@ -0,0 +1,13 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class FeatureConfig {
+
+ @JsonProperty("mls")
+ public MlsResponse mls;
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/MlsConfigResponse.java b/src/main/java/com/wire/helium/models/model/response/MlsConfigResponse.java
new file mode 100644
index 0000000..17d100a
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/MlsConfigResponse.java
@@ -0,0 +1,23 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+import java.util.List;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class MlsConfigResponse {
+ @JsonProperty
+ public List allowedCipherSuites;
+
+ @JsonProperty
+ public Integer defaultCipherSuite;
+
+ @JsonProperty
+ public String defaultProtocol;
+
+ @JsonProperty
+ public List supportedProtocols;
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/MlsResponse.java b/src/main/java/com/wire/helium/models/model/response/MlsResponse.java
new file mode 100644
index 0000000..3e920f3
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/MlsResponse.java
@@ -0,0 +1,19 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class MlsResponse {
+ @JsonProperty("config")
+ public MlsConfigResponse config;
+
+ @JsonProperty
+ public String status;
+
+ public boolean isMlsStatusEnabled() {
+ return status.equals("enabled");
+ }
+}
diff --git a/src/main/java/com/wire/helium/models/model/response/PublicKeysResponse.java b/src/main/java/com/wire/helium/models/model/response/PublicKeysResponse.java
new file mode 100644
index 0000000..39721f6
--- /dev/null
+++ b/src/main/java/com/wire/helium/models/model/response/PublicKeysResponse.java
@@ -0,0 +1,14 @@
+package com.wire.helium.models.model.response;
+
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.wire.xenon.backend.models.ClientUpdate;
+
+@JsonIgnoreProperties(ignoreUnknown = true)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class PublicKeysResponse {
+
+ @JsonProperty("removal")
+ public ClientUpdate.MlsPublicKeys removal;
+}
diff --git a/src/test/java/com/wire/helium/End2EndTest.java b/src/test/java/com/wire/helium/End2EndTest.java
index 1c5527a..8db557f 100644
--- a/src/test/java/com/wire/helium/End2EndTest.java
+++ b/src/test/java/com/wire/helium/End2EndTest.java
@@ -12,6 +12,7 @@
import com.wire.xenon.backend.models.NewBot;
import com.wire.xenon.backend.models.QualifiedId;
import com.wire.xenon.crypto.CryptoDatabase;
+import com.wire.xenon.crypto.mls.CryptoMlsClient;
import com.wire.xenon.crypto.storage.JdbiStorage;
import com.wire.xenon.models.otr.OtrMessage;
import org.junit.jupiter.api.AfterEach;
@@ -31,6 +32,7 @@ public class End2EndTest extends DatabaseTestBase {
public void beforeEach() {
rootFolder = "helium-unit-test-" + UUID.randomUUID();
storage = new JdbiStorage(jdbi);
+
}
@AfterEach
@@ -49,11 +51,12 @@ public void testAliceToAlice() throws Exception {
CryptoDatabase aliceCrypto = new CryptoDatabase(aliceId, storage, rootFolder + "/testAliceToAlice/1");
CryptoDatabase aliceCrypto1 = new CryptoDatabase(aliceId, storage, rootFolder + "/testAliceToAlice/2");
+ CryptoMlsClient cryptoMlsClient = new CryptoMlsClient(client1, client1 + "_db_key");
DummyAPI api = new DummyAPI();
api.addDevice(aliceId, client1, aliceCrypto1.box().newLastPreKey());
- WireClient aliceClient = new WireClientBase(api, aliceCrypto, state);
+ WireClient aliceClient = new WireClientBase(api, aliceCrypto, cryptoMlsClient, state);
for (int i = 0; i < 10; i++) {
String text = "Hello Alice, This is Alice!";
@@ -78,6 +81,7 @@ public void testAliceToBob() throws Exception {
CryptoDatabase aliceCrypto = new CryptoDatabase(aliceId, storage, rootFolder + "/testAliceToBob");
CryptoDatabase bobCrypto = new CryptoDatabase(bobId, storage, rootFolder + "/testAliceToBob");
+ CryptoMlsClient cryptoMlsClient = new CryptoMlsClient(client1, client1 + "_db_key");
DummyAPI api = new DummyAPI();
api.addDevice(bobId, client1, bobCrypto.box().newLastPreKey());
@@ -85,7 +89,7 @@ public void testAliceToBob() throws Exception {
NewBot state = new NewBot();
state.id = aliceId.id;
state.client = "alice1";
- WireClient aliceClient = new WireClientBase(api, aliceCrypto, state);
+ WireClient aliceClient = new WireClientBase(api, aliceCrypto, cryptoMlsClient, state);
for (int i = 0; i < 10; i++) {
String text = "Hello Bob, This is Alice!";
@@ -112,6 +116,7 @@ public void testMultiDevicePostgres() throws Exception {
CryptoDatabase aliceCrypto1 = new CryptoDatabase(aliceId, storage, rootFolder + "/testMultiDevicePostgres/alice/1");
CryptoDatabase bobCrypto1 = new CryptoDatabase(bobId, storage, rootFolder + "/testMultiDevicePostgres/bob/1");
CryptoDatabase bobCrypto2 = new CryptoDatabase(bobId, storage, rootFolder + "/testMultiDevicePostgres/bob/2");
+ CryptoMlsClient cryptoMlsClient = new CryptoMlsClient(client1, client1 + "_db_key");
DummyAPI api = new DummyAPI();
api.addDevice(bobId, client1, bobCrypto1.box().newLastPreKey());
@@ -123,7 +128,7 @@ public void testMultiDevicePostgres() throws Exception {
NewBot state = new NewBot();
state.id = aliceId.id;
state.client = aliceCl;
- WireClient aliceClient = new WireClientBase(api, aliceCrypto, state);
+ WireClient aliceClient = new WireClientBase(api, aliceCrypto, cryptoMlsClient, state);
for (int i = 0; i < 10; i++) {
String text = "Hello Bob, This is Alice!";