From e0d509179de8b59f982213eeed228c9a61473f5c Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Thu, 19 Sep 2024 23:52:01 -0600 Subject: [PATCH] get the first test passing --- Sources/XMTPTestHelpers/TestHelpers.swift | 2 +- Sources/XMTPiOS/Client.swift | 5 +- Sources/XMTPiOS/Contacts.swift | 193 +++++++++++----------- Sources/XMTPiOS/ConversationV1.swift | 15 +- Sources/XMTPiOS/ConversationV2.swift | 12 +- Sources/XMTPiOS/Conversations.swift | 22 ++- Sources/XMTPiOS/Frames/FramesClient.swift | 4 +- Sources/XMTPiOS/Messages/MessageV2.swift | 4 +- Tests/XMTPTests/ClientTests.swift | 28 ++-- Tests/XMTPTests/ConversationTests.swift | 8 +- Tests/XMTPTests/ConversationsTest.swift | 2 +- Tests/XMTPTests/IntegrationTests.swift | 8 +- 12 files changed, 166 insertions(+), 137 deletions(-) diff --git a/Sources/XMTPTestHelpers/TestHelpers.swift b/Sources/XMTPTestHelpers/TestHelpers.swift index e6d9a940..d9a43f26 100644 --- a/Sources/XMTPTestHelpers/TestHelpers.swift +++ b/Sources/XMTPTestHelpers/TestHelpers.swift @@ -88,7 +88,7 @@ public struct Fixtures { public func publishLegacyContact(client: Client) async throws { var contactBundle = ContactBundle() - contactBundle.v1.keyBundle = client.privateKeyBundleV1.toPublicKeyBundle() + contactBundle.v1.keyBundle = try client.v1keys.toPublicKeyBundle() var envelope = Envelope() envelope.contentTopic = Topic.contact(client.address).description diff --git a/Sources/XMTPiOS/Client.swift b/Sources/XMTPiOS/Client.swift index ec4de35a..e0da501d 100644 --- a/Sources/XMTPiOS/Client.swift +++ b/Sources/XMTPiOS/Client.swift @@ -114,8 +114,8 @@ public struct ClientOptions { public final class Client { /// The wallet address of the ``SigningKey`` used to create this Client. public let address: String - let privateKeyBundleV1: PrivateKeyBundleV1? - let apiClient: ApiClient? + var privateKeyBundleV1: PrivateKeyBundleV1? = nil + var apiClient: ApiClient? = nil public let v3Client: LibXMTP.FfiXmtpClient? public let libXMTPVersion: String = getVersionInfo() public let dbPath: String @@ -191,6 +191,7 @@ public final class Client { for codec in (options.codecs) { client.register(codec: codec) } + return client } static func initV3Client( diff --git a/Sources/XMTPiOS/Contacts.swift b/Sources/XMTPiOS/Contacts.swift index 3f1d91f3..23d55358 100644 --- a/Sources/XMTPiOS/Contacts.swift +++ b/Sources/XMTPiOS/Contacts.swift @@ -58,63 +58,63 @@ public actor EntriesManager { public class ConsentList { public let entriesManager = EntriesManager() - var publicKey: Data - var privateKey: Data - var identifier: String? var lastFetched: Date? var client: Client init(client: Client) { self.client = client - privateKey = client.privateKeyBundleV1.identityKey.secp256K1.bytes - publicKey = client.privateKeyBundleV1.identityKey.publicKey.secp256K1Uncompressed.bytes - identifier = try? LibXMTP.generatePrivatePreferencesTopicIdentifier(privateKey: privateKey) } func load() async throws -> [ConsentListEntry] { - guard let identifier = identifier else { - throw ContactError.invalidIdentifier - } - let newDate = Date() - - let pagination = Pagination( - limit: 500, - after: lastFetched, - direction: .ascending - ) - let envelopes = try await client.apiClient.envelopes(topic: Topic.preferenceList(identifier).description, pagination: pagination) - lastFetched = newDate - - var preferences: [PrivatePreferencesAction] = [] - - for envelope in envelopes { - let payload = try LibXMTP.userPreferencesDecrypt(publicKey: publicKey, privateKey: privateKey, message: envelope.message) - - try preferences.append(PrivatePreferencesAction(serializedData: Data(payload))) - } - for preference in preferences { - for address in preference.allowAddress.walletAddresses { - _ = await allow(address: address) - } - - for address in preference.denyAddress.walletAddresses { - _ = await deny(address: address) - } - - for groupId in preference.allowGroup.groupIds { - _ = await allowGroup(groupId: groupId) - } - - for groupId in preference.denyGroup.groupIds { - _ = await denyGroup(groupId: groupId) + if (client.hasV2Client) { + let privateKey = try client.v1keys.identityKey.secp256K1.bytes + let publicKey = try client.v1keys.identityKey.publicKey.secp256K1Uncompressed.bytes + let identifier = try? LibXMTP.generatePrivatePreferencesTopicIdentifier(privateKey: privateKey) + + guard let identifier = identifier else { + throw ContactError.invalidIdentifier } + let newDate = Date() + + let pagination = Pagination( + limit: 500, + after: lastFetched, + direction: .ascending + ) + let envelopes = try await client.apiClient!.envelopes(topic: Topic.preferenceList(identifier).description, pagination: pagination) + lastFetched = newDate - for inboxId in preference.allowInboxID.inboxIds { - _ = await allowInboxId(inboxId: inboxId) + var preferences: [PrivatePreferencesAction] = [] + + for envelope in envelopes { + let payload = try LibXMTP.userPreferencesDecrypt(publicKey: publicKey, privateKey: privateKey, message: envelope.message) + + try preferences.append(PrivatePreferencesAction(serializedData: Data(payload))) } - - for inboxId in preference.denyInboxID.inboxIds { - _ = await denyInboxId(inboxId: inboxId) + for preference in preferences { + for address in preference.allowAddress.walletAddresses { + _ = await allow(address: address) + } + + for address in preference.denyAddress.walletAddresses { + _ = await deny(address: address) + } + + for groupId in preference.allowGroup.groupIds { + _ = await allowGroup(groupId: groupId) + } + + for groupId in preference.denyGroup.groupIds { + _ = await denyGroup(groupId: groupId) + } + + for inboxId in preference.allowInboxID.inboxIds { + _ = await allowInboxId(inboxId: inboxId) + } + + for inboxId in preference.denyInboxID.inboxIds { + _ = await denyInboxId(inboxId: inboxId) + } } } @@ -122,56 +122,61 @@ public class ConsentList { } func publish(entries: [ConsentListEntry]) async throws { - guard let identifier = identifier else { - throw ContactError.invalidIdentifier - } - var payload = PrivatePreferencesAction() - - for entry in entries { - switch entry.entryType { - case .address: - switch entry.consentType { - case .allowed: - payload.allowAddress.walletAddresses.append(entry.value) - case .denied: - payload.denyAddress.walletAddresses.append(entry.value) - case .unknown: - payload.messageType = nil - } - case .group_id: - switch entry.consentType { - case .allowed: - payload.allowGroup.groupIds.append(entry.value) - case .denied: - payload.denyGroup.groupIds.append(entry.value) - case .unknown: - payload.messageType = nil - } - case .inbox_id: - switch entry.consentType { - case .allowed: - payload.allowInboxID.inboxIds.append(entry.value) - case .denied: - payload.denyInboxID.inboxIds.append(entry.value) - case .unknown: - payload.messageType = nil + if (client.hasV2Client) { + let privateKey = try client.v1keys.identityKey.secp256K1.bytes + let publicKey = try client.v1keys.identityKey.publicKey.secp256K1Uncompressed.bytes + let identifier = try? LibXMTP.generatePrivatePreferencesTopicIdentifier(privateKey: privateKey) + guard let identifier = identifier else { + throw ContactError.invalidIdentifier } + var payload = PrivatePreferencesAction() + + for entry in entries { + switch entry.entryType { + case .address: + switch entry.consentType { + case .allowed: + payload.allowAddress.walletAddresses.append(entry.value) + case .denied: + payload.denyAddress.walletAddresses.append(entry.value) + case .unknown: + payload.messageType = nil + } + case .group_id: + switch entry.consentType { + case .allowed: + payload.allowGroup.groupIds.append(entry.value) + case .denied: + payload.denyGroup.groupIds.append(entry.value) + case .unknown: + payload.messageType = nil + } + case .inbox_id: + switch entry.consentType { + case .allowed: + payload.allowInboxID.inboxIds.append(entry.value) + case .denied: + payload.denyInboxID.inboxIds.append(entry.value) + case .unknown: + payload.messageType = nil + } + } + } + + let message = try LibXMTP.userPreferencesEncrypt( + publicKey: publicKey, + privateKey: privateKey, + message: payload.serializedData() + ) + + let envelope = Envelope( + topic: Topic.preferenceList(identifier), + timestamp: Date(), + message: Data(message) + ) + + try await client.publish(envelopes: [envelope]) } - } - - let message = try LibXMTP.userPreferencesEncrypt( - publicKey: publicKey, - privateKey: privateKey, - message: payload.serializedData() - ) - - let envelope = Envelope( - topic: Topic.preferenceList(identifier), - timestamp: Date(), - message: Data(message) - ) - - try await client.publish(envelopes: [envelope]) } func allow(address: String) async -> ConsentListEntry { diff --git a/Sources/XMTPiOS/ConversationV1.swift b/Sources/XMTPiOS/ConversationV1.swift index 2b187ded..8e62f037 100644 --- a/Sources/XMTPiOS/ConversationV1.swift +++ b/Sources/XMTPiOS/ConversationV1.swift @@ -52,7 +52,7 @@ public struct ConversationV1 { let date = sentAt let message = try MessageV1.encode( - sender: client.privateKeyBundleV1, + sender: client.v1keys, recipient: recipient, message: try encodedContent.serializedData(), timestamp: date @@ -217,8 +217,10 @@ public struct ConversationV1 { func decryptedMessages(limit: Int? = nil, before: Date? = nil, after: Date? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecryptedMessage] { let pagination = Pagination(limit: limit, before: before, after: after, direction: direction) - - let envelopes = try await client.apiClient.envelopes( + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } + let envelopes = try await apiClient.envelopes( topic: Topic.directMessageV1(client.address, peerAddress).description, pagination: pagination ) @@ -229,7 +231,10 @@ public struct ConversationV1 { func messages(limit: Int? = nil, before: Date? = nil, after: Date? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecodedMessage] { let pagination = Pagination(limit: limit, before: before, after: after, direction: direction) - let envelopes = try await client.apiClient.envelopes( + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } + let envelopes = try await apiClient.envelopes( topic: Topic.directMessageV1(client.address, peerAddress).description, pagination: pagination ) @@ -246,7 +251,7 @@ public struct ConversationV1 { func decrypt(envelope: Envelope) throws -> DecryptedMessage { let message = try Message(serializedData: envelope.message) - let decrypted = try message.v1.decrypt(with: client.privateKeyBundleV1) + let decrypted = try message.v1.decrypt(with: client.v1keys) let encodedMessage = try EncodedContent(serializedData: decrypted) let header = try message.v1.header diff --git a/Sources/XMTPiOS/ConversationV2.swift b/Sources/XMTPiOS/ConversationV2.swift index 86c81974..cb479b2e 100644 --- a/Sources/XMTPiOS/ConversationV2.swift +++ b/Sources/XMTPiOS/ConversationV2.swift @@ -37,7 +37,7 @@ public struct ConversationV2 { private var header: SealedInvitationHeaderV1 static func create(client: Client, invitation: InvitationV1, header: SealedInvitationHeaderV1) throws -> ConversationV2 { - let myKeys = client.keys.getPublicKeyBundle() + let myKeys = try client.keys.getPublicKeyBundle() let peer = try myKeys.walletAddress == (try header.sender.walletAddress) ? header.recipient : header.sender let peerAddress = try peer.walletAddress @@ -133,7 +133,10 @@ public struct ConversationV2 { func messages(limit: Int? = nil, before: Date? = nil, after: Date? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecodedMessage] { let pagination = Pagination(limit: limit, before: before, after: after, direction: direction) - let envelopes = try await client.apiClient.envelopes(topic: topic.description, pagination: pagination) + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } + let envelopes = try await apiClient.envelopes(topic: topic.description, pagination: pagination) return envelopes.compactMap { envelope in do { @@ -146,8 +149,11 @@ public struct ConversationV2 { } func decryptedMessages(limit: Int? = nil, before: Date? = nil, after: Date? = nil, direction: PagingInfoSortDirection? = .descending) async throws -> [DecryptedMessage] { + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } let pagination = Pagination(limit: limit, before: before, after: after, direction: direction) - let envelopes = try await client.apiClient.envelopes(topic: topic.description, pagination: pagination) + let envelopes = try await apiClient.envelopes(topic: topic.description, pagination: pagination) return try envelopes.map { envelope in try decrypt(envelope: envelope) diff --git a/Sources/XMTPiOS/Conversations.swift b/Sources/XMTPiOS/Conversations.swift index f35637c7..04c70cee 100644 --- a/Sources/XMTPiOS/Conversations.swift +++ b/Sources/XMTPiOS/Conversations.swift @@ -296,8 +296,11 @@ public actor Conversations { .map { requests in BatchQueryRequest.with { $0.requests = requests } } var messages: [DecodedMessage] = [] // TODO: consider using a task group here for parallel batch calls + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } for batch in batches { - messages += try await client.apiClient.batchQuery(request: batch) + messages += try await apiClient.batchQuery(request: batch) .responses.flatMap { res in res.envelopes.compactMap { envelope in let conversation = conversationsByTopic[envelope.contentTopic] @@ -327,8 +330,11 @@ public actor Conversations { .map { requests in BatchQueryRequest.with { $0.requests = requests } } var messages: [DecryptedMessage] = [] // TODO: consider using a task group here for parallel batch calls + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } for batch in batches { - messages += try await client.apiClient.batchQuery(request: batch) + messages += try await apiClient.batchQuery(request: batch) .responses.flatMap { res in res.envelopes.compactMap { envelope in let conversation = conversationsByTopic[envelope.contentTopic] @@ -833,7 +839,10 @@ public actor Conversations { } private func listIntroductionPeers(pagination: Pagination?) async throws -> [String: Date] { - let envelopes = try await client.apiClient.query( + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } + let envelopes = try await apiClient.query( topic: .userIntro(client.address), pagination: pagination ).envelopes @@ -841,7 +850,7 @@ public actor Conversations { do { let message = try MessageV1.fromBytes(envelope.message) // Attempt to decrypt, just to make sure we can - _ = try message.decrypt(with: client.privateKeyBundleV1) + _ = try message.decrypt(with: client.v1keys) return message } catch { return nil @@ -867,7 +876,10 @@ public actor Conversations { } private func listInvitations(pagination: Pagination?) async throws -> [SealedInvitation] { - var envelopes = try await client.apiClient.envelopes( + guard let apiClient = client.apiClient else { + throw ClientError.noV2Client("Error no V2 client initialized") + } + var envelopes = try await apiClient.envelopes( topic: Topic.userInvite(client.address).description, pagination: pagination ) diff --git a/Sources/XMTPiOS/Frames/FramesClient.swift b/Sources/XMTPiOS/Frames/FramesClient.swift index e234e53b..0fea2726 100644 --- a/Sources/XMTPiOS/Frames/FramesClient.swift +++ b/Sources/XMTPiOS/Frames/FramesClient.swift @@ -62,14 +62,14 @@ public class FramesClient { } private func signDigest(digest: Data) async throws -> Signature { - let key = self.xmtpClient.keys.identityKey + let key = try self.xmtpClient.keys.identityKey let privateKey = try PrivateKey(key) let signature = try await privateKey.sign(Data(digest)) return signature } private func getPublicKeyBundle() async throws -> PublicKeyBundle { - let bundleBytes = self.xmtpClient.publicKeyBundle; + let bundleBytes = try self.xmtpClient.publicKeyBundle; return try PublicKeyBundle(bundleBytes); } diff --git a/Sources/XMTPiOS/Messages/MessageV2.swift b/Sources/XMTPiOS/Messages/MessageV2.swift index 66e1816f..3e5d0090 100644 --- a/Sources/XMTPiOS/Messages/MessageV2.swift +++ b/Sources/XMTPiOS/Messages/MessageV2.swift @@ -88,10 +88,10 @@ extension MessageV2 { let headerBytes = try header.serializedData() let digest = SHA256.hash(data: headerBytes + payload) - let preKey = client.keys.preKeys[0] + let preKey = try client.keys.preKeys[0] let signature = try await preKey.sign(Data(digest)) - let bundle = client.privateKeyBundleV1.toV2().getPublicKeyBundle() + let bundle = try client.v1keys.toV2().getPublicKeyBundle() let signedContent = SignedContent(payload: payload, sender: bundle, signature: signature) let signedBytes = try signedContent.serializedData() diff --git a/Tests/XMTPTests/ClientTests.swift b/Tests/XMTPTests/ClientTests.swift index 362da66d..43599ffe 100644 --- a/Tests/XMTPTests/ClientTests.swift +++ b/Tests/XMTPTests/ClientTests.swift @@ -50,7 +50,7 @@ class ClientTests: XCTestCase { ) ) - let keys = client.privateKeyBundle + let keys = try client.privateKeyBundle let otherClient = try await Client.from( bundle: keys, options: .init( @@ -204,9 +204,9 @@ class ClientTests: XCTestCase { let fakeWallet = try PrivateKey.generate() let client = try await Client.create(account: fakeWallet, options: opts) - XCTAssertEqual(1, client.privateKeyBundleV1.preKeys.count) + XCTAssertEqual(1, try client.v1keys.preKeys.count) - let preKey = client.privateKeyBundleV1.preKeys[0] + let preKey = try client.v1keys.preKeys[0] XCTAssert(preKey.publicKey.hasSignature, "prekey not signed") } @@ -216,12 +216,12 @@ class ClientTests: XCTestCase { let fakeWallet = try PrivateKey.generate() let client = try await Client.create(account: fakeWallet) - let bundle = client.privateKeyBundle + let bundle = try client.privateKeyBundle let clientFromV1Bundle = try await Client.from(bundle: bundle) XCTAssertEqual(client.address, clientFromV1Bundle.address) - XCTAssertEqual(client.privateKeyBundleV1.identityKey, clientFromV1Bundle.privateKeyBundleV1.identityKey) - XCTAssertEqual(client.privateKeyBundleV1.preKeys, clientFromV1Bundle.privateKeyBundleV1.preKeys) + XCTAssertEqual(try client.v1keys.identityKey, try clientFromV1Bundle.v1keys.identityKey) + XCTAssertEqual(try client.v1keys.preKeys, try clientFromV1Bundle.v1keys.preKeys) } func testCanBeCreatedWithV1Bundle() async throws { @@ -229,20 +229,20 @@ class ClientTests: XCTestCase { let fakeWallet = try PrivateKey.generate() let client = try await Client.create(account: fakeWallet) - let bundleV1 = client.v1keys + let bundleV1 = try client.v1keys let clientFromV1Bundle = try await Client.from(v1Bundle: bundleV1) XCTAssertEqual(client.address, clientFromV1Bundle.address) - XCTAssertEqual(client.privateKeyBundleV1.identityKey, clientFromV1Bundle.privateKeyBundleV1.identityKey) - XCTAssertEqual(client.privateKeyBundleV1.preKeys, clientFromV1Bundle.privateKeyBundleV1.preKeys) + XCTAssertEqual(try client.v1keys.identityKey, try clientFromV1Bundle.v1keys.identityKey) + XCTAssertEqual(try client.v1keys.preKeys, try clientFromV1Bundle.v1keys.preKeys) } func testCanAccessPublicKeyBundle() async throws { let fakeWallet = try PrivateKey.generate() let client = try await Client.create(account: fakeWallet) - let publicKeyBundle = client.keys.getPublicKeyBundle() - XCTAssertEqual(publicKeyBundle, client.publicKeyBundle) + let publicKeyBundle = try client.keys.getPublicKeyBundle() + XCTAssertEqual(publicKeyBundle, try client.publicKeyBundle) } func testCanSignWithPrivateIdentityKey() async throws { @@ -254,7 +254,7 @@ class ClientTests: XCTestCase { let recovered = try KeyUtilx.recoverPublicKeyKeccak256(from: signature.rawData, message: Data("hello world".utf8)) - XCTAssertEqual(recovered, client.keys.identityKey.publicKey.secp256K1Uncompressed.bytes) + XCTAssertEqual(recovered, try client.keys.identityKey.publicKey.secp256K1Uncompressed.bytes) } func testPreEnableIdentityCallback() async throws { @@ -331,7 +331,7 @@ class ClientTests: XCTestCase { ) ) - let keys = client.privateKeyBundle + let keys = try client.privateKeyBundle let bundleClient = try await Client.from( bundle: keys, options: .init( @@ -467,7 +467,7 @@ class ClientTests: XCTestCase { let inboxId = try await Client.getOrCreateInboxId(options: options, address: alix.address) - let alixClient = try await Client.create( + let alixClient = try await Client.createOrBuild( account: alix, options: options ) diff --git a/Tests/XMTPTests/ConversationTests.swift b/Tests/XMTPTests/ConversationTests.swift index 04721db8..ea7ffb8e 100644 --- a/Tests/XMTPTests/ConversationTests.swift +++ b/Tests/XMTPTests/ConversationTests.swift @@ -145,7 +145,7 @@ class ConversationTests: XCTestCase { func publishLegacyContact(client: Client) async throws { var contactBundle = ContactBundle() - contactBundle.v1.keyBundle = client.privateKeyBundleV1.toPublicKeyBundle() + contactBundle.v1.keyBundle = try client.v1keys.toPublicKeyBundle() var envelope = Envelope() envelope.contentTopic = Topic.contact(client.address).description @@ -215,10 +215,10 @@ class ConversationTests: XCTestCase { let headerBytes = try header.serializedData() let digest = SHA256.hash(data: headerBytes + tamperedPayload) - let preKey = aliceClient.keys.preKeys[0] + let preKey = try aliceClient.keys.preKeys[0] let signature = try await preKey.sign(Data(digest)) - let bundle = aliceClient.privateKeyBundleV1.toV2().getPublicKeyBundle() + let bundle = try aliceClient.v1keys.toV2().getPublicKeyBundle() let signedContent = SignedContent(payload: originalPayload, sender: bundle, signature: signature) let signedBytes = try signedContent.serializedData() @@ -375,7 +375,7 @@ class ConversationTests: XCTestCase { try await bobConversation.send(content: "Hello") // Now we send some garbage and expect it to be properly ignored. - try await bobClient.apiClient.publish(envelopes: [ + try await bobClient.apiClient!.publish(envelopes: [ Envelope( topic: bobConversation.topic, timestamp: Date(), diff --git a/Tests/XMTPTests/ConversationsTest.swift b/Tests/XMTPTests/ConversationsTest.swift index a1c0823d..90325267 100644 --- a/Tests/XMTPTests/ConversationsTest.swift +++ b/Tests/XMTPTests/ConversationsTest.swift @@ -21,7 +21,7 @@ class ConversationsTests: XCTestCase { let created = Date() let message = try MessageV1.encode( - sender: fixtures.bobClient.privateKeyBundleV1, + sender: try fixtures.bobClient.v1keys, recipient: fixtures.aliceClient.v1keys.toPublicKeyBundle(), message: try TextCodec().encode(content: "hello", client: client).serializedData(), timestamp: created diff --git a/Tests/XMTPTests/IntegrationTests.swift b/Tests/XMTPTests/IntegrationTests.swift index 06a1231d..8cccdd17 100644 --- a/Tests/XMTPTests/IntegrationTests.swift +++ b/Tests/XMTPTests/IntegrationTests.swift @@ -52,7 +52,7 @@ final class IntegrationTests: XCTestCase { try await delayToPropagate() let contact = try await alice.getUserContact(peerAddress: alice.address) - XCTAssertEqual(contact!.v2.keyBundle.identityKey.secp256K1Uncompressed, alice.privateKeyBundleV1.identityKey.publicKey.secp256K1Uncompressed) + XCTAssertEqual(contact!.v2.keyBundle.identityKey.secp256K1Uncompressed, try alice.v1keys.identityKey.publicKey.secp256K1Uncompressed) XCTAssert(contact!.v2.keyBundle.identityKey.hasSignature == true, "no signature") XCTAssert(contact!.v2.keyBundle.preKey.hasSignature == true, "pre key not signed") @@ -474,7 +474,7 @@ final class IntegrationTests: XCTestCase { key.publicKey.secp256K1Uncompressed.bytes = Data(try LibXMTP.publicKeyFromPrivateKeyK256(privateKeyBytes: keyBytes)) let client = try await XMTPiOS.Client.create(account: key) - XCTAssertEqual(client.apiClient.environment, .dev) + XCTAssertEqual(client.environment, .dev) let conversations = try await client.conversations.list() XCTAssertEqual(1, conversations.count) @@ -542,7 +542,7 @@ final class IntegrationTests: XCTestCase { key.publicKey.secp256K1Uncompressed.bytes = Data(try LibXMTP.publicKeyFromPrivateKeyK256(privateKeyBytes: keyBytes)) let client = try await XMTPiOS.Client.create(account: key) - XCTAssertEqual(client.apiClient.environment, .dev) + XCTAssertEqual(client.environment, .dev) let convo = try await client.conversations.list()[0] let message = try await convo.messages()[0] @@ -565,7 +565,7 @@ final class IntegrationTests: XCTestCase { key.publicKey.secp256K1Uncompressed.bytes = Data(try LibXMTP.publicKeyFromPrivateKeyK256(privateKeyBytes: keyBytes)) let client = try await XMTPiOS.Client.create(account: key) - XCTAssertEqual(client.apiClient.environment, .dev) + XCTAssertEqual(client.environment, .dev) let convo = try await client.conversations.list()[0] let message = try await convo.messages().last!