Skip to main content

Overview

The Turnkey Swift SDK provides a straightforward way to create and manage wallets in your Swift application. You can create wallets, derive accounts, import/export, and refresh wallet state from TurnkeyContext. Before you start, make sure you’re familiar with Wallets and Wallet Accounts.

Creation

There are two ways to create wallets and accounts:
  • During signup (sub-organization creation): Configure default wallet/accounts in your signup parameters so users get a wallet at account creation time. See Sub-organization customization for how to set CreateSubOrgParams globally or per auth method.
  • After authentication (active session): Create wallets programmatically using the TurnkeyContext once the user is authenticated.

Wallet

Create a wallet with one Ethereum account using an active session:
CreateWalletButton.swift
import SwiftUI
import TurnkeySwift

struct CreateWalletButton: View {
  @EnvironmentObject private var turnkey: TurnkeyContext

  var body: some View {
    Button("Create Wallet") {
      Task {
        do {
          let accounts: [WalletAccountParams] = [
            WalletAccountParams(
              addressFormat: .address_format_ethereum,
              curve: .curve_secp256k1,
              path: "m/44'/60'/0'/0/0",
              pathFormat: .path_format_bip32
            )
          ]
          try await turnkey.createWallet(
            walletName: "My New Wallet",
            accounts: accounts
          )
        } catch {
          print("Error creating wallet:", error)
        }
      }
    }
  }
}

Wallet accounts

You can derive additional addresses for an existing wallet using the HTTP client:
import TurnkeyHttp
import TurnkeyTypes
import TurnkeySwift

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let newAccounts: [WalletAccountParams] = [
  WalletAccountParams(
    addressFormat: .address_format_ethereum,
    curve: .curve_secp256k1,
    path: "m/44'/60'/0'/0/1",
    pathFormat: .path_format_bip32
  )
]

_ = try await client.createWalletAccounts(TCreateWalletAccountsBody(
  organizationId: orgId,
  accounts: newAccounts,
  walletId: "<wallet_id_here>"
))

Private keys

Private keys are typically created when creating wallet accounts or by importing existing key material. See Importing → Private key.

Listing wallets in the UI

The TurnkeyContext maintains wallets for the active session. You can render them in your views:
import SwiftUI
import TurnkeySwift

struct WalletList: View {
  @EnvironmentObject private var turnkey: TurnkeyContext

  var body: some View {
    List(turnkey.wallets, id: \.walletId) { wallet in
      VStack(alignment: .leading) {
        Text(wallet.walletName)
        Text(wallet.walletId).font(.caption).foregroundColor(.gray)
      }
    }
  }
}

Refreshing wallets

Call refreshWallets() to re-fetch wallets and accounts for the current session:
Task {
  try? await turnkey.refreshWallets()
}

Exporting

The Swift SDK lets you securely import/export wallets, accounts, and private keys. You can return decrypted values for developer workflows or handle encrypted bundles explicitly.

Wallet

Default: decrypt locally and return the mnemonic (developer-friendly).
import TurnkeySwift

let mnemonic = try await turnkey.exportWallet(walletId: "<wallet_id>")
// Do not display secrets in production UIs

Wallet account

import TurnkeyHttp
import TurnkeyCrypto
import TurnkeySwift

let (targetPublicKey, _, _) = TurnkeyCrypto.generateP256KeyPair()

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let resp = try await client.exportWalletAccount(TExportWalletAccountBody(
  organizationId: orgId,
  address: "<wallet_account_address>",
  targetPublicKey: targetPublicKey
))

let exportBundle = resp.exportBundle

Private key

import TurnkeyHttp
import TurnkeyCrypto
import TurnkeySwift

let (targetPublicKey, _, _) = TurnkeyCrypto.generateP256KeyPair()

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let resp = try await client.exportPrivateKey(TExportPrivateKeyBody(
  organizationId: orgId,
  privateKeyId: "<private_key_id>",
  targetPublicKey: targetPublicKey
))

let exportBundle = resp.exportBundle

Importing

Wallet

Imports a wallet from a mnemonic and automatically refreshes local state.
import TurnkeySwift

let accounts: [WalletAccountParams] = [
  WalletAccountParams(
    addressFormat: .address_format_ethereum,
    curve: .curve_secp256k1,
    path: "m/44'/60'/0'/0/0",
    pathFormat: .path_format_bip32
  )
]

let walletId = try await turnkey.importWallet(
  walletName: "Imported Wallet",
  mnemonic: "<mnemonic>",
  accounts: accounts
)

Private key

Imports a private key from plaintext key material and automatically refreshes local state.
import TurnkeyHttp
import TurnkeySwift

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let resp = try await client.importPrivateKey(TImportPrivateKeyBody(
  organizationId: orgId,
  privateKey: "<hex-or-base58-key>",
  privateKeyName: "My Key",
  addressFormats: [.address_format_ethereum]
))
let privateKeyId = resp.privateKeyId

Deleting

If a wallet, wallet account, or private key has not been exported, you must either export it first or pass the deleteWithoutExport: true flag in the delete request.

Wallet

import TurnkeyHttp
import TurnkeyTypes
import TurnkeySwift

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let deleteResp = try await client.deleteWallets(TDeleteWalletsBody(
  organizationId: orgId,
  deleteWithoutExport: true, // set to true if the wallet hasn't been exported
  walletIds: ["<wallet_id_1>", "<wallet_id_2>"]
))

let removedWalletIds = deleteResp.walletIds

Wallet accounts

import TurnkeyHttp
import TurnkeyTypes
import TurnkeySwift

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let deleteResp = try await client.deleteWalletAccounts(TDeleteWalletAccountsBody(
  organizationId: orgId,
  deleteWithoutExport: true, // set to true if the accounts haven't been exported
  walletAccountIds: ["<wallet_account_id_1>", "<wallet_account_id_2>"]
))

let removedAccountIds = deleteResp.walletAccountIds

Private keys

import TurnkeyHttp
import TurnkeyTypes
import TurnkeySwift

guard
  let client = TurnkeyContext.shared.client,
  let orgId = TurnkeyContext.shared.session?.organizationId
else { return }

let deleteResp = try await client.deletePrivateKeys(TDeletePrivateKeysBody(
  organizationId: orgId,
  deleteWithoutExport: true, // set to true if the keys haven't been exported
  privateKeyIds: ["<private_key_id_1>", "<private_key_id_2>"]
))

let removedKeyIds = deleteResp.privateKeyIds