From fe87978d45d60f3684e44e2f69c38c2b2cd51866 Mon Sep 17 00:00:00 2001 From: Gbogboade Ayomide Date: Thu, 25 Apr 2024 16:00:11 +0100 Subject: [PATCH] feat: add profile high level sdk --- Sources/PushAPI/Chat.swift | 40 ++++++++++++++ Sources/PushAPI/Profile.swift | 31 +++++++++++ Sources/PushAPI/PushAPI.swift | 89 ++++++++++++++++++++++++++++++++ Tests/PushAPI/ChatTests.swift | 24 +++++++++ Tests/PushAPI/PushAPITests.swift | 42 +++++++++++++++ 5 files changed, 226 insertions(+) create mode 100644 Sources/PushAPI/Chat.swift create mode 100644 Sources/PushAPI/Profile.swift create mode 100644 Sources/PushAPI/PushAPI.swift create mode 100644 Tests/PushAPI/ChatTests.swift create mode 100644 Tests/PushAPI/PushAPITests.swift diff --git a/Sources/PushAPI/Chat.swift b/Sources/PushAPI/Chat.swift new file mode 100644 index 0000000..182bcae --- /dev/null +++ b/Sources/PushAPI/Chat.swift @@ -0,0 +1,40 @@ +public struct Chat { + private var account: String + private var decryptedPgpPvtKey: String + private var env: ENV + + init( + account: String, + decryptedPgpPvtKey: String, + env: ENV + ) { + self.account = account + self.decryptedPgpPvtKey = decryptedPgpPvtKey + self.env = env + } + + public func list(type: ChatListType, page: Int = 1, limit: Int = 10, overrideAccount: String? = nil) async throws -> [PushChat.Feeds] { + if type == .CHAT { + let options = PushChat.GetChatsOptions( + account: account, + pgpPrivateKey: decryptedPgpPvtKey, + page: page, limit: limit, env: env) + + return try await PushChat.getChats( + options: options + ) + + } else { + let options = PushChat.RequestOptionsType( + account: account, + pgpPrivateKey: decryptedPgpPvtKey, + page: page, limit: limit, env: env) + return try await PushChat.requests(options: options) + } + } +} + +public enum ChatListType { + case CHAT + case REQUESTS +} diff --git a/Sources/PushAPI/Profile.swift b/Sources/PushAPI/Profile.swift new file mode 100644 index 0000000..3d319e9 --- /dev/null +++ b/Sources/PushAPI/Profile.swift @@ -0,0 +1,31 @@ +import Foundation + +public struct Profile { + private var account: String + private var decryptedPgpPvtKey: String + private var env: ENV + + init( + account: String, + decryptedPgpPvtKey: String, + env: ENV + ) { + self.account = account + self.decryptedPgpPvtKey = decryptedPgpPvtKey + self.env = env + } + + public func info(overrideAccount: String? = nil) async throws -> PushUser? { + return try? await PushUser.get(account: overrideAccount ?? account, env: env) + } + + public func update(name: String? = nil, desc: String? = nil, picture: String? = nil) async throws { + let info = try? await info() + var profile = info!.profile + profile.name = name ?? profile.name + profile.desc = desc ?? profile.desc + profile.picture = picture ?? profile.picture + + try await PushUser.updateUserProfile(account: account, pgpPrivateKey: decryptedPgpPvtKey, newProfile: profile, env: env) + } +} diff --git a/Sources/PushAPI/PushAPI.swift b/Sources/PushAPI/PushAPI.swift new file mode 100644 index 0000000..188d9f8 --- /dev/null +++ b/Sources/PushAPI/PushAPI.swift @@ -0,0 +1,89 @@ +import Foundation + +public struct PushAPI { + private var env: ENV + private var account: String + private var readMode: Bool + private var decryptedPgpPvtKey: String + private var pgpPublicKey: String? + private var signer: Signer + + public var chat: Chat + public var profile: Profile + + init(env: ENV, + account: String, + readMode: Bool, + decryptedPgpPvtKey: String, + pgpPublicKey: String?, + signer: Signer) { + self.env = env + self.account = account + self.readMode = readMode + self.decryptedPgpPvtKey = decryptedPgpPvtKey + self.pgpPublicKey = pgpPublicKey + self.signer = signer + + chat = Chat(account: account, decryptedPgpPvtKey: decryptedPgpPvtKey, env: env) + profile = Profile(account: account, decryptedPgpPvtKey: decryptedPgpPvtKey, env: env) + } + + public static func initializePush(signer: Signer, options: PushAPIInitializeOptions) async throws -> PushAPI { + // Get account + // Derives account from signer if not provided + let derivedAccount = try await signer.getAddress() + + var decryptedPGPPrivateKey: String? + var pgpPublicKey: String? + + /** + * Decrypt PGP private key + * If user exists, decrypts the PGP private key + * If user does not exist, creates a new user and returns the decrypted PGP private key + */ + if let user = try await PushUser.get(account: derivedAccount, env: options.env) { + decryptedPGPPrivateKey = try await PushUser.DecryptPGPKey(encryptedPrivateKey: user.encryptedPrivateKey, signer: signer) + pgpPublicKey = user.publicKey + } else { + let newUser = try await PushUser.create( + options: PushUser.CreateUserOptions( + env: options.env, + signer: signer, + progressHook: nil + )) + + decryptedPGPPrivateKey = try await PushUser.DecryptPGPKey(encryptedPrivateKey: newUser.encryptedPrivateKey, signer: signer) + pgpPublicKey = newUser.publicKey + } + + return PushAPI(env: options.env, + account: derivedAccount, + readMode: true, + decryptedPgpPvtKey: decryptedPGPPrivateKey!, + pgpPublicKey: pgpPublicKey, + signer: signer) + } +} + +extension PushAPI { + public struct PushAPIInitializeOptions { + var env: ENV + var version: ENCRYPTION_TYPE + var versionMeta: [String: [String: String]]? + var autoUpgrade: Bool + var origin: String? + + public init( + env: ENV = .PROD, + version: ENCRYPTION_TYPE = .PGP_V3, + versionMeta: [String: [String: String]]? = nil, + autoUpgrade: Bool = true, + origin: String? = nil) { + self.env = env + self.version = version + self.versionMeta = versionMeta + self.autoUpgrade = autoUpgrade + self.origin = origin + } + } +} diff --git a/Tests/PushAPI/ChatTests.swift b/Tests/PushAPI/ChatTests.swift new file mode 100644 index 0000000..e12a876 --- /dev/null +++ b/Tests/PushAPI/ChatTests.swift @@ -0,0 +1,24 @@ +import Push +import XCTest + +class ChatTests: XCTestCase { + + func testChatLists() async throws { + let userPk = getRandomAccount() + let signer = try SignerPrivateKey(privateKey: userPk) + + let pushAPI = try await PushAPI + .initializePush( + signer: signer, + options: PushAPI.PushAPIInitializeOptions() + ) + + let requests = try await pushAPI.chat.list(type: .REQUESTS) + XCTAssertEqual(requests.count, 0) + + + let chats = try await pushAPI.chat.list(type: .CHAT) + XCTAssertEqual(chats.count, 0) + } +} + diff --git a/Tests/PushAPI/PushAPITests.swift b/Tests/PushAPI/PushAPITests.swift new file mode 100644 index 0000000..aa5b456 --- /dev/null +++ b/Tests/PushAPI/PushAPITests.swift @@ -0,0 +1,42 @@ +import Push +import XCTest + +class PushAPITests: XCTestCase { + func testInitialize() async throws { + let userPk = getRandomAccount() + let signer = try SignerPrivateKey(privateKey: userPk) + let address = try await signer.getAddress() + + let pushAPI = try await PushAPI + .initializePush( + signer: signer, + options: PushAPI.PushAPIInitializeOptions() + ) + + let user = try await pushAPI.profile.info() + + XCTAssertEqual(user?.did, "eip155:\(address)") + } + + func testProfileUpdate() async throws { + let userPk = getRandomAccount() + let signer = try SignerPrivateKey(privateKey: userPk) + let address = try await signer.getAddress() + + let pushAPI = try await PushAPI + .initializePush( + signer: signer, + options: PushAPI.PushAPIInitializeOptions() + ) + + let newName = "Push Swift" + + try await pushAPI.profile.update(name: newName, desc: "Push Swift Tester") + + let user = try await pushAPI.profile.info() + + XCTAssertEqual(user?.profile.name, newName) + } + + +}