Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ struct SmartWalletsDemoApp: App {
WindowGroup {
SplashScreen()
.crossmintNonCustodialSigner(
CrossmintSDK.shared(apiKey: crossmintApiKey, authManager: crossmintAuthManager)
CrossmintSDK.shared(
apiKey: crossmintApiKey,
authManager: crossmintAuthManager,
trackingConsent: .granted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have two nits here:

  • If we change who we use for logging, or move away from datadog, we'll be forced to make a breaking change here
  • The user if they step into the code will see datadog documentation on granted vs notGranted vs pending -- we may have expanded use for this consent in the future, and we may want finer grained control over the documentation

)
)
}
}
Expand Down
7 changes: 6 additions & 1 deletion Examples/SolanaDemo/SolanaDemo/SolanaDemoApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
)
}
}
Expand Down
22 changes: 17 additions & 5 deletions Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Combine
@_exported import CrossmintCommonTypes
@_exported import CrossmintService
import Logger
@_exported import Logger
import SwiftUI
import Utils
@_exported import Wallet
Expand All @@ -26,14 +26,15 @@
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
}
Expand Down Expand Up @@ -64,20 +65,22 @@
#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
Logger.client.error("Crossmint SDK requires an API key")
fatalError("Crossmint SDK requires an API key. Please call CrossmintSDK.shared(apiKey:) before accessing CrossmintSDK.shared")

Check warning on line 73 in Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift

View workflow job for this annotation

GitHub Actions / Build and Test

Line Length Violation: Line should be 120 characters or less; currently it has 134 characters (line_length)

Check warning on line 73 in Sources/CrossmintClient/SwiftUI/CrossmintSDK.swift

View workflow job for this annotation

GitHub Actions / Build and Test

Line Length Violation: Line should be 120 characters or less; currently it has 134 characters (line_length)
}

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
Expand All @@ -96,6 +99,15 @@
}
}

/// 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()
}
Expand Down
32 changes: 32 additions & 0 deletions Sources/Logger/DataDogConfig.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
8 changes: 3 additions & 5 deletions Sources/Logger/DataDogLoggerProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -60,19 +58,19 @@ 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(
clientToken: clientToken,
env: environment,
service: "crossmint-ios-sdk"
),
trackingConsent: .granted
trackingConsent: DataDogConfig.datadogConsent(for: DataDogConfig.trackingConsent)
)

Logs.enable()

isDataDogInitialized = true
DataDogConfig.markDataDogInitialized()
}
}
18 changes: 18 additions & 0 deletions Sources/Logger/TrackingConsent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//
// TrackingConsent.swift
// CrossmintSDK
//
// Created by Tomas Martins on 11/12/25.
//

import Foundation

/// 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
}
Loading