From 5eb4b32faf6b92729794257f4c75b17c2916c99a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Martins?= Date: Thu, 11 Dec 2025 12:37:15 -0300 Subject: [PATCH 1/5] Added TrackingConsent enum --- Sources/Logger/TrackingConsent.swift | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Sources/Logger/TrackingConsent.swift diff --git a/Sources/Logger/TrackingConsent.swift b/Sources/Logger/TrackingConsent.swift new file mode 100644 index 0000000..8f301be --- /dev/null +++ b/Sources/Logger/TrackingConsent.swift @@ -0,0 +1,19 @@ +// +// TrackingConsent.swift +// CrossmintSDK +// +// Created by Tomas Martins on 11/12/25. +// + +import Foundation +import DatadogCore + +/// Tracking consent states for remote logging (GDPR compliance) +public enum TrackingConsent: Sendable { + /// The SDK starts collecting and batching the data but does not send it to the remote logging endpoint. + case pending + /// The SDK starts collecting the data and sends it to the remote logging endpoint. + case granted + /// The SDK does not collect any data for remote logging. + case notGranted +} From 5b480a9bcf388e14603b3fbe2121fdbbfb5b9606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Martins?= Date: Thu, 11 Dec 2025 13:59:10 -0300 Subject: [PATCH 2/5] Added setTrackingConsent to DataDogConfig --- Sources/Logger/DataDogConfig.swift | 32 ++++++++++++++++++++++++++++ Sources/Logger/TrackingConsent.swift | 1 - 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/Sources/Logger/DataDogConfig.swift b/Sources/Logger/DataDogConfig.swift index f300045..12d72ab 100644 --- a/Sources/Logger/DataDogConfig.swift +++ b/Sources/Logger/DataDogConfig.swift @@ -6,13 +6,45 @@ // import Foundation +import DatadogCore public enum DataDogConfig { static let clientToken = "pub946d87ea0c2cc02431c15e9446f776fc" private(set) nonisolated(unsafe) static var environment: String = "production" + private(set) nonisolated(unsafe) static var trackingConsent: TrackingConsent = .notGranted + private(set) nonisolated(unsafe) static var isDataDogInitialized: Bool = false public static func configure(environment: String) { self.environment = environment } + + /// Sets or updates the tracking consent for remote logging + /// - Parameter consent: The new tracking consent state + /// - Note: When changing from pending to granted, all batched data will be sent. + /// When changing from pending to notGranted, all batched data will be wiped. + /// Safe to call before or after DataDog initialization. + public static func setTrackingConsent(_ consent: TrackingConsent) { + self.trackingConsent = consent + + // Only update DataDog if it's already initialized + if isDataDogInitialized { + Datadog.set(trackingConsent: datadogConsent(for: consent)) + } + } + + static func markDataDogInitialized() { + isDataDogInitialized = true + } + + static func datadogConsent(for consent: TrackingConsent) -> DatadogCore.TrackingConsent { + switch consent { + case .pending: + return .pending + case .granted: + return .granted + case .notGranted: + return .notGranted + } + } } diff --git a/Sources/Logger/TrackingConsent.swift b/Sources/Logger/TrackingConsent.swift index 8f301be..aa0112e 100644 --- a/Sources/Logger/TrackingConsent.swift +++ b/Sources/Logger/TrackingConsent.swift @@ -6,7 +6,6 @@ // import Foundation -import DatadogCore /// Tracking consent states for remote logging (GDPR compliance) public enum TrackingConsent: Sendable { From 1e1e4efcc3acd612e017aa336ea6836dc60b1511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Martins?= Date: Thu, 11 Dec 2025 14:01:20 -0300 Subject: [PATCH 3/5] Set DD tracking consent on DataDogLoggerProvider --- Sources/Logger/DataDogLoggerProvider.swift | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Sources/Logger/DataDogLoggerProvider.swift b/Sources/Logger/DataDogLoggerProvider.swift index 70209f7..abef986 100644 --- a/Sources/Logger/DataDogLoggerProvider.swift +++ b/Sources/Logger/DataDogLoggerProvider.swift @@ -10,8 +10,6 @@ import DatadogCore import DatadogLogs final class DataDogLoggerProvider: LoggerProvider { - private nonisolated(unsafe) static var isDataDogInitialized: Bool = false - private let logger: LoggerProtocol private let service: String @@ -60,7 +58,7 @@ final class DataDogLoggerProvider: LoggerProvider { } private static func setupDataDogIfNeeded(clientToken: String, environment: String) { - guard !isDataDogInitialized else { return } + guard !DataDogConfig.isDataDogInitialized else { return } Datadog.initialize( with: Datadog.Configuration( @@ -68,11 +66,11 @@ final class DataDogLoggerProvider: LoggerProvider { env: environment, service: "crossmint-ios-sdk" ), - trackingConsent: .granted + trackingConsent: DataDogConfig.datadogConsent(for: DataDogConfig.trackingConsent) ) Logs.enable() - isDataDogInitialized = true + DataDogConfig.markDataDogInitialized() } } From 9b475a7abf21bd2c3a942dfcb93a934256c6123d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Martins?= Date: Thu, 11 Dec 2025 14:02:13 -0300 Subject: [PATCH 4/5] Added tracking consent to CrossmintSDK --- .../SwiftUI/CrossmintSDK.swift | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift b/Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift index 5631dd3..9027bbe 100644 --- a/Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift +++ b/Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift @@ -2,7 +2,7 @@ import CrossmintAuth import Combine @_exported import CrossmintCommonTypes @_exported import CrossmintService -import Logger +@_exported import Logger import SwiftUI import Utils @_exported import Wallet @@ -26,14 +26,15 @@ final public class CrossmintSDK: ObservableObject { public static func shared( apiKey: String, authManager: AuthManager? = nil, - logLevel: OSLogType = .default + logLevel: OSLogType = .default, + trackingConsent: TrackingConsent ) -> CrossmintSDK { if let existing = _shared { return existing } Logger.level = logLevel - let newInstance = CrossmintSDK(apiKey: apiKey, authManager: authManager) + let newInstance = CrossmintSDK(apiKey: apiKey, authManager: authManager, trackingConsent: trackingConsent) _shared = newInstance return newInstance } @@ -64,7 +65,7 @@ final public class CrossmintSDK: ObservableObject { #if DEBUG if let apiKey = ProcessInfo.processInfo.environment["CROSSMINT_API_KEY"] { Logger.client.info("Using API key from the environment variable.") - self.init(apiKey: apiKey) + self.init(apiKey: apiKey, trackingConsent: .notGranted) return } #endif @@ -72,12 +73,14 @@ final public class CrossmintSDK: ObservableObject { fatalError("Crossmint SDK requires an API key. Please call CrossmintSDK.shared(apiKey:) before accessing CrossmintSDK.shared") } - private init(apiKey: String, authManager: AuthManager? = nil) { + private init(apiKey: String, authManager: AuthManager? = nil, trackingConsent: TrackingConsent) { sdkInstances += 1 if sdkInstances > 1 { Logger.sdk.error("Multiple SDK instances created, behaviour is undefined") } + DataDogConfig.setTrackingConsent(trackingConsent) + do { sdk = try CrossmintClient.sdk(key: apiKey, authManager: authManager) let authManager = sdk.authManager @@ -96,6 +99,15 @@ final public class CrossmintSDK: ObservableObject { } } + /// Sets or updates the tracking consent for remote logging + /// - Parameter consent: The new tracking consent state + /// - Note: When changing from pending to granted, all batched data will be sent. + /// When changing from pending to notGranted, all batched data will be wiped. + /// This only affects remote logs; local os.log entries will continue to be displayed. + public func setTrackingConsent(_ consent: TrackingConsent) { + DataDogConfig.setTrackingConsent(consent) + } + public func logout() async throws { crossmintTEE.resetState() } From 5b574c888904965bf785afbb7bb942774d12c9dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Martins?= Date: Thu, 11 Dec 2025 14:15:16 -0300 Subject: [PATCH 5/5] Updated SmartWallets and Solana demo apps --- .../SmartWalletsDemo/SmartWalletsDemoApp.swift | 6 +++++- Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Examples/SmartWalletsDemo/SmartWalletsDemo/SmartWalletsDemoApp.swift b/Examples/SmartWalletsDemo/SmartWalletsDemo/SmartWalletsDemoApp.swift index 603e0bf..461ec58 100644 --- a/Examples/SmartWalletsDemo/SmartWalletsDemo/SmartWalletsDemoApp.swift +++ b/Examples/SmartWalletsDemo/SmartWalletsDemo/SmartWalletsDemoApp.swift @@ -7,7 +7,11 @@ struct SmartWalletsDemoApp: App { WindowGroup { SplashScreen() .crossmintNonCustodialSigner( - CrossmintSDK.shared(apiKey: crossmintApiKey, authManager: crossmintAuthManager) + CrossmintSDK.shared( + apiKey: crossmintApiKey, + authManager: crossmintAuthManager, + trackingConsent: .granted + ) ) } } diff --git a/Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift b/Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift index 7bf3f81..ec38d8e 100644 --- a/Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift +++ b/Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift @@ -7,7 +7,12 @@ struct SolanaDemoApp: App { WindowGroup { SplashScreen() .crossmintNonCustodialSigner( - CrossmintSDK.shared(apiKey: crossmintApiKey, authManager: crossmintAuthManager, logLevel: .debug) + CrossmintSDK.shared( + apiKey: crossmintApiKey, + authManager: crossmintAuthManager, + logLevel: .debug, + trackingConsent: .granted + ) ) } }