# FrakClient

```swift
final class FrakClient
```

Everything the SDK can do. Obtained from `Frak.client`.

A concrete class, not a protocol: adding a member here is additive on both platforms,
where adding a requirement to a protocol invalidates every witness table built before
it. There is no supported way for a merchant to substitute a fake; point
`FrakEnvironment.custom(wallet:backend:)` at a stub server instead and exercise
the real client.

Capabilities are grouped into five namespaces — ``config``, ``rewards``, ``sharing``,
``tracking``, ``appLink`` — rather than kept flat, so the wallet-session cluster (SSO,
embedded wallet, pairing) can land as a new namespace without touching this one.

**Conforms to** `Swift.Sendable`

Defined in: [Sources/FrakSDK/FrakClient.swift:14](https://github.com/frak-id/wallet/blob/35995d05c807efe1e0d6319fdede3ad363124d1e/sdk/ios/Sources/FrakSDK/FrakClient.swift#L14)

## Properties

### anonymousId

```swift
var anonymousId: String? { get async }
```

Nil when tracking is disabled or the device refused key material.

### appLink

```swift
let appLink: AppLinkAPI
```

Inbound referral links and the wallet app handoff.

### config

```swift
let config: ConfigAPI
```

Config resolution and its live stream.

### environment

```swift
nonisolated var environment: FrakEnvironment { get }
```

The stage this client talks to. Merchants never set it directly, see `FrakConfig.env`.

### rewards

```swift
let rewards: RewardsAPI
```

Campaigns and the single best reward to advertise.

### sharing

```swift
let sharing: SharingAPI
```

Share link construction.

### tracking

```swift
let tracking: TrackingAPI
```

Interaction and purchase tracking.

## Methods

### isTrackingEnabled()

```swift
func isTrackingEnabled() async -> Bool
```

Whether tracking is currently allowed: `FrakConfig.trackingEnabled` AND the persisted
runtime decision. For a consent screen that has to render the current state, and for the
accountability record a data-protection authority asks for.

### resetAnonymousId()

```swift
@discardableResult func resetAnonymousId() async -> Bool
```

Destroys the keypair (next `anonymousId` read mints a new one) and purges the queue.

This is a local identity rotation, not an Art. 17 erasure: events already sent stay
attributed to the old id on Frak's side. Route an actual erasure request to
https://frak.id/account-deletion.

Returns false when erasure failed and the id did NOT rotate. On this platform the
underlying delete cannot fail, so this always returns true — the value exists to keep one
cross-platform contract for merchants writing shared erasure logic.

### setTrackingEnabled(_:)

```swift
func setTrackingEnabled(_ enabled: Bool) async
```

Turns tracking on or off at runtime, and persists the decision for this install. Call it
from your consent-management flow; call it as often as the user changes their mind.

`false` stops all tracking immediately and purges anything still queued. `true` re-enables
it **unless** this build ships `FrakConfig(trackingEnabled: false)`, which is a hard floor
a runtime call cannot lift.

This does **not** destroy the identity: a user who opts back in is still the same
`anonymousId`, which is what makes a temporary opt-out a pause rather than an amputation.
For a genuine withdrawal of consent, the recipe is both calls in this order:

```swift
await client.setTrackingEnabled(false)   // stop, and drop what is queued
await client.resetAnonymousId()          // then sever the device from the id
```

Purging the queue can discard purchase events that have not reached the backend yet. That
is deliberate — they were captured under a consent decision that no longer holds — but it
is a revenue consequence, not only a privacy one.