> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# State and events

> Observe checkout state changes using AsyncStream and the onCompletion callback

Primer Checkout communicates state through two mechanisms: `AsyncStream` for continuous observation and `onCompletion` for the final payment result.

## Checkout state lifecycle

```mermaid theme={"dark"}
stateDiagram-v2
    [*] --> initializing
    initializing --> ready
    ready --> success
    ready --> failure
    success --> dismissed
    failure --> dismissed
    dismissed --> [*]
```

## PrimerCheckoutState

The top-level checkout state, observed via `PrimerCheckoutScope.state`:

| State                               | Description                                      |
| ----------------------------------- | ------------------------------------------------ |
| `.initializing`                     | SDK is loading configuration and payment methods |
| `.ready(totalAmount:currencyCode:)` | Checkout is ready for user interaction           |
| `.success(PaymentResult)`           | Payment completed successfully                   |
| `.failure(PrimerError)`             | Payment failed                                   |
| `.dismissed`                        | Checkout was dismissed                           |

### Observing checkout state

```swift theme={"dark"}
PrimerCheckout(
  clientToken: clientToken,
  scope: { checkoutScope in
    Task {
      for await state in checkoutScope.state {
        switch state {
        case .initializing:
          print("Loading checkout...")
        case .ready(let totalAmount, let currencyCode):
          print("Ready: \(totalAmount) \(currencyCode)")
        case .success(let result):
          print("Success: \(result.payment?.id ?? "")")
        case .failure(let error):
          print("Failed: \(error.errorId)")
        case .dismissed:
          print("Dismissed")
        }
      }
    }
  }
)
```

## onCompletion callback

The `onCompletion` callback fires when the checkout reaches a terminal state (success, failure, or dismissed):

```swift theme={"dark"}
PrimerCheckout(
  clientToken: clientToken,
  onCompletion: { state in
    switch state {
    case .success(let result):
      navigateToConfirmation(result: result)
    case .failure(let error):
      logError(error)
    case .dismissed:
      navigateBack()
    default:
      break
    }
  }
)
```

<Note>
  `onCompletion` receives the same `PrimerCheckoutState` enum as the `AsyncStream`. Use `onCompletion` when you only need to react to the final result, and `AsyncStream` when you need to track intermediate states.
</Note>

## Payment method scope states

Each payment method scope has its own state type:

### PrimerCardFormState

```swift theme={"dark"}
Task {
  let cardFormScope: PrimerCardFormScope = checkoutScope.getPaymentMethodScope(PrimerCardFormScope.self)!
  for await state in cardFormScope.state {
    print("Valid: \(state.isValid)")
    print("Loading: \(state.isLoading)")
    print("Fields: \(state.displayFields)")
    if let network = state.selectedNetwork {
      print("Network: \(network)")
    }
  }
}
```

| Property            | Type                       | Description                                 |
| ------------------- | -------------------------- | ------------------------------------------- |
| `isValid`           | `Bool`                     | Whether all required fields pass validation |
| `isLoading`         | `Bool`                     | Whether the form is submitting              |
| `fieldErrors`       | `[FieldError]`             | Current validation errors                   |
| `selectedNetwork`   | `PrimerCardNetwork?`       | Detected card network                       |
| `availableNetworks` | `[PrimerCardNetwork]`      | Available card networks for co-badged cards |
| `displayFields`     | `[PrimerInputElementType]` | Fields to display based on configuration    |
| `selectedCountry`   | `PrimerCountry?`           | Selected country for billing address        |

## See also

<CardGroup cols={2}>
  <Card title="Scopes overview" icon="diagram-project" href="/sdk/ios-checkout/v3.0.0-beta/configuration/scopes-overview">
    All available scopes and their relationships
  </Card>

  <Card title="Handle payment result" icon="arrow-right" href="/sdk/ios-checkout/v3.0.0-beta/guides-and-recipes/handle-payment-result">
    Navigate after payment completion
  </Card>

  <Card title="Error handling" icon="triangle-exclamation" href="/checkout/primer-checkout/build-your-ui/error-handling">
    Handle validation and payment errors
  </Card>
</CardGroup>
