...
 
Commits (6)
......@@ -14,12 +14,12 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
library matrix;
export 'src/homeserver.dart';
export 'src/user.dart';
export 'src/exception.dart';
export 'src/identifier.dart';
export 'src/device.dart';
export 'src/storables.dart';
......@@ -46,3 +46,6 @@ export 'src/event/room/state/power_levels_change_event.dart';
export 'src/store.dart';
export 'src/util/json.dart';
export 'src/encryption/olm.dart';
export 'src/encryption/account.dart';
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
export 'src/encryption/ffi/olm.dart';
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:meta/meta.dart';
class DeviceId extends Id {
DeviceId(String value) : super(value);
}
class Device extends Identifiable<DeviceId> {
@override
final DeviceId id;
final String name;
final DateTime lastSeen;
final String lastIpAddress;
Device({
@required this.id,
this.name,
this.lastSeen,
this.lastIpAddress,
});
}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'package:meta/meta.dart';
class Account {
final IdentityKeys identityKeys;
Account(this.identityKeys);
}
class IdentityKeys {
/// Curve22519 base64 encoded key.
final String curve25519;
/// Ed25519 base64 encoded key.
final String ed25519;
IdentityKeys({
@required this.curve25519,
@required this.ed25519,
});
factory IdentityKeys.fromJson(Map<String, dynamic> json) {
return IdentityKeys(
curve25519: json['curve25519'],
ed25519: json['ed25519'],
);
}
Map<String, dynamic> toJson() => {
'curve25519': curve25519,
'ed25519': ed25519,
};
}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'dart:ffi';
import 'dart:io';
/// Path to the olm dynamic library.
///
/// Note that [path] must end with a slash.
DynamicLibrary open({String path}) {
final name = 'olm';
if (path == null) path = '';
if (Platform.isLinux || Platform.isAndroid) path += 'lib$name.so';
if (Platform.isMacOS) path += 'lib$name.dylib';
if (Platform.isWindows) path += '$name.dll';
// If path is still empty, we're not on a supported platform
if (path.isEmpty) {
throw UnimplementedError("OlmFFI is not implemented on this platform");
}
print(path);
return DynamicLibrary.open(path);
}
/// A constructor function type.
typedef Constructor = Pointer<Uint8> Function(Pointer<Uint8>);
/// A size of function type.
typedef Size = int Function();
typedef SizeNative = Uint16 Function();
typedef Creator = int Function(Pointer<Uint8>, Pointer<Uint8>, int);
typedef CreatorNative = Uint16 Function(Pointer<Uint8>, Pointer<Uint8>, Uint16);
/// Size for a specific property of a struct function type.
typedef SizeFor = int Function(Pointer<Uint8>);
typedef SizeForNative = Uint16 Function(Pointer<Uint8>);
/// Get data from a property and fill in to the second pointer function type.
typedef FillFromProperty = int Function(Pointer<Uint8>, Pointer<Uint8>, int);
typedef FillFromPropertyNative = Uint16 Function(
Pointer<Uint8>,
Pointer<Uint8>,
Uint16,
);
typedef Error = int Function();
typedef ErrorNative = Uint16 Function();
/// Direct bindings to the C API of `libolm`.
///
/// All functions are the exact name as in `libolm`, except that they're
/// camelCased and not prefixed with `olm`, e.g: [account] corresponds to
/// `olm_account`.
class OlmBindings {
final DynamicLibrary lib;
Error error;
Constructor account;
Size accountSize;
Creator createAccount;
SizeFor createAccountRandomLength;
SizeFor accountIdentityKeysLength;
FillFromProperty accountIdentityKeys;
OlmBindings({String path}) : lib = open(path: path) {
error = lib.lookupFunction<ErrorNative, Error>('olm_error');
account = lib.lookupFunction<Constructor, Constructor>('olm_account');
accountSize = lib.lookupFunction<SizeNative, Size>('olm_account_size');
createAccount = lib.lookupFunction<CreatorNative, Creator>(
'olm_create_account',
);
createAccountRandomLength = lib.lookupFunction<SizeForNative, SizeFor>(
'olm_create_account_random_length',
);
accountIdentityKeysLength = lib.lookupFunction<SizeForNative, SizeFor>(
'olm_account_identity_keys_length',
);
accountIdentityKeys =
lib.lookupFunction<FillFromPropertyNative, FillFromProperty>(
'olm_account_identity_keys',
);
}
}
// Error codes, taken directly from source.
const int success = 0;
const int notEnoughRandom = 1;
const int outputBufferTooSmall = 2;
const int badMessageVersion = 3;
const int badMessageFormat = 4;
const int badMessageMac = 5;
const int badMessageKeyId = 6;
const int invalidBase64 = 7;
const int badAccountKey = 8;
const int unknownPickleVersion = 9;
const int corruptedPickle = 10;
const int badSessionKey = 11;
const int unknownMessageIndex = 12;
const int badLegacyAccountPickle = 13;
const int badSignature = 14;
const int inputBufferTooSmall = 15;
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'dart:convert';
import 'dart:ffi';
import 'dart:typed_data';
import 'package:matrix_sdk/src/encryption/account.dart';
import 'package:matrix_sdk/src/encryption/ffi/bindings.dart' hide Error;
import '../olm.dart';
/// Implementation of `libolm` via FFI. C code is called directly.
class OlmFFI implements Olm {
final OlmBindings olm;
/// Will look for a appropriate file (e.g. `libolm.so` on Linux,
/// but `olm.dll` on Windows) in [libraryPath].
OlmFFI({String libraryPath}) : olm = OlmBindings(path: libraryPath);
void _throwIfError(int result) {
if (result != olm.error()) {
return;
}
// TODO: Throw from error, must be per resource type
}
String _pointerToString(Pointer<Uint8> pointer, int length) {
var str = '';
for (int i = 0; i < length; i++) {
str += String.fromCharCode(pointer.elementAt(i).load());
}
return str;
}
Account account() {
// Reuse result from calls which can return error codes.
var result;
// Create pointer.
final accountSize = olm.accountSize();
final memory = allocate<Uint8>(count: accountSize);
final accountPointer = olm.account(memory);
// Initialize random memory.
final randomMemorySize = olm.createAccountRandomLength(accountPointer);
final randomMemory = allocate<Uint8>(
count: randomMemorySize,
);
// Create account.
// TODO: Check result for errors
result = olm.createAccount(accountPointer, randomMemory, randomMemorySize);
_throwIfError(result);
// Create identity keys pointer.
final identityKeysSize = olm.accountIdentityKeysLength(accountPointer);
final identityKeysPointer = allocate<Uint8>(
count: identityKeysSize,
);
result = olm.accountIdentityKeys(
accountPointer,
identityKeysPointer,
identityKeysSize,
);
_throwIfError(result);
final keys = IdentityKeys.fromJson(json.decode(_pointerToString(
identityKeysPointer,
identityKeysSize,
)));
return Account(keys);
}
}
// Errors and exceptions.
// Which classes are errors and which are exceptions may change while pre-1.0.
class NotEnoughRandomError extends Error {}
class OutputBufferTooSmallError extends Error {}
class BadMessageVersionException implements Exception {}
class BadMessageFormatException implements Exception {}
class BadMessageMacException implements Exception {}
class BadMessageKeyIdException implements Exception {}
class InvalidBase64Error extends Error {}
class BadAccountKeyException implements Exception {}
class CorruptedPickleException implements Exception {}
class BadSessionKeyError extends Error {}
class BadLegacyAccountPickleException implements Exception {}
class BadSignatureException implements Exception {}
class InputBufferTooSmallError extends Error {}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'package:matrix_sdk/src/encryption/account.dart';
/// Interface of `libolm`.
///
/// Implement this class to provide a `libolm` implementation.
///
/// See
abstract class Olm {
Account account();
}
......@@ -33,6 +33,8 @@ import 'package:kiwi/kiwi.dart';
import 'package:url/url.dart';
import 'package:meta/meta.dart';
import 'device.dart';
/// Represents a Matrix homeserver. Also used as the main entry point
/// of the SDK.
class Homeserver {
......@@ -122,15 +124,14 @@ class Homeserver {
UserIdentifier user,
String password, {
@required Store store,
String deviceId,
String deviceName,
Device device,
}) async {
final response = await _client.login(json.encode({
'type': 'm.login.password',
'identifier': user.toIdentifierJson(),
'password': password,
'device_id': deviceId,
'initial_device_display_name': deviceName,
'device_id': device?.id?.toString(),
'initial_device_display_name': device?.name,
}));
final body = json.decode(response.body);
......@@ -138,11 +139,18 @@ class Homeserver {
String accessToken = body['access_token'];
final userId = UserId(body['user_id']);
// If device was null,
// create one with the id from the repsonse
if (device == null) {
device = Device(id: DeviceId(body['device_id']));
}
final localUser = LocalUser(
id: userId,
store: store,
homeserver: this,
accessToken: accessToken,
currentDevice: device,
httpClient: _httpClient,
);
......
......@@ -20,11 +20,20 @@ import 'package:validators/validators.dart';
import 'package:matrix_sdk/src/store.dart';
/// A Matrix identifier.
abstract class Id {
final String value;
Id._(this.sigil, this.value, {bool validate = true}) {
Id(this.value);
@override
String toString() => value;
String toJson() => toString();
}
/// A Matrix identifier.
abstract class MatrixId extends Id {
MatrixId._(this.sigil, String value, {bool validate = true}) : super(value) {
if (validate && !_isValidFullyQualified(value, sigil)) {
throw ArgumentError.value(value, 'value',
'Must be in format of: ${sigil}localpart${seperator}server.tld');
......@@ -55,8 +64,6 @@ abstract class Id {
int get hashCode => value.hashCode;
factory Id.user(String value) = UserId;
// Verification
static final _localPartRegex = RegExp('^[A-z0-9\\-.=_\\/]+\$');
......@@ -121,25 +128,26 @@ enum ValidId { no, local, full }
const _roomSigil = '!';
/// An internal room ID in the form `!something:server.tld`.
class RoomId extends Id implements JsonWritable {
class RoomId extends MatrixId implements JsonWritable {
RoomId(String value) : super._(_roomSigil, value);
/// Checks whether the given string is a valid
/// local part of a room id.
///
/// Must match the regex `[a-z0-9\\-.=_\\/]+`
static bool isValidLocalPart(String input) => Id.isValidLocalPart(input);
static bool isValidLocalPart(String input) =>
MatrixId.isValidLocalPart(input);
/// Checks whether the given string is a valid
/// fully qualified user id, must be in the form of:
/// `!localpart:server.tld`.
static bool isValidFullyQualified(String input) =>
Id._isValidFullyQualified(input, _roomSigil);
MatrixId._isValidFullyQualified(input, _roomSigil);
/// Checks whether the given string is either a valid localpart (returns
/// [ValidId.local]), a valid fully qualified room id (returns
/// [ValidId.full]) or that it's not a valid id (returns [ValidId.no]).
static ValidId isValid(String input) => Id._isValid(input, _roomSigil);
static ValidId isValid(String input) => MatrixId._isValid(input, _roomSigil);
String toJson() => toString();
}
......@@ -147,7 +155,7 @@ class RoomId extends Id implements JsonWritable {
const _eventSigil = '\$';
/// An event ID in the form `$12323:server.tld`.
class EventId extends Id implements JsonWritable {
class EventId extends MatrixId implements JsonWritable {
EventId(String value) : super._(_eventSigil, value, validate: false);
String toJson() => toString();
......@@ -156,7 +164,7 @@ class EventId extends Id implements JsonWritable {
const _userSigil = '@';
/// A Matrix ID in the form `@username:server.tld`.
class UserId extends Id implements UserIdentifier, JsonWritable {
class UserId extends MatrixId implements UserIdentifier, JsonWritable {
UserId(String value) : super._(_userSigil, value);
/// The [Username] of this ID, so in the case of `@joe:matrix.org`:
......@@ -169,18 +177,19 @@ class UserId extends Id implements UserIdentifier, JsonWritable {
/// local part of a user identifier.
///
/// Must match the regex `[a-z0-9\\-.=_\\/]+`
static bool isValidLocalPart(String input) => Id.isValidLocalPart(input);
static bool isValidLocalPart(String input) =>
MatrixId.isValidLocalPart(input);
/// Checks whether the given string is a valid
/// fully qualified user id, must be in the form of:
/// `@localpart:server.tld`.
static bool isValidFullyQualified(String input) =>
Id._isValidFullyQualified(input, _userSigil);
MatrixId._isValidFullyQualified(input, _userSigil);
/// Checks whether the given string is either a valid localpart (returns
/// [ValidId.local]), a valid fully qualified user id (returns
/// [ValidId.full]) or that it's not a valid id (returns [ValidId.no]).
static ValidId isValid(String input) => Id._isValid(input, _userSigil);
static ValidId isValid(String input) => MatrixId._isValid(input, _userSigil);
String toJson() => toString();
......@@ -206,7 +215,7 @@ class Username implements UserIdentifier, JsonWritable {
final String value;
Username(this.value) {
if (!Id.isValidLocalPart(value)) {
if (!MatrixId.isValidLocalPart(value)) {
// throw
}
}
......@@ -225,12 +234,7 @@ class Username implements UserIdentifier, JsonWritable {
/// username.
///
/// Must match the regex `[a-z0-9\\-.=_\\/]+`
static bool isValid(String input) => Id.isValidLocalPart(input);
@override
String toString() => value;
String toJson() => toString();
static bool isValid(String input) => MatrixId.isValidLocalPart(input);
/// Return this object represented as a user identifier, in the form
/// of
......@@ -247,6 +251,9 @@ class Username implements UserIdentifier, JsonWritable {
'user': '$value',
};
}
@override
dynamic toJson() => value;
}
/// Not to be confused with [UserId], the [UserIdentifier]
......
......@@ -22,6 +22,7 @@ import 'package:matrix_sdk/src/identifier.dart';
import 'package:matrix_sdk/src/room/room.dart';
import 'package:matrix_sdk/src/user.dart';
import 'device.dart';
import 'event/event.dart';
/// Stores all data (rooms, users, events) somewhere.
......@@ -45,6 +46,9 @@ abstract class Store {
Future<Homeserver> getHomeserver();
Future<void> setHomeserver(Homeserver value);
Future<Device> getCurrentDevice();
Future<Device> setCurrentDevice(Device device);
Future<Room> getRoom(RoomId id);
Future<void> setRooms(Iterable<Room> rooms);
......@@ -109,6 +113,10 @@ class MemoryStore implements Store {
Future<Homeserver> getHomeserver() async => homeserver;
Future<void> setHomeserver(Homeserver value) async => homeserver = value;
Device device;
Future<Device> getCurrentDevice() async => device;
Future<Device> setCurrentDevice(Device device) async => this.device = device;
final rooms = Map<RoomId, Room>();
Future<Room> getRoom(RoomId id) async => rooms[id];
Future<void> setRooms(Iterable<Room> rooms) async {
......
......@@ -34,6 +34,8 @@ import 'package:meta/meta.dart';
import 'package:url/url.dart';
import 'package:http/http.dart' as http;
import 'device.dart';
class UserState implements Comparable<UserState> {
UserId _userId;
......@@ -113,6 +115,8 @@ class LocalUser extends User {
Rooms _rooms;
Rooms get rooms => _rooms;
final Device currentDevice;
bool _isLoggedOut = false;
bool get isLoggedOut => _isLoggedOut;
......@@ -147,14 +151,25 @@ class LocalUser extends User {
return null;
}
final device = await store.getCurrentDevice();
if (device == null) {
return null;
}
return LocalUser(
id: userId, homeserver: hs, accessToken: accessToken, store: store);
id: userId,
homeserver: hs,
accessToken: accessToken,
store: store,
currentDevice: device,
);
}
LocalUser({
@required UserId id,
@required this.homeserver,
@required this.accessToken,
@required this.currentDevice,
@required Store store,
http.Client httpClient,
}) : _chopper = createChopper(
......
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'dart:convert';
import 'package:http/http.dart';
import 'package:http/testing.dart';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:test/test.dart';
import 'package:url/url.dart';
void testHomeserver() {
group('Homeserver', () {
group('.login ', () {
test('returns LocalUser if successful', () async {
final hs = Homeserver(
Url.parse('https://pattle.im'),
httpClient: MockClient((request) async {
return Response(
json.encode({
'user_id': '@pat:pattle.im',
'access_token': 'abc123',
'device_id': 'GHTYAJCE',
'well_known': {
'm.homeserver': {
'base_url': 'https://pattle.im',
},
'm.identity_server': {
'base_url': 'https://id.pattle.im',
},
},
}),
200,
);
}),
);
final user = await hs.login(
Username('pat'),
'password',
store: MemoryStore(),
);
expect(user, isNotNull);
expect(user.id.toString(), matches('@pat:pattle.im'));
expect(user.accessToken, equals('abc123'));
});
test('returns LocalUser with given device id if none given', () async {
final hs = Homeserver(
Url.parse('https://pattle.im'),
httpClient: MockClient((request) async {
return Response(
json.encode({
'user_id': '@pat:pattle.im',
'access_token': 'abc123',
'device_id': 'GHTYAJCE',
'well_known': {
'm.homeserver': {
'base_url': 'https://pattle.im',
},
'm.identity_server': {
'base_url': 'https://id.pattle.im',
},
},
}),
200,
);
}),
);
final user = await hs.login(
Username('pat'),
'password',
store: MemoryStore(),
);
expect(user.currentDevice.id.toString(), equals('GHTYAJCE'));
});
test('returns LocalUser with set device id by caller', () async {
final hs = Homeserver(
Url.parse('https://pattle.im'),
httpClient: MockClient((request) async {
return Response(
json.encode({
'user_id': '@pat:pattle.im',
'access_token': 'abc123',
'device_id': 'GHTYAJCE',
'well_known': {
'm.homeserver': {
'base_url': 'https://pattle.im',
},
'm.identity_server': {
'base_url': 'https://id.pattle.im',
},
},
}),
200,
);
}),
);
final user = await hs.login(
Username('pat'),
'password',
store: MemoryStore(),
device: Device(
id: DeviceId('BLABLA'),
name: 'Pattle Android',
),
);
expect(user.currentDevice.id.toString(), equals('BLABLA'));
expect(user.currentDevice.name, equals('Pattle Android'));
});
test('throws ForbiddenException if password is wrong', () async {
final hs = Homeserver(
Url.parse('https://pattle.im'),
httpClient: MockClient((request) async {
return Response(
json.encode({'errcode': 'M_FORBIDDEN'}),
403,
);
}),
);
expect(
hs.login(
Username('pat'),
'password',
store: MemoryStore(),
),
throwsA(isA<ForbiddenException>()),
);
});
});
});
// TODO: Handle 400
}
......@@ -19,6 +19,7 @@ import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:test/test.dart';
import 'homeserver_test.dart';
import 'olm_test.dart';
void main() {
group('Identifier validity', () {
......@@ -46,5 +47,6 @@ void main() {
});
});
testOlm();
testHomeserver();
}
// Copyright (C) 2019 Wilko Manger
//
// This file is part of matrix-dart-sdk.
//
// matrix-dart-sdk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// matrix-dart-sdk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with matrix-dart-sdk. If not, see <https://www.gnu.org/licenses/>.
import 'dart:io';
import 'package:matrix_sdk/matrix_sdk.dart';
import 'package:matrix_sdk/olm_ffi.dart';
import 'package:test/test.dart';
void testOlm() {
group('Olm', () {
group('.account ', () {
test('returns Account if successful', () async {
Olm olm = OlmFFI(
libraryPath: '${Directory.current.path}/lib-native/x86_64/',
);
final account = olm.account();
expect(account.identityKeys.curve25519, isNotNull);
expect(account.identityKeys.ed25519, isNotNull);
});
});
});
}