From d5a7236f57c9f83196cd19930c803aeed1d8148b Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:28:33 +0100 Subject: [PATCH 1/5] Use new GRDB format --- Gem/App.swift | 1 + Gem/Connections/Scenes/ConnectionsScene.swift | 2 +- .../Sources/Requests/ConnectionsRequest.swift | 14 +++----------- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Gem/App.swift b/Gem/App.swift index c2adb23a..29dd28d2 100644 --- a/Gem/App.swift +++ b/Gem/App.swift @@ -20,6 +20,7 @@ struct GemApp: App { WalletCoordinator( db: db ) + .databaseContext(.readOnly { db.dbQueue }) .navigationBarTitleDisplayMode(.inline) .tint(Colors.blue) } diff --git a/Gem/Connections/Scenes/ConnectionsScene.swift b/Gem/Connections/Scenes/ConnectionsScene.swift index 1b72e587..9d933da4 100644 --- a/Gem/Connections/Scenes/ConnectionsScene.swift +++ b/Gem/Connections/Scenes/ConnectionsScene.swift @@ -32,7 +32,7 @@ struct ConnectionsScene: View { model: ConnectionsViewModel ) { self.model = model - _connections = Query(ConnectionsRequest(), in: \.db.dbQueue) + _connections = Query(ConnectionsRequest()) } var body: some View { diff --git a/Packages/Store/Sources/Requests/ConnectionsRequest.swift b/Packages/Store/Sources/Requests/ConnectionsRequest.swift index 9a414d75..907c3f05 100644 --- a/Packages/Store/Sources/Requests/ConnectionsRequest.swift +++ b/Packages/Store/Sources/Requests/ConnectionsRequest.swift @@ -6,21 +6,13 @@ import GRDBQuery import Combine import Primitives -public struct ConnectionsRequest: Queryable { +public struct ConnectionsRequest: ValueObservationQueryable { public static var defaultValue: [WalletConnection] { [] } public init() { } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[WalletConnection], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> [WalletConnection] { + + public func fetch(_ db: Database) throws -> [WalletConnection] { return try WalletRecord .including(required: WalletRecord.connection) .asRequest(of: WalletConnectionInfo.self) From 6f81a84ce8060fb4cbde8ad733d499b9617da13f Mon Sep 17 00:00:00 2001 From: gemdev111 Date: Mon, 2 Sep 2024 20:28:32 +0300 Subject: [PATCH 2/5] Connections frozen fixes by adding readwrite access --- Gem/App.swift | 2 +- Gem/Connections/Scenes/ConnectionsScene.swift | 3 +-- Gem/Wallet/Types/Environment.swift | 2 ++ core | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Gem/App.swift b/Gem/App.swift index 29dd28d2..bf9bdf75 100644 --- a/Gem/App.swift +++ b/Gem/App.swift @@ -20,7 +20,7 @@ struct GemApp: App { WalletCoordinator( db: db ) - .databaseContext(.readOnly { db.dbQueue }) + .databaseContext(.readWrite { db.dbQueue }) .navigationBarTitleDisplayMode(.inline) .tint(Colors.blue) } diff --git a/Gem/Connections/Scenes/ConnectionsScene.swift b/Gem/Connections/Scenes/ConnectionsScene.swift index 9d933da4..0bc2d27b 100644 --- a/Gem/Connections/Scenes/ConnectionsScene.swift +++ b/Gem/Connections/Scenes/ConnectionsScene.swift @@ -15,7 +15,7 @@ struct ConnectionsScene: View { @State private var isPresentingScanner: Bool = false @State private var isPresentingErrorMessage: String? - @Query + @Query(ConnectionsRequest()) var connections: [WalletConnection] var groupedByWallet: [Wallet: [Primitives.WalletConnection]] { @@ -32,7 +32,6 @@ struct ConnectionsScene: View { model: ConnectionsViewModel ) { self.model = model - _connections = Query(ConnectionsRequest()) } var body: some View { diff --git a/Gem/Wallet/Types/Environment.swift b/Gem/Wallet/Types/Environment.swift index 772847ea..3782c5da 100644 --- a/Gem/Wallet/Types/Environment.swift +++ b/Gem/Wallet/Types/Environment.swift @@ -7,6 +7,7 @@ import Store import Keystore import GemstonePrimitives +// TODO: - remove ref. https://swiftpackageindex.com/groue/grdbquery/0.9.0/documentation/grdbquery/migratingtogrdbquery09-unrestricted-writes struct DatabaseQueueKey: EnvironmentKey { static var defaultValue: DB { DB.main } } @@ -80,6 +81,7 @@ struct IsWalletPresentedServiceKey: EnvironmentKey { } extension EnvironmentValues { + // TODO: - remove ref. https://swiftpackageindex.com/groue/grdbquery/0.9.0/documentation/grdbquery/migratingtogrdbquery09-unrestricted-writes var db: DB { get { self[DatabaseQueueKey.self] } set { self[DatabaseQueueKey.self] = newValue } diff --git a/core b/core index e3bdc97b..5d7cb2bd 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit e3bdc97b6996ba9751184a60e781ffdcd0cd12cf +Subproject commit 5d7cb2bddcdfdd11293e7da0a52873ca4a9a6094 From 76aa4aeddbfdae2324b583755d964e5eab6941ad Mon Sep 17 00:00:00 2001 From: gemdev111 Date: Wed, 4 Sep 2024 17:17:37 +0300 Subject: [PATCH 3/5] Removed db from env Migrated requests from Queryable to ValueObservationQueryable Updates gem dependencies requests init --- Gem/Asset/AssetScene.swift | 6 +- Gem/Assets/Scenes/SelectAssetScene.swift | 6 +- Gem/Charts/Scenes/ChartScene.swift | 2 +- Gem/Connections/Scenes/ConnectionsScene.swift | 2 - Gem/Core/Coordinator/WalletCoordinator.swift | 1 - Gem/Core/Views/MainTabView.swift | 2 +- Gem/Stake/Scenes/StakeScene.swift | 3 +- Gem/Swap/Scenes/SwapScene.swift | 17 +++-- .../Scenes/TransactionScene.swift | 2 +- .../Scenes/TransactionsScene.swift | 4 +- Gem/Wallet/Scenes/WalletScene.swift | 12 ++- Gem/Wallet/Types/Environment.swift | 11 --- Gem/Wallets/Scenes/WalletsScene.swift | 5 +- .../Store/Sources/Requests/AssetRequest.swift | 27 +++---- .../Sources/Requests/AssetsInfoRequest.swift | 17 ++--- .../Sources/Requests/AssetsRequest.swift | 73 +++++++++---------- .../Sources/Requests/BannerRequest.swift | 22 ++---- .../Sources/Requests/ConnectionsRequest.swift | 5 +- .../Requests/StakeDelegationsRequest.swift | 22 ++---- .../Sources/Requests/TotalValueRequest.swift | 23 ++---- .../Requests/TransactionsCountRequest.swift | 15 +--- .../Requests/TransactionsRequest.swift | 46 ++++++------ .../Sources/Requests/WalletRequest.swift | 22 ++---- .../Sources/Requests/WalletsRequest.swift | 19 ++--- .../Sources/Types/AssetsRequestFilter.swift | 1 + .../Types/TransactionsRequestType.swift | 4 +- core | 2 +- 27 files changed, 142 insertions(+), 229 deletions(-) diff --git a/Gem/Asset/AssetScene.swift b/Gem/Asset/AssetScene.swift index 9d8e107f..4bf95a67 100644 --- a/Gem/Asset/AssetScene.swift +++ b/Gem/Asset/AssetScene.swift @@ -52,9 +52,9 @@ struct AssetScene: View { self.wallet = wallet self.input = input _isPresentingAssetSelectType = isPresentingAssetSelectType - _assetData = Query(constant: input.assetRequest, in: \.db.dbQueue) - _transactions = Query(constant: input.transactionsRequest, in: \.db.dbQueue) - _banners = Query(constant: input.bannersRequest, in: \.db.dbQueue) + _assetData = Query(constant: input.assetRequest) + _transactions = Query(constant: input.transactionsRequest) + _banners = Query(constant: input.bannersRequest) } var body: some View { diff --git a/Gem/Assets/Scenes/SelectAssetScene.swift b/Gem/Assets/Scenes/SelectAssetScene.swift index f0641518..3979710d 100644 --- a/Gem/Assets/Scenes/SelectAssetScene.swift +++ b/Gem/Assets/Scenes/SelectAssetScene.swift @@ -7,8 +7,6 @@ import GRDBQuery import Style struct SelectAssetScene: View { - - @Environment(\.db) private var DB @Environment(\.keystore) private var keystore @Environment(\.walletsService) private var walletsService @Environment(\.nodeService) private var nodeService @@ -30,8 +28,8 @@ struct SelectAssetScene: View { isPresentingAddToken: Binding ) { _model = StateObject(wrappedValue: model) - _assets = Query(model.assetRequest, in: \.db.dbQueue) - _assetInfo = Query(model.assetsInfoRequest, in: \.db.dbQueue) + _assets = Query(model.assetRequest) + _assetInfo = Query(model.assetsInfoRequest) self.isPresentingAddToken = isPresentingAddToken } diff --git a/Gem/Charts/Scenes/ChartScene.swift b/Gem/Charts/Scenes/ChartScene.swift index 06c26a3e..ca17a1e6 100644 --- a/Gem/Charts/Scenes/ChartScene.swift +++ b/Gem/Charts/Scenes/ChartScene.swift @@ -20,7 +20,7 @@ struct ChartScene: View { model: ChartsViewModel ) { _model = StateObject(wrappedValue: model) - _assetData = Query(constant: model.assetRequest, in: \.db.dbQueue) + _assetData = Query(constant: model.assetRequest) } var body: some View { diff --git a/Gem/Connections/Scenes/ConnectionsScene.swift b/Gem/Connections/Scenes/ConnectionsScene.swift index 0bc2d27b..a832ed26 100644 --- a/Gem/Connections/Scenes/ConnectionsScene.swift +++ b/Gem/Connections/Scenes/ConnectionsScene.swift @@ -9,8 +9,6 @@ import QRScanner import Style struct ConnectionsScene: View { - - @Environment(\.db) private var DB @Environment(\.keystore) private var keystore @State private var isPresentingScanner: Bool = false @State private var isPresentingErrorMessage: String? diff --git a/Gem/Core/Coordinator/WalletCoordinator.swift b/Gem/Core/Coordinator/WalletCoordinator.swift index 1bc5fdfc..85aa56c4 100644 --- a/Gem/Core/Coordinator/WalletCoordinator.swift +++ b/Gem/Core/Coordinator/WalletCoordinator.swift @@ -161,7 +161,6 @@ struct WalletCoordinator: View { } message: { Text(Localized.UpdateApp.description(updateAvailableAlertSheetMessage ?? "")) } - .environment(\.db, db) .environment(\.nodeService, nodeService) .environment(\.keystore, keystore) .environment(\.walletService, walletService) diff --git a/Gem/Core/Views/MainTabView.swift b/Gem/Core/Views/MainTabView.swift index 4e889d80..6cbc5f25 100644 --- a/Gem/Core/Views/MainTabView.swift +++ b/Gem/Core/Views/MainTabView.swift @@ -40,7 +40,7 @@ struct MainTabView: View { navigationStateManager: Binding ) { self.model = model - _transactions = Query(constant: model.transactionsCountRequest, in: \.db.dbQueue) + _transactions = Query(constant: model.transactionsCountRequest) _navigationStateManager = navigationStateManager } diff --git a/Gem/Stake/Scenes/StakeScene.swift b/Gem/Stake/Scenes/StakeScene.swift index 71a1982e..a0160b40 100644 --- a/Gem/Stake/Scenes/StakeScene.swift +++ b/Gem/Stake/Scenes/StakeScene.swift @@ -9,7 +9,6 @@ import Components import Style struct StakeScene: View { - @Environment(\.db) private var DB @Environment(\.keystore) private var keystore @Environment(\.nodeService) private var nodeService @Environment(\.walletsService) private var walletsService @@ -25,7 +24,7 @@ struct StakeScene: View { init(model: StakeViewModel) { _model = State(initialValue: model) - _delegations = Query(model.request, in: \.db.dbQueue) + _delegations = Query(model.request) } var body: some View { diff --git a/Gem/Swap/Scenes/SwapScene.swift b/Gem/Swap/Scenes/SwapScene.swift index 2052cbf8..ced70e98 100644 --- a/Gem/Swap/Scenes/SwapScene.swift +++ b/Gem/Swap/Scenes/SwapScene.swift @@ -12,9 +12,14 @@ import Keystore struct SwapScene: View { @Environment(\.nodeService) private var nodeService - @Query var fromAsset: AssetData - @Query var toAsset: AssetData - @Query var tokenApprovals: [TransactionExtended] + @Query + var fromAsset: AssetData + + @Query + var toAsset: AssetData + + @Query + var tokenApprovals: [TransactionExtended] @State var model: SwapViewModel @@ -25,9 +30,9 @@ struct SwapScene: View { init(model: SwapViewModel) { _model = State(initialValue: model) - _fromAsset = Query(model.fromAssetRequest, in: \.db.dbQueue) - _toAsset = Query(model.toAssetRequest, in: \.db.dbQueue) - _tokenApprovals = Query(model.tokenApprovalsRequest, in: \.db.dbQueue) + _fromAsset = Query(model.fromAssetRequest) + _toAsset = Query(model.toAssetRequest) + _tokenApprovals = Query(model.tokenApprovalsRequest) } var body: some View { diff --git a/Gem/Transactions/Scenes/TransactionScene.swift b/Gem/Transactions/Scenes/TransactionScene.swift index fadbe857..52f48f96 100644 --- a/Gem/Transactions/Scenes/TransactionScene.swift +++ b/Gem/Transactions/Scenes/TransactionScene.swift @@ -29,7 +29,7 @@ struct TransactionScene: View { input: TransactionSceneInput ) { self.input = input - _transactions = Query(input.transactionRequest, in: \.db.dbQueue) + _transactions = Query(input.transactionRequest) } @State private var showShareSheet = false diff --git a/Gem/Transactions/Scenes/TransactionsScene.swift b/Gem/Transactions/Scenes/TransactionsScene.swift index b2ecea9f..7b2def5c 100644 --- a/Gem/Transactions/Scenes/TransactionsScene.swift +++ b/Gem/Transactions/Scenes/TransactionsScene.swift @@ -8,8 +8,6 @@ import Store import Style struct TransactionsScene: View { - @Environment(\.db) private var DB - @Query private var transactions: [TransactionExtended] @@ -19,7 +17,7 @@ struct TransactionsScene: View { model: TransactionsViewModel ) { self.model = model - _transactions = Query(constant: model.request, in: \.db.dbQueue) + _transactions = Query(constant: model.request) } var body: some View { diff --git a/Gem/Wallet/Scenes/WalletScene.swift b/Gem/Wallet/Scenes/WalletScene.swift index 26a8aedf..2314348c 100644 --- a/Gem/Wallet/Scenes/WalletScene.swift +++ b/Gem/Wallet/Scenes/WalletScene.swift @@ -10,8 +10,6 @@ import GRDBQuery import Style struct WalletScene: View { - - @Environment(\.db) private var DB @Environment(\.keystore) private var keystore @Environment(\.assetsService) private var assetsService @Environment(\.transactionsService) private var transactionsService @@ -49,11 +47,11 @@ struct WalletScene: View { try? model.setupWallet() - _assets = Query(constant: model.assetsRequest, in: \.db.dbQueue) - _assetsPinned = Query(constant: model.assetsPinnedRequest, in: \.db.dbQueue) - _fiatValue = Query(constant: model.fiatValueRequest, in: \.db.dbQueue) - _dbWallet = Query(constant: model.walletRequest, in: \.db.dbQueue) - _banners = Query(constant: model.bannersRequest, in: \.db.dbQueue) + _assets = Query(constant: model.assetsRequest) + _assetsPinned = Query(constant: model.assetsPinnedRequest) + _fiatValue = Query(constant: model.fiatValueRequest) + _dbWallet = Query(constant: model.walletRequest) + _banners = Query(constant: model.bannersRequest) } var body: some View { diff --git a/Gem/Wallet/Types/Environment.swift b/Gem/Wallet/Types/Environment.swift index 3782c5da..2312d2d6 100644 --- a/Gem/Wallet/Types/Environment.swift +++ b/Gem/Wallet/Types/Environment.swift @@ -7,11 +7,6 @@ import Store import Keystore import GemstonePrimitives -// TODO: - remove ref. https://swiftpackageindex.com/groue/grdbquery/0.9.0/documentation/grdbquery/migratingtogrdbquery09-unrestricted-writes -struct DatabaseQueueKey: EnvironmentKey { - static var defaultValue: DB { DB.main } -} - struct NodeServiceKey: EnvironmentKey { static var defaultValue: NodeService { NodeService.main } } @@ -81,12 +76,6 @@ struct IsWalletPresentedServiceKey: EnvironmentKey { } extension EnvironmentValues { - // TODO: - remove ref. https://swiftpackageindex.com/groue/grdbquery/0.9.0/documentation/grdbquery/migratingtogrdbquery09-unrestricted-writes - var db: DB { - get { self[DatabaseQueueKey.self] } - set { self[DatabaseQueueKey.self] = newValue } - } - var nodeService: NodeService { get { self[NodeServiceKey.self] } set { self[NodeServiceKey.self] = newValue } diff --git a/Gem/Wallets/Scenes/WalletsScene.swift b/Gem/Wallets/Scenes/WalletsScene.swift index cf4bbb5c..24f7cd57 100644 --- a/Gem/Wallets/Scenes/WalletsScene.swift +++ b/Gem/Wallets/Scenes/WalletsScene.swift @@ -8,7 +8,6 @@ import Style struct WalletsScene: View { @Environment(\.dismiss) private var dismiss - @Environment(\.db) private var DB @Environment(\.keystore) private var keystore @State private var isPresentingErrorMessage: String? @@ -31,8 +30,8 @@ struct WalletsScene: View { model: WalletsViewModel ) { self.model = model - _pinnedWallets = Query(WalletsRequest(isPinned: true), in: \.db.dbQueue) - _wallets = Query(WalletsRequest(isPinned: false), in: \.db.dbQueue) + _pinnedWallets = Query(WalletsRequest(isPinned: true)) + _wallets = Query(WalletsRequest(isPinned: false)) } var body: some View { diff --git a/Packages/Store/Sources/Requests/AssetRequest.swift b/Packages/Store/Sources/Requests/AssetRequest.swift index bfe6efb8..5167f235 100644 --- a/Packages/Store/Sources/Requests/AssetRequest.swift +++ b/Packages/Store/Sources/Requests/AssetRequest.swift @@ -6,30 +6,20 @@ import GRDBQuery import Combine import Primitives -public struct AssetRequest: Queryable { - +public struct AssetRequest: ValueObservationQueryable { public static var defaultValue: AssetData { AssetData.empty } - public let walletId: String public var assetId: String - public init( - walletId: String, - assetId: String - ) { + private let walletId: String + + public init(walletId: String, assetId: String) { self.walletId = walletId self.assetId = assetId } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> AssetData { - return try AssetRecord + + public func fetch(_ db: Database) throws -> AssetData { + try AssetRecord .including(optional: AssetRecord.price) .including(optional: AssetRecord.balance) .including(optional: AssetRecord.details) @@ -43,7 +33,10 @@ public struct AssetRequest: Queryable { } } +// MARK: - Models Exttensions + //TODO: Find a way to remove .empty + extension AssetData { static let empty: AssetData = { return AssetData( diff --git a/Packages/Store/Sources/Requests/AssetsInfoRequest.swift b/Packages/Store/Sources/Requests/AssetsInfoRequest.swift index f1c67ed5..61991cd2 100644 --- a/Packages/Store/Sources/Requests/AssetsInfoRequest.swift +++ b/Packages/Store/Sources/Requests/AssetsInfoRequest.swift @@ -4,23 +4,16 @@ import GRDBQuery import Combine import Primitives -public struct AssetsInfoRequest: Queryable { +public struct AssetsInfoRequest: ValueObservationQueryable { public static var defaultValue: AssetsInfo { AssetsInfo(hidden: 0) } - let walletId: String - + private let walletId: String + public init(walletId: String) { self.walletId = walletId } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> AssetsInfo { + + public func fetch(_ db: Database) throws -> AssetsInfo { let hidden = try AssetBalanceRecord .filter(Columns.Balance.walletId == walletId) .filter(Columns.Balance.isHidden == true) diff --git a/Packages/Store/Sources/Requests/AssetsRequest.swift b/Packages/Store/Sources/Requests/AssetsRequest.swift index 86eb3f6e..1e65b7e6 100644 --- a/Packages/Store/Sources/Requests/AssetsRequest.swift +++ b/Packages/Store/Sources/Requests/AssetsRequest.swift @@ -4,13 +4,14 @@ import GRDBQuery import Combine import Primitives -public struct AssetsRequest: Queryable { +public struct AssetsRequest: ValueObservationQueryable { public static var defaultValue: [AssetData] { [] } - public var walletID: String + private let walletID: String + public var searchBy: String public var filters: [AssetsRequestFilter] - + public init( walletID: String, searchBy: String = "", @@ -20,42 +21,19 @@ public struct AssetsRequest: Queryable { self.searchBy = searchBy self.filters = filters } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[AssetData], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() - } - - func assetBalancesRequest(_ db: Database) throws -> [AssetData] { - try fetchAssets(filters: filters) - .fetchAll(db).map { $0.assetData } - } - - func assetsRequest(_ db: Database, searchBy: String, excludeAssetIds: [String]) throws -> [AssetData] { - return try Self.fetchAssetsSearch( - walletId: walletID, - searchBy: searchBy, - filters: filters, - excludeAssetIds: excludeAssetIds - ) - .fetchAll(db).map { $0.assetData } - } - - private func fetch(_ db: Database) throws -> [AssetData] { + + public func fetch(_ db: Database) throws -> [AssetData] { let searchBy = searchBy.trim() + if filters.contains(.includeNewAssets) { let request1 = try assetBalancesRequest(db) let request2 = try assetsRequest(db, searchBy: searchBy, excludeAssetIds: request1.map { $0.asset.id.identifier }) - + return [request1, request2].flatMap { $0 } - } else { - return try assetBalancesRequest(db) } + return try assetBalancesRequest(db) } - + func fetchAssets(filters: [AssetsRequestFilter])-> QueryInterfaceRequest { var request = AssetRecord .including(optional: AssetRecord.price) @@ -71,14 +49,33 @@ public struct AssetsRequest: Queryable { if !searchBy.isEmpty { request = Self.applyFilter(request: request, .search(searchBy)) } - + filters.forEach { request = Self.applyFilter(request: request, $0) } return request.asRequest(of: AssetRecordInfo.self) } - - static func applyFilter(request: QueryInterfaceRequest, _ filter: AssetsRequestFilter) -> QueryInterfaceRequest { +} + +// MARK: - Private + +extension AssetsRequest { + private func assetBalancesRequest(_ db: Database) throws -> [AssetData] { + try fetchAssets(filters: filters) + .fetchAll(db).map { $0.assetData } + } + + private func assetsRequest(_ db: Database, searchBy: String, excludeAssetIds: [String]) throws -> [AssetData] { + try Self.fetchAssetsSearch( + walletId: walletID, + searchBy: searchBy, + filters: filters, + excludeAssetIds: excludeAssetIds + ) + .fetchAll(db).map { $0.assetData } + } + + static private func applyFilter(request: QueryInterfaceRequest, _ filter: AssetsRequestFilter) -> QueryInterfaceRequest { switch filter { case .search(let name): return request @@ -136,8 +133,8 @@ public struct AssetsRequest: Queryable { return request } } - - static func fetchAssetsSearch( + + static private func fetchAssetsSearch( walletId: String, searchBy: String, filters: [AssetsRequestFilter], @@ -151,7 +148,7 @@ public struct AssetsRequest: Queryable { ) .order(Columns.Asset.rank.asc) .limit(50) - + if !searchBy.isEmpty { request = Self.applyFilter(request: request, .search(searchBy)) } diff --git a/Packages/Store/Sources/Requests/BannerRequest.swift b/Packages/Store/Sources/Requests/BannerRequest.swift index 73b2a63d..7ee58800 100644 --- a/Packages/Store/Sources/Requests/BannerRequest.swift +++ b/Packages/Store/Sources/Requests/BannerRequest.swift @@ -4,14 +4,14 @@ import Foundation import GRDB import GRDBQuery import Combine -import Primitives +@preconcurrency import Primitives // TODO: - integrate Sendable for BannerEvent -public struct BannersRequest: Queryable { +public struct BannersRequest: ValueObservationQueryable { public static var defaultValue: [Banner] { [] } - let walletId: String? - let assetId: String? - let events: [BannerEvent] + private let walletId: String? + private let assetId: String? + private let events: [BannerEvent] public init( walletId: String?, @@ -23,16 +23,8 @@ public struct BannersRequest: Queryable { self.events = events } - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[Banner], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> [Banner] { - return try BannerRecord + public func fetch(_ db: Database) throws -> [Banner] { + try BannerRecord .including(optional: BannerRecord.asset) .including(optional: BannerRecord.wallet) .filter(Columns.Banner.walletId == walletId || Columns.Banner.walletId == nil) diff --git a/Packages/Store/Sources/Requests/ConnectionsRequest.swift b/Packages/Store/Sources/Requests/ConnectionsRequest.swift index 907c3f05..23d3907f 100644 --- a/Packages/Store/Sources/Requests/ConnectionsRequest.swift +++ b/Packages/Store/Sources/Requests/ConnectionsRequest.swift @@ -9,11 +9,10 @@ import Primitives public struct ConnectionsRequest: ValueObservationQueryable { public static var defaultValue: [WalletConnection] { [] } - public init() { - } + public init() {} public func fetch(_ db: Database) throws -> [WalletConnection] { - return try WalletRecord + try WalletRecord .including(required: WalletRecord.connection) .asRequest(of: WalletConnectionInfo.self) .fetchAll(db) diff --git a/Packages/Store/Sources/Requests/StakeDelegationsRequest.swift b/Packages/Store/Sources/Requests/StakeDelegationsRequest.swift index ae4144cb..4592e9e6 100644 --- a/Packages/Store/Sources/Requests/StakeDelegationsRequest.swift +++ b/Packages/Store/Sources/Requests/StakeDelegationsRequest.swift @@ -6,27 +6,19 @@ import GRDBQuery import Combine import Primitives -public struct StakeDelegationsRequest: Queryable { +public struct StakeDelegationsRequest: ValueObservationQueryable { public static var defaultValue: [Delegation] { [] } - let walletId: String - let assetId: String - + private let walletId: String + private let assetId: String + public init(walletId: String, assetId: String) { self.walletId = walletId self.assetId = assetId } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[Delegation], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> [Delegation] { - return try StakeDelegationRecord + + public func fetch(_ db: Database) throws -> [Delegation] { + try StakeDelegationRecord .including(optional: StakeDelegationRecord.validator) .including(optional: StakeDelegationRecord.price) .filter(Columns.StakeDelegation.walletId == walletId) diff --git a/Packages/Store/Sources/Requests/TotalValueRequest.swift b/Packages/Store/Sources/Requests/TotalValueRequest.swift index 4320d0c5..67a5e2eb 100644 --- a/Packages/Store/Sources/Requests/TotalValueRequest.swift +++ b/Packages/Store/Sources/Requests/TotalValueRequest.swift @@ -4,29 +4,18 @@ import GRDBQuery import Combine import Primitives -public struct TotalValueRequest: Queryable { +public struct TotalValueRequest: ValueObservationQueryable { public static var defaultValue: Double { 0 } public var walletId: String - public init( - walletID: String - ) { + public init(walletID: String) { self.walletId = walletID } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher { - ValueObservation - .tracking { db in try fetch(db) } - // The `.immediate` scheduling feeds the view right on subscription, - // and avoids an initial rendering with an empty list: - .publisher(in: dbQueue, scheduling: .immediate) - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> Double { - //TODO: Refactor to calculate total price - return try AssetRecord + + public func fetch(_ db: Database) throws -> Double { + //TODO: - Refactor to calculate total price + try AssetRecord .including(optional: AssetRecord.price) .including(optional: AssetRecord.balance) .joining(required: AssetRecord.balance diff --git a/Packages/Store/Sources/Requests/TransactionsCountRequest.swift b/Packages/Store/Sources/Requests/TransactionsCountRequest.swift index f030546c..298a7b36 100644 --- a/Packages/Store/Sources/Requests/TransactionsCountRequest.swift +++ b/Packages/Store/Sources/Requests/TransactionsCountRequest.swift @@ -4,9 +4,9 @@ import Foundation import GRDB import GRDBQuery import Combine -import Primitives +@preconcurrency import Primitives // TODO: - integrate Sendable for TransactionState -public struct TransactionsCountRequest: Queryable { +public struct TransactionsCountRequest: ValueObservationQueryable { public static var defaultValue: Int { 0 } private let walletId: String @@ -20,15 +20,8 @@ public struct TransactionsCountRequest: Queryable { self.state = state } - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> Int { - return try TransactionRecord + public func fetch(_ db: Database) throws -> Int { + try TransactionRecord .filter(Columns.Transaction.walletId == walletId) .filter(Columns.Transaction.state == state.rawValue) .fetchCount(db) diff --git a/Packages/Store/Sources/Requests/TransactionsRequest.swift b/Packages/Store/Sources/Requests/TransactionsRequest.swift index 2ac8741b..65a37f84 100644 --- a/Packages/Store/Sources/Requests/TransactionsRequest.swift +++ b/Packages/Store/Sources/Requests/TransactionsRequest.swift @@ -6,13 +6,13 @@ import GRDBQuery import Combine import Primitives -public struct TransactionsRequest: Queryable { +public struct TransactionsRequest: ValueObservationQueryable { public static var defaultValue: [TransactionExtended] { [] } - - let walletId: String - let type: TransactionsRequestType - let limit: Int - + + private let walletId: String + private let type: TransactionsRequestType + private let limit: Int + public init( walletId: String, type: TransactionsRequestType, @@ -22,16 +22,8 @@ public struct TransactionsRequest: Queryable { self.type = type self.limit = limit } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[TransactionExtended], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0 } - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> [TransactionExtended] { + + public func fetch(_ db: Database) throws -> [TransactionExtended] { let states = states(type: type) let types = types(type: type) var request = TransactionRecord @@ -46,7 +38,7 @@ public struct TransactionsRequest: Queryable { .order(Columns.Transaction.date.desc) .distinct() .limit(limit) - + switch type { case .asset(let assetId): request = request.joining(required: TransactionRecord.assetsAssociation.filter(Columns.TransactionAssetAssociation.assetId == assetId.identifier)) @@ -57,29 +49,33 @@ public struct TransactionsRequest: Queryable { case .all, .pending: break } - + return try request.asRequest(of: TransactionInfo.self) .fetchAll(db) .compactMap { $0.mapToTransactionExtended() } } - +} + +// MARK: - Private + +extension TransactionsRequest { private func states(type: TransactionsRequestType) -> [String] { switch type { case .pending: - return [TransactionState.pending.rawValue] + [TransactionState.pending.rawValue] case .all, .asset, .transaction: - return TransactionState.allCases.map { $0.rawValue } + TransactionState.allCases.map { $0.rawValue } case .assetsTransactionType(_, _, let states): - return states.map { $0.rawValue } + states.map { $0.rawValue } } } - + private func types(type: TransactionsRequestType) -> [String] { switch type { case .assetsTransactionType(_, let type, _): - return [type.rawValue] + [type.rawValue] case .pending, .all, .asset, .transaction: - return TransactionType.allCases.map { $0.rawValue } + TransactionType.allCases.map { $0.rawValue } } } } diff --git a/Packages/Store/Sources/Requests/WalletRequest.swift b/Packages/Store/Sources/Requests/WalletRequest.swift index 6fc174ce..9837d89f 100644 --- a/Packages/Store/Sources/Requests/WalletRequest.swift +++ b/Packages/Store/Sources/Requests/WalletRequest.swift @@ -6,25 +6,17 @@ import GRDBQuery import Combine import Primitives -public struct WalletRequest: Queryable { +public struct WalletRequest: ValueObservationQueryable { public static var defaultValue: Wallet? { .none } - - let walletId: String - + + private let walletId: String + public init(walletId: String) { self.walletId = walletId } - - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() - } - - private func fetch(_ db: Database) throws -> Wallet? { - return try WalletRecord + + public func fetch(_ db: Database) throws -> Wallet? { + try WalletRecord .including(all: WalletRecord.accounts) .asRequest(of: WalletRecordInfo.self) .filter(Columns.Wallet.id == walletId) diff --git a/Packages/Store/Sources/Requests/WalletsRequest.swift b/Packages/Store/Sources/Requests/WalletsRequest.swift index a1503c62..ed298de8 100644 --- a/Packages/Store/Sources/Requests/WalletsRequest.swift +++ b/Packages/Store/Sources/Requests/WalletsRequest.swift @@ -6,26 +6,17 @@ import GRDBQuery import Combine import Primitives -public struct WalletsRequest: Queryable { +public struct WalletsRequest: ValueObservationQueryable { public static var defaultValue: [Wallet] { [] } private let isPinned: Bool - public init( - isPinned: Bool - ) { - self.isPinned = isPinned - } - public func publisher(in dbQueue: DatabaseQueue) -> AnyPublisher<[Wallet], Error> { - ValueObservation - .tracking { db in try fetch(db) } - .publisher(in: dbQueue, scheduling: .immediate) - .map { $0.map{ $0 } } - .eraseToAnyPublisher() + public init(isPinned: Bool) { + self.isPinned = isPinned } - private func fetch(_ db: Database) throws -> [Wallet] { - return try WalletRecord + public func fetch(_ db: Database) throws -> [Wallet] { + try WalletRecord .including(all: WalletRecord.accounts) .filter(Columns.Wallet.isPinned == isPinned) .order(Columns.Wallet.order.asc) diff --git a/Packages/Store/Sources/Types/AssetsRequestFilter.swift b/Packages/Store/Sources/Types/AssetsRequestFilter.swift index 4055d55e..f0cec35a 100644 --- a/Packages/Store/Sources/Types/AssetsRequestFilter.swift +++ b/Packages/Store/Sources/Types/AssetsRequestFilter.swift @@ -19,3 +19,4 @@ public enum AssetsRequestFilter { } extension AssetsRequestFilter: Equatable {} +extension AssetsRequestFilter: Sendable {} diff --git a/Packages/Store/Sources/Types/TransactionsRequestType.swift b/Packages/Store/Sources/Types/TransactionsRequestType.swift index cddbcf2f..9c3f3a45 100644 --- a/Packages/Store/Sources/Types/TransactionsRequestType.swift +++ b/Packages/Store/Sources/Types/TransactionsRequestType.swift @@ -1,7 +1,7 @@ // Copyright (c). Gem Wallet. All rights reserved. import Foundation -import Primitives +@preconcurrency import Primitives // TODO: - integrate Sendable for AssetId & TransactionType & TransactionState public enum TransactionsRequestType: Equatable { case all @@ -23,3 +23,5 @@ extension TransactionsRequestType: Identifiable { } } } + +extension TransactionsRequestType: Sendable {} diff --git a/core b/core index 5d7cb2bd..4a75f6af 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 5d7cb2bddcdfdd11293e7da0a52873ca4a9a6094 +Subproject commit 4a75f6af2b7e6592c5bfc84976dbe54c023e3a08 From ce3b862fac6f0d6a742cd9ca2c50ba04892ebbc3 Mon Sep 17 00:00:00 2001 From: gemdev111 Date: Wed, 4 Sep 2024 17:37:36 +0300 Subject: [PATCH 4/5] added @discardableResult to fix xcode warning --- Packages/Store/Sources/Stores/BalanceStore.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Packages/Store/Sources/Stores/BalanceStore.swift b/Packages/Store/Sources/Stores/BalanceStore.swift index bc8e239d..92a67ba3 100644 --- a/Packages/Store/Sources/Stores/BalanceStore.swift +++ b/Packages/Store/Sources/Stores/BalanceStore.swift @@ -114,6 +114,7 @@ public struct BalanceStore { } } + @discardableResult public func pinAsset(walletId: String, assetId: String, value: Bool) throws -> Int { try db.write { db in return try AssetBalanceRecord From 6b81ea2f070ff2e78c02cb5f1cebd5a164e4ab47 Mon Sep 17 00:00:00 2001 From: gemdev111 Date: Wed, 4 Sep 2024 21:46:40 +0300 Subject: [PATCH 5/5] moved ConnectionsRequest to model for concistency --- Gem/Connections/Scenes/ConnectionsScene.swift | 7 +++---- Gem/Connections/ViewModels/ConnectionsViewModel.swift | 7 ++++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Gem/Connections/Scenes/ConnectionsScene.swift b/Gem/Connections/Scenes/ConnectionsScene.swift index a832ed26..59c9268e 100644 --- a/Gem/Connections/Scenes/ConnectionsScene.swift +++ b/Gem/Connections/Scenes/ConnectionsScene.swift @@ -13,7 +13,7 @@ struct ConnectionsScene: View { @State private var isPresentingScanner: Bool = false @State private var isPresentingErrorMessage: String? - @Query(ConnectionsRequest()) + @Query var connections: [WalletConnection] var groupedByWallet: [Wallet: [Primitives.WalletConnection]] { @@ -26,10 +26,9 @@ struct ConnectionsScene: View { let model: ConnectionsViewModel - init( - model: ConnectionsViewModel - ) { + init(model: ConnectionsViewModel) { self.model = model + _connections = Query(constant: model.request) } var body: some View { diff --git a/Gem/Connections/ViewModels/ConnectionsViewModel.swift b/Gem/Connections/ViewModels/ConnectionsViewModel.swift index 165f35f5..fba0e076 100644 --- a/Gem/Connections/ViewModels/ConnectionsViewModel.swift +++ b/Gem/Connections/ViewModels/ConnectionsViewModel.swift @@ -2,10 +2,15 @@ import Foundation import Primitives +import Store struct ConnectionsViewModel { let service: ConnectionsService - + + var request: ConnectionsRequest { + ConnectionsRequest() + } + func addConnectionURI(uri: String, wallet: Wallet) async throws { try await service.addConnectionURI(uri: uri, wallet: wallet) }