OZCredentialManager

public final class OZCredentialManager : OZCredentialManagerProtocol, @unchecked Sendable

Manages the lifecycle of stored Smart Account credentials.

OZCredentialManager provides operations for creating, querying, updating, and deleting stored credentials, and for reconciling local credential state with on-chain deployment status. The manager is the only supported entry point for the application-visible side of credential storage; lower-level access goes through the underlying OZStorageAdapter.

Credential State Machine

pending --[deploy success]------------------> credential DELETED from storage
pending --[deploy failure]------------------> failed (deploymentError set)
pending --[sync discovers contract on-chain]-> credential DELETED from storage
failed  --[deleteCredential]-----------------> credential DELETED from storage

After successful deployment (or sync discovery), credentials are removed from local storage. Reconnection works through sessions or the indexer. Failed deployments can be retried by deleting the credential and creating a new one with the same identifier.

Usage

let manager = kit.credentialManager

// Get all credentials.
let all = try await manager.getAllCredentials()

// Get pending and failed credentials.
let pending = try await manager.getPendingCredentials()

// Sync a credential with on-chain state (deletes if deployed).
let isDeployed = try await manager.sync(credentialId: "base64url-id")

// Delete a pending credential.
try await manager.deleteCredential(credentialId: "base64url-id")

Public API: Create

  • Creates a new pending credential and persists it to storage.

    The credential is created with deployment status pending, isPrimary set to false (the wallet-creation flow is responsible for promoting a credential to primary), and createdAt set to the current wall-clock time in milliseconds since the Unix epoch.

    Validation

    • publicKey must be exactly secp256r1PublicKeySize bytes (uncompressed secp256r1).
    • credentialId must not be empty.
    • credentialId must be unique (no existing credential may share the identifier).

    Throws

    Throws:

    Declaration

    Swift

    public func createPendingCredential(
        credentialId: String,
        publicKey: Data,
        contractId: String,
        nickname: String? = nil,
        transports: [String]? = nil,
        deviceType: String? = nil,
        backedUp: Bool? = nil
    ) async throws -> OZStoredCredential

    Parameters

    credentialId

    Base64URL-encoded credential identifier (must be unique and non-empty).

    publicKey

    Uncompressed secp256r1 public key (secp256r1PublicKeySize bytes).

    contractId

    Smart account contract address (C… strkey).

    nickname

    Optional user-friendly display name.

    transports

    Optional WebAuthn transport hints (e.g. "usb", "nfc", "ble", "internal").

    deviceType

    Optional authenticator device type ("singleDevice" or "multiDevice").

    backedUp

    Optional flag indicating whether the passkey is backed up or synced.

    Return Value

    The persisted OZStoredCredential.

  • Saves a credential directly to storage with looser validation than createPendingCredential(credentialId:publicKey:contractId:nickname:transports:deviceType:backedUp:).

    Unlike the create path this method does not check for duplicates, does not capture deployment-time WebAuthn metadata (transports, deviceType, backedUp), and persists isPrimary = false. A nil contractId is stored as the empty string to mirror the on-chain “not yet derived” sentinel used by other call sites.

    Validation

    Throws

    Throws:

    Declaration

    Swift

    public func saveCredential(
        credentialId: String,
        publicKey: Data,
        nickname: String? = nil,
        contractId: String? = nil
    ) async throws -> OZStoredCredential

    Parameters

    credentialId

    Base64URL-encoded credential identifier.

    publicKey

    Uncompressed secp256r1 public key (secp256r1PublicKeySize bytes).

    nickname

    Optional user-friendly display name.

    contractId

    Optional smart account contract address. nil is stored as the empty string.

    Return Value

    The persisted OZStoredCredential.

Public API: Sync

  • sync(credentialId:) Asynchronous

    Synchronises a single credential with on-chain contract state.

    Queries the contract instance for the credential’s contractId via Soroban RPC. When the contract instance exists the credential is removed from local storage (deployment is confirmed) and the method returns true. When the contract instance does not exist, when the credential has no associated contractId, or when the on-chain check fails for any reason (transport error, parse error, RPC error), the method returns false without throwing.

    The on-chain check intentionally swallows errors: a pending-credentials sweep needs a binary answer, not a failure mode. The credential remains in storage in any non-deployed outcome.

    Throws

    • NotFound when no credential with the supplied identifier exists in storage.
    • ReadFailed when reading the credential fails.

    Declaration

    Swift

    @discardableResult
    public func sync(credentialId: String) async throws -> Bool

    Parameters

    credentialId

    Identifier of the credential to sync.

    Return Value

    true when the contract is deployed and the credential was removed from local storage, otherwise false.

  • syncAll() Asynchronous

    Synchronises every stored credential with on-chain contract state.

    Iterates the full credential set, invoking sync(credentialId:) for each entry. Deployed credentials are removed from storage (and counted as deployed); failed credentials are counted as failed; everything else is counted as pending.

    Throws

    ReadFailed when reading the credential set fails.

    Declaration

    Swift

    public func syncAll() async throws -> OZSyncResult

    Return Value

    An OZSyncResult summarising the deployment status counts.

Public API: Delete

  • Deletes a pending credential from storage.

    Before deletion the manager runs sync(credentialId:) to confirm the contract has not been deployed on-chain. When the contract is already deployed the sync removes the credential and the deletion is rejected with Invalid because the wallet exists on-chain and the local entry is no longer authoritative.

    On successful deletion the manager emits a credentialDeleted(credentialId:) event.

    Throws

    • NotFound when no credential with the supplied identifier exists in storage.
    • Invalid when the credential is already deployed on-chain.
    • ReadFailed when reading the credential fails.
    • WriteFailed when deletion fails.

    Declaration

    Swift

    public func deleteCredential(credentialId: String) async throws

    Parameters

    credentialId

    Identifier of the credential to delete.

Public API: Query

  • Retrieves a stored credential by its identifier.

    Throws

    ReadFailed when reading fails.

    Declaration

    Swift

    public func getCredential(credentialId: String) async throws -> OZStoredCredential?

    Parameters

    credentialId

    Identifier of the credential to look up.

    Return Value

    The OZStoredCredential when present, otherwise nil.

  • Retrieves every credential associated with the supplied contract address.

    Throws

    ReadFailed when reading fails.

    Declaration

    Swift

    public func getCredentialsByContract(contractId: String) async throws -> [OZStoredCredential]

    Parameters

    contractId

    Contract address to filter by.

    Return Value

    Credentials whose contractId matches; empty when none match.

  • getAllCredentials() Asynchronous

    Retrieves every stored credential, regardless of deployment status or associated contract.

    Throws

    ReadFailed when reading fails.

    Declaration

    Swift

    public func getAllCredentials() async throws -> [OZStoredCredential]

    Return Value

    All stored credentials (empty when no credentials exist).

  • Retrieves every credential associated with the kit’s currently connected wallet.

    Returns an empty list when no wallet is connected. The connected contract is queried through the kit’s contractId accessor; concrete kits expose this through the Smart Account Kit’s connected-state API.

    Throws

    ReadFailed when reading fails.

    Declaration

    Swift

    public func getForConnectedWallet() async throws -> [OZStoredCredential]

    Return Value

    Credentials whose contractId matches the connected wallet’s contract address (empty when not connected or when no credentials match).

  • Retrieves every credential whose deployment status is pending or failed.

    Returned credentials have not been confirmed on-chain and may need attention (retry, sync, or delete).

    Throws

    ReadFailed when reading fails.

    Declaration

    Swift

    public func getPendingCredentials() async throws -> [OZStoredCredential]

    Return Value

    Credentials with status .pending or .failed (empty when none match).

Public API: Update

  • Updates the nickname of a stored credential.

    Overwrites the nickname when nickname is non-nil. Passing nil leaves the existing nickname unchanged (the partial-update path treats nil as a no-op). The credential must exist before the update; the manager does not create a new credential as a side effect.

    Throws

    Declaration

    Swift

    public func updateNickname(credentialId: String, nickname: String?) async throws

    Parameters

    credentialId

    Identifier of the credential to update.

    nickname

    New nickname, or nil to leave the existing nickname unchanged.

  • clearAll() Asynchronous

    Clears every credential from storage.

    This operation is irreversible. Use with caution.

    Throws

    WriteFailed when clearing fails.

    Declaration

    Swift

    public func clearAll() async throws