diff --git a/Podfile b/Podfile index ed30a54d9a..b0a7fca9de 100644 --- a/Podfile +++ b/Podfile @@ -71,6 +71,11 @@ pod 'YYImage/libwebp', git: 'https://github.com/signalapp/YYImage', :inhibit_war pod 'Reachability', :inhibit_warnings => true +# pod 'LibMobileCoin', git: 'https://github.com/signalapp/libmobilecoin-ios-artifacts.git', branch: 'signal/1.1.0' +# pod 'MobileCoin', git: 'https://github.com/mobilecoinofficial/MobileCoin-Swift.git', :tag => 'v1.1.0' +# pod 'MobileCoinMinimal', git: 'https://github.com/mobilecoinofficial/MobileCoin-Swift.git', :tag => 'v1.1.0' + + def ui_pods pod 'BonMot', inhibit_warnings: true pod 'PureLayout', :inhibit_warnings => true @@ -99,7 +104,10 @@ end # These extensions inherit all of the common pods -target 'SignalMessaging' +# target 'SignalMessaging' +target 'SignalMessaging' do + pod 'MobileCoinMinimal', path: '../MobileCoinMinimal', testspecs: ["Tests"] +end target 'SignalShareExtension' do ui_pods @@ -109,7 +117,11 @@ target 'SignalUI' do ui_pods end -target 'SignalNSE' +target 'SignalNSE' do + # pod 'MobileCoin', git: 'https://github.com/mobilecoinofficial/MobileCoin-Swift.git', :tag => 'v1.1.0' + # pod 'MobileCoinProtos', path: '../MobileCoinProtos-Swift', testspecs: ["Tests"] + # pod 'MobileCoinMinimal', path: '../MobileCoinMinimal', testspecs: ["Tests"] +end post_install do |installer| enable_strip(installer) @@ -224,6 +236,7 @@ def strip_valid_archs(installer) Dir.glob('Pods/Target Support Files/**/*.xcconfig') do |xcconfig_path| xcconfig = File.read(xcconfig_path) xcconfig_mod = xcconfig.gsub('VALID_ARCHS[sdk=iphoneos*] = arm64', '') + xcconfig_mod = xcconfig_mod.gsub('VALID_ARCHS[sdk=iphonesimulator*] = x86_64 arm64', '') xcconfig_mod = xcconfig_mod.gsub('VALID_ARCHS[sdk=iphonesimulator*] = x86_64', '') File.open(xcconfig_path, "w") { |file| file << xcconfig_mod } end diff --git a/Podfile.lock b/Podfile.lock index 7b4b30a4f8..ee90e58d6b 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -83,6 +83,14 @@ PODS: - SwiftNIOHPACK (~> 1.16) - SwiftNIOHTTP1 (~> 2.18) - SwiftProtobuf (~> 1.5) + - MobileCoinMinimal (1.2.0-pre2): + - CocoaLumberjack + - Logging (~> 1.4) + - SwiftProtobuf + - MobileCoinMinimal/Tests (1.2.0-pre2): + - CocoaLumberjack + - Logging (~> 1.4) + - SwiftProtobuf - OpenSSL-Universal (1.1.1100) - PureLayout (3.1.4) - Reachability (3.2) @@ -223,6 +231,8 @@ DEPENDENCIES: - lottie-ios - Mantle (from `https://github.com/signalapp/Mantle`, branch `signal-master`) - MobileCoin (from `https://github.com/mobilecoinofficial/MobileCoin-Swift.git`, tag `v1.1.0`) + - MobileCoinMinimal (from `../MobileCoinMinimal`) + - MobileCoinMinimal/Tests (from `../MobileCoinMinimal`) - OpenSSL-Universal (from `https://github.com/signalapp/GRKOpenSSLFramework`) - PureLayout - Reachability @@ -302,6 +312,8 @@ EXTERNAL SOURCES: MobileCoin: :git: https://github.com/mobilecoinofficial/MobileCoin-Swift.git :tag: v1.1.0 + MobileCoinMinimal: + :path: "../MobileCoinMinimal" OpenSSL-Universal: :git: https://github.com/signalapp/GRKOpenSSLFramework SignalArgon2: @@ -396,6 +408,7 @@ SPEC CHECKSUMS: lottie-ios: 496ac5cea1bbf1a7bd1f1f472f3232eb1b8d744b Mantle: 2fa750afa478cd625a94230fbf1c13462f29395b MobileCoin: 59f940b9f71e6fdcfd206150ebda839a132b58be + MobileCoinMinimal: 627ed590d8a0d5d57c39ec25727bde3d976d2f7a OpenSSL-Universal: d8fb58afffcf2dafe4ad99e17efe236bcd216c2e PureLayout: f08c01b8dec00bb14a1fefa3de4c7d9c265df85e Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 @@ -423,6 +436,6 @@ SPEC CHECKSUMS: YYImage: f1ddd15ac032a58b78bbed1e012b50302d318331 ZKGroup: 81ba58bf87b5614b03d49364db221390bf257dd7 -PODFILE CHECKSUM: aaba99834df7eb9f753a09579156322883499d5f +PODFILE CHECKSUM: 774768ab4bf23ff88c236e4d27d4b2795219bb96 COCOAPODS: 1.10.1 diff --git a/SignalMessaging/Payments/PaymentsHelperImpl.swift b/SignalMessaging/Payments/PaymentsHelperImpl.swift index 02b3f1713f..ce00f00eea 100644 --- a/SignalMessaging/Payments/PaymentsHelperImpl.swift +++ b/SignalMessaging/Payments/PaymentsHelperImpl.swift @@ -58,6 +58,7 @@ public class PaymentsHelperImpl: NSObject, PaymentsHelperSwift { private static let arePaymentsEnabledKey = "isPaymentEnabled" private static let paymentsEntropyKey = "paymentsEntropy" + private static let lastKnownLocalPaymentAddressProtoDataKey = "lastKnownLocalPaymentAddressProtoData" private let paymentStateCache = AtomicOptional(nil) @@ -146,10 +147,12 @@ public class PaymentsHelperImpl: NSObject, PaymentsHelperSwift { self.paymentStateCache.set(newPaymentsState) + paymentsEvents.updateLastKnownLocalPaymentAddressProtoData(transaction: transaction) + transaction.addAsyncCompletionOffMain { NotificationCenter.default.postNotificationNameAsync(PaymentsConstants.arePaymentsEnabledDidChange, object: nil) - self.updateCurrentPaymentBalance() + Self.paymentsEvents.paymentsStateDidChange() Self.profileManager.reuploadLocalProfile() @@ -193,6 +196,15 @@ public class PaymentsHelperImpl: NSObject, PaymentsHelperSwift { paymentStateCache.set(nil) } + public func setLastKnownLocalPaymentAddressProtoData(_ data: Data, transaction: SDSAnyWriteTransaction) { + Self.keyValueStore.setData(data, key: Self.lastKnownLocalPaymentAddressProtoDataKey, transaction: transaction) + } + + public func lastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) -> Data? { + paymentsEvents.updateLastKnownLocalPaymentAddressProtoData(transaction: transaction) + return Self.keyValueStore.getData(Self.lastKnownLocalPaymentAddressProtoDataKey, transaction: transaction) + } + // MARK: - private static let arePaymentsEnabledForUserStore = SDSKeyValueStore(collection: "arePaymentsEnabledForUserStore") diff --git a/SignalMessaging/environment/AppSetup.h b/SignalMessaging/environment/AppSetup.h index fbdd4bb518..be9193f9c4 100644 --- a/SignalMessaging/environment/AppSetup.h +++ b/SignalMessaging/environment/AppSetup.h @@ -10,10 +10,11 @@ NS_ASSUME_NONNULL_BEGIN // This is _NOT_ a singleton and will be instantiated each time that the SAE is used. @interface AppSetup : NSObject -+ (void)setupEnvironmentWithAppSpecificSingletonBlock:(dispatch_block_t)appSpecificSingletonBlock - paymentsEvents:(id)paymentsEvents - mobileCoinHelper:(id)mobileCoinHelper - migrationCompletion:(void (^)(NSError *_Nullable error))migrationCompletion; ++ (void)setupEnvironmentWithPaymentsEvents:(id)paymentsEvents + mobileCoinHelper:(id)mobileCoinHelper + appSpecificSingletonBlock:(dispatch_block_t)appSpecificSingletonBlock + migrationCompletion:(void (^)(NSError *_Nullable error))migrationCompletion +NS_SWIFT_NAME(setupEnvironment(paymentsEvents:mobileCoinHelper:appSpecificSingletonBlock:migrationCompletion:)); @end diff --git a/SignalMessaging/environment/AppSetup.m b/SignalMessaging/environment/AppSetup.m index 6087f4e4d1..05910d49b9 100644 --- a/SignalMessaging/environment/AppSetup.m +++ b/SignalMessaging/environment/AppSetup.m @@ -22,10 +22,10 @@ NS_ASSUME_NONNULL_BEGIN @implementation AppSetup -+ (void)setupEnvironmentWithAppSpecificSingletonBlock:(dispatch_block_t)appSpecificSingletonBlock - paymentsEvents:(id)paymentsEvents - mobileCoinHelper:(id)mobileCoinHelper - migrationCompletion:(void (^)(NSError *_Nullable error))migrationCompletion ++ (void)setupEnvironmentWithPaymentsEvents:(id)paymentsEvents + mobileCoinHelper:(id)mobileCoinHelper + appSpecificSingletonBlock:(dispatch_block_t)appSpecificSingletonBlock + migrationCompletion:(void (^)(NSError *_Nullable error))migrationCompletion { OWSAssertDebug(appSpecificSingletonBlock); OWSAssertDebug(migrationCompletion); @@ -177,7 +177,6 @@ NS_ASSUME_NONNULL_BEGIN paymentsCurrencies:paymentsCurrencies paymentsEvents:paymentsEvents mobileCoinHelper:mobileCoinHelper - paymentsCurrencies:paymentsCurrencies spamChallengeResolver:spamChallengeResolver senderKeyStore:senderKeyStore phoneNumberUtil:phoneNumberUtil]]; diff --git a/SignalMessaging/profiles/VersionedProfilesImpl.swift b/SignalMessaging/profiles/VersionedProfilesImpl.swift index 4552f0d797..34861e3019 100644 --- a/SignalMessaging/profiles/VersionedProfilesImpl.swift +++ b/SignalMessaging/profiles/VersionedProfilesImpl.swift @@ -61,10 +61,16 @@ public class VersionedProfilesImpl: NSObject, VersionedProfilesSwift { let commitmentData = commitment.serialize().asData let hasAvatar = profileAvatarData != nil + func fetchLocalPaymentAddressProtoData() -> Data? { + Self.databaseStorage.write { transaction in + Self.paymentsHelper.lastKnownLocalPaymentAddressProtoData(transaction: transaction) + } + } + var profilePaymentAddressData: Data? if Self.paymentsHelper.arePaymentsEnabled, !Self.paymentsHelper.isKillSwitchActive, - let addressProtoData = Self.paymentsHelper.localPaymentAddressProtoData() { + let addressProtoData = fetchLocalPaymentAddressProtoData() { var paymentAddressDataWithLength = Data() var littleEndian: UInt32 = CFSwapInt32HostToLittle(UInt32(addressProtoData.count)) diff --git a/SignalNSE/NSEEnvironment.swift b/SignalNSE/NSEEnvironment.swift index 74cfca21ee..71bf0d0abe 100644 --- a/SignalNSE/NSEEnvironment.swift +++ b/SignalNSE/NSEEnvironment.swift @@ -143,6 +143,8 @@ class NSEEnvironment: Dependencies { } AppSetup.setupEnvironment( + paymentsEvents: PaymentsEventsAppExtension(), + mobileCoinHelper: MobileCoinHelperMinimal(), appSpecificSingletonBlock: { SSKEnvironment.shared.callMessageHandlerRef = NSECallMessageHandler() SSKEnvironment.shared.notificationsManagerRef = NotificationPresenter() diff --git a/SignalServiceKit/src/Payments/PaymentsEvents.swift b/SignalServiceKit/src/Payments/PaymentsEvents.swift index 8118c6d7b6..4958cd6c86 100644 --- a/SignalServiceKit/src/Payments/PaymentsEvents.swift +++ b/SignalServiceKit/src/Payments/PaymentsEvents.swift @@ -9,6 +9,10 @@ public protocol PaymentsEvents: AnyObject { func willInsertPayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) func willUpdatePayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) + func updateLastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) + + func paymentsStateDidChange() + func clearState(transaction: SDSAnyWriteTransaction) } @@ -18,7 +22,11 @@ public protocol PaymentsEvents: AnyObject { public class PaymentsEventsNoop: NSObject, PaymentsEvents { public func willInsertPayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) {} public func willUpdatePayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) {} - + + public func updateLastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) {} + + public func paymentsStateDidChange() {} + public func clearState(transaction: SDSAnyWriteTransaction) {} } @@ -29,6 +37,10 @@ public class PaymentsEventsAppExtension: NSObject, PaymentsEvents { public func willInsertPayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) {} public func willUpdatePayment(_ paymentModel: TSPaymentModel, transaction: SDSAnyWriteTransaction) {} + public func updateLastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) {} + + public func paymentsStateDidChange() {} + public func clearState(transaction: SDSAnyWriteTransaction) { paymentsHelperSwift.clearState(transaction: transaction) } diff --git a/SignalServiceKit/src/Payments/PaymentsHelper.swift b/SignalServiceKit/src/Payments/PaymentsHelper.swift index f1f2022c78..060b0b06c4 100644 --- a/SignalServiceKit/src/Payments/PaymentsHelper.swift +++ b/SignalServiceKit/src/Payments/PaymentsHelper.swift @@ -21,6 +21,9 @@ public protocol PaymentsHelper: AnyObject { func enablePayments(withPaymentsEntropy: Data, transaction: SDSAnyWriteTransaction) -> Bool func disablePayments(transaction: SDSAnyWriteTransaction) + func setLastKnownLocalPaymentAddressProtoData(_ data: Data, transaction: SDSAnyWriteTransaction) + func lastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) -> Data? + @objc(processIncomingPaymentSyncMessage:messageTimestamp:transaction:) func processIncomingPaymentSyncMessage(_ paymentProto: SSKProtoSyncMessageOutgoingPayment, messageTimestamp: UInt64, @@ -177,6 +180,14 @@ extension MockPaymentsHelper: PaymentsHelperSwift { owsFail("Not implemented.") } + public func setLastKnownLocalPaymentAddressProtoData(_ data: Data, transaction: SDSAnyWriteTransaction) { + owsFail("Not implemented.") + } + + public func lastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) -> Data? { + owsFail("Not implemented.") + } + public func processIncomingPaymentRequest(thread: TSThread, paymentRequest: TSPaymentRequest, transaction: SDSAnyWriteTransaction) { diff --git a/SignalShareExtension/ShareViewController.swift b/SignalShareExtension/ShareViewController.swift index bf2c7328bd..c974c23e86 100644 --- a/SignalShareExtension/ShareViewController.swift +++ b/SignalShareExtension/ShareViewController.swift @@ -61,7 +61,10 @@ public class ShareViewController: UIViewController, ShareViewDelegate, SAEFailed } // We shouldn't set up our environment until after we've consulted isReadyForAppExtensions. - AppSetup.setupEnvironment(appSpecificSingletonBlock: { + AppSetup.setupEnvironment( + paymentsEvents: PaymentsEventsAppExtension(), + mobileCoinHelper: MobileCoinHelperMinimal(), + appSpecificSingletonBlock: { // Create SUIEnvironment. SUIEnvironment.shared.setup() SSKEnvironment.shared.callMessageHandlerRef = NoopCallMessageHandler() diff --git a/SignalUI/Environment/Dependencies+SignalUI.swift b/SignalUI/Environment/Dependencies+SignalUI.swift index 2159fb276a..578ef434b6 100644 --- a/SignalUI/Environment/Dependencies+SignalUI.swift +++ b/SignalUI/Environment/Dependencies+SignalUI.swift @@ -90,11 +90,19 @@ public extension Dependencies { public extension NSObject { final var paymentsSwift: PaymentsSwift { - SSKEnvironment.shared.paymentsRef as! PaymentsSwift + SUIEnvironment.shared.paymentsRef as! PaymentsSwift } static var paymentsSwift: PaymentsSwift { - SSKEnvironment.shared.paymentsRef as! PaymentsSwift + SUIEnvironment.shared.paymentsRef as! PaymentsSwift + } + + final var paymentsImpl: PaymentsImpl { + SUIEnvironment.shared.paymentsRef as! PaymentsImpl + } + + static var paymentsImpl: PaymentsImpl { + SUIEnvironment.shared.paymentsRef as! PaymentsImpl } } @@ -103,10 +111,18 @@ public extension NSObject { public extension Dependencies { var paymentsSwift: PaymentsSwift { - SSKEnvironment.shared.paymentsRef as! PaymentsSwift + SUIEnvironment.shared.paymentsRef as! PaymentsSwift } static var paymentsSwift: PaymentsSwift { - SSKEnvironment.shared.paymentsRef as! PaymentsSwift + SUIEnvironment.shared.paymentsRef as! PaymentsSwift + } + + var paymentsImpl: PaymentsImpl { + SUIEnvironment.shared.paymentsRef as! PaymentsImpl + } + + static var paymentsImpl: PaymentsImpl { + SUIEnvironment.shared.paymentsRef as! PaymentsImpl } } diff --git a/SignalUI/Payments/MobileCoinAPI.swift b/SignalUI/Payments/MobileCoinAPI.swift index 6db70d2b69..1d46e39472 100644 --- a/SignalUI/Payments/MobileCoinAPI.swift +++ b/SignalUI/Payments/MobileCoinAPI.swift @@ -67,7 +67,7 @@ public class MobileCoinAPI: Dependencies { throw PaymentsError.invalidEntropy } - owsAssertDebug(Self.payments.arePaymentsEnabled) + owsAssertDebug(Self.paymentsHelper.arePaymentsEnabled) self.paymentsEntropy = paymentsEntropy self.localAccount = localAccount diff --git a/SignalUI/Payments/PaymentsImpl.swift b/SignalUI/Payments/PaymentsImpl.swift index f28340a410..1fd59fc2d7 100644 --- a/SignalUI/Payments/PaymentsImpl.swift +++ b/SignalUI/Payments/PaymentsImpl.swift @@ -32,6 +32,44 @@ public class PaymentsImpl: NSObject, PaymentsSwift { } MobileCoinAPI.configureSDKLogging() + + AppReadiness.runNowOrWhenAppDidBecomeReadyAsync { + DispatchQueue.global().async { + self.updateLastKnownLocalPaymentAddressProtoDataIfNecessary() + } + } + } + + private func updateLastKnownLocalPaymentAddressProtoDataIfNecessary() { + guard tsAccountManager.isRegisteredAndReady else { + return + } + guard AppReadiness.isAppReady else { + return + } + + let appVersionKey = "appVersion" + let currentAppVersion4 = appVersion.currentAppVersion4 + + let shouldUpdate = Self.databaseStorage.read { (transaction: SDSAnyReadTransaction) -> Bool in + // Check if the app version has changed. + let lastAppVersion = self.keyValueStore.getString(appVersionKey, transaction: transaction) + guard lastAppVersion == currentAppVersion4 else { + return true + } + Logger.info("Skipping; lastAppVersion: \(String(describing: lastAppVersion)), currentAppVersion4: \(currentAppVersion4).") + return false + } + guard shouldUpdate else { + return + } + Logger.info("Updating last known local payment address.") + + databaseStorage.write { transaction in + self.updateLastKnownLocalPaymentAddressProtoData(transaction: transaction) + + self.keyValueStore.setString(currentAppVersion4, key: appVersionKey, transaction: transaction) + } } struct ApiHandle { @@ -118,6 +156,10 @@ public class PaymentsImpl: NSObject, PaymentsSwift { // MARK: - PaymentsState + public var paymentsState: PaymentsState { + paymentsHelper.paymentsState + } + public var arePaymentsEnabled: Bool { paymentsHelper.arePaymentsEnabled } @@ -440,6 +482,11 @@ public extension PaymentsImpl { return nil } } + + func updateLastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) { + let data: Data? = localPaymentAddressProtoData() + paymentsHelper.setLastKnownLocalPaymentAddressProtoData(data, transaction: transaction) + } } // MARK: - Current Balance @@ -775,7 +822,6 @@ public extension PaymentsImpl { if DebugFlags.paymentsIgnoreBadData.get() { Logger.warn("Missing or invalid mcReceiptData.") } else { - owsFailDebug("Missing or invalid mcReceiptData.") } return @@ -1093,6 +1139,14 @@ public class PaymentsEventsMainApp: NSObject, PaymentsEvents { payments.paymentsReconciliation.willUpdatePayment(paymentModel, transaction: transaction) } + public func updateLastKnownLocalPaymentAddressProtoData(transaction: SDSAnyWriteTransaction) { + payments.updateLastKnownLocalPaymentAddressProtoData(transaction: transaction) + } + + public func paymentsStateDidChange() { + payments.updateCurrentPaymentBalance() + } + public func clearState(transaction: SDSAnyWriteTransaction) { paymentsHelper.clearState(transaction: transaction) payments.clearState(transaction: transaction) diff --git a/SignalUI/Payments/PaymentsProcessor.swift b/SignalUI/Payments/PaymentsProcessor.swift index 223be577a8..ee524a0e37 100644 --- a/SignalUI/Payments/PaymentsProcessor.swift +++ b/SignalUI/Payments/PaymentsProcessor.swift @@ -100,7 +100,7 @@ public class PaymentsProcessor: NSObject { guard !CurrentAppContext().isRunningTests else { return } - guard Self.payments.arePaymentsEnabled else { + guard Self.paymentsHelper.arePaymentsEnabled else { return } guard AppReadiness.isAppReady, diff --git a/SignalUI/Payments/PaymentsReconciliation.swift b/SignalUI/Payments/PaymentsReconciliation.swift index 3ea272f80c..082880ea7e 100644 --- a/SignalUI/Payments/PaymentsReconciliation.swift +++ b/SignalUI/Payments/PaymentsReconciliation.swift @@ -58,7 +58,7 @@ public class PaymentsReconciliation: Dependencies { guard !CurrentAppContext().isRunningTests else { return false } - guard Self.payments.arePaymentsEnabled else { + guard Self.paymentsHelper.arePaymentsEnabled else { return false } guard AppReadiness.isAppReady,