# Manage Wallets

An agent needs a secure persistent place to store their cryptographic keys, credentials, protocol data and more. Before using most agent APIs, a wallet must be created and opened for usage. The important wallet management functionality is highlighted below.

Note that all "wallet" functionality is found under the agent's `WalletModule` implementation (within `agent.wallet`).

## Creating a Wallet

To effectively manage a user's DI data, a wallet must be created to securely store that data.

Each wallet must be created with a unique `id` along with a secure `passphrase`. To create a new wallet on the user's device, call the `wallet.create` method with those parameters. The chosen unique `id` should be remembered by consuming apps, as it is required to [open the wallet](#opening-a-wallet).

Configurable `id`s allow for developers to create "multi-wallet" applications if desired.

The chosen passphrase is used to encrypt the wallet's data, and as such, should be a secure value. Passphrase's also cannot be changed after wallet creation. Due to these reasons, an application may wish to consider a flow such as:&#x20;

1. Randomly generate a secure permanent passphrase for the wallet, &#x20;
2. Store this passphrase in the app's secure device storage,&#x20;
3. add some "user friendly" authentication to the app to protect access to the passphrase: e.g. biometrics etc.

{% tabs %}
{% tab title="Swift" %}

<pre class="language-swift"><code class="lang-swift"><strong>let id: String // the unique id for the wallet
</strong><strong>let passphrase: String // the secure passphrase used to open the wallet
</strong><strong>let agent: SudoDIEdgeAgent // the instantiated agent
</strong><strong>
</strong><strong>let walletConfiguration = WalletConfiguration(id: id, passphrase: passphrase)
</strong>do {
    try await agent.wallet.create(walletConfiguration: walletConfiguration)
} catch {
    // handle error
}
</code></pre>

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val id: String // Unique wallet identifier
val passphrase: String // Secure passphrase
val agent: SudoDIEdgeAgent // Instantiated agent

launch {
    try {
        val walletConfig = WalletConfiguration(id, passphrase)
        agent.wallet.create(walletConfig)
    } catch (e: WalletModule.CreateException) {
        // Handle exception
    }
}
```

{% endtab %}
{% endtabs %}

## Opening a Wallet

To access and manage the data within a wallet, it must first be opened successfully by calling `agent.open` with the correct `id` and `passphrase` used when the wallet was created. If the wallet is not successfully opened, an exception/error will be thrown.

{% tabs %}
{% tab title="Swift" %}

```swift
let id: String // the existing id of the wallet
let passphrase: String // the existing passphrase used to open the wallet
let agent: SudoDIEdgeAgent // the instantiated agent

let walletConfiguration = WalletConfiguration(id: id, passphrase: passphrase)
do {
    try await agent.wallet.open(walletConfiguration: walletConfiguration)
} catch {
    // handle error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val id: String // Existing wallet identifier
val passphrase: String // Secure passphrase
val agent: SudoDIEdgeAgent // Instantiated agent

launch {
    try {
        val walletConfig = WalletConfiguration(id, passphrase)
        agent.wallet.open(walletConfig)
    } catch (e: WalletModule.OpenException) {
        // Handle exception
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
An instance of `SudoDIEdgeAgent` can only have 1 wallet open at a time. To "switch wallets", close the current wallet and re-open a different one.
{% endhint %}

## Closing a Wallet

The currently open wallet can be closed by calling `wallet.close`. Closing a wallet will disallow read and write operations to the wallet until it is subsequently opened again. A wallet may be deleted once closed via the `wallet.delete` API.&#x20;

{% tabs %}
{% tab title="Swift" %}

```swift
let agent: SudoDIEdgeAgent // the instantiated agent

do {
    try await agent.wallet.close()
} catch {
    // handle error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val agent: SudoDIEdgeAgent // Instantiated agent

launch {
    try {
        agent.wallet.close()
    } catch (e: WalletModule.CloseException) {
        // Handle exception
    }
}
```

{% endtab %}
{% endtabs %}

## Deleting a Wallet

To delete a wallet from storage on the user's device, call `wallet.delete` with the `id` and `passphrase` that was used to originally create the wallet. Deleting the wallet will erase all of the user's DI data within that wallet. The wallet must be closed before deleting it.

{% tabs %}
{% tab title="Swift" %}

```swift
let id: String // the existing id of the wallet
let passphrase: String // the existing passphrase used to open the wallet
let agent: SudoDIEdgeAgent // the instantiated agent

do {
    let walletConfiguration = WalletConfiguration(id: id, passphrase: passphrase)
    try await agent.wallet.delete(walletConfiguration: walletConfiguration)
} catch {
    // handle error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val id: String = // Existing wallet identifier
val passphrase: String // Secure passphrase
val agent: SudoDIEdgeAgent = // Instantiated agent

launch {
    try {
        val walletConfig = WalletConfiguration(id, passphrase)
        agent.wallet.delete(walletConfig)
    } catch (e: WalletModule.DeleteException) {
        // Handle exception
    }
}
```

{% endtab %}
{% endtabs %}

## Check if a Wallet Exists

The existence of a wallet identified by `id` can be checked using `wallet.exists`.

{% tabs %}
{% tab title="Swift" %}

```swift
let id: String // the id of the wallet
let agent: SudoDIEdgeAgent // the instantiated agent

do {
    let exists = try await agent.wallet.exists(walletId: id)
    if exists {
        // handle wallet existing
    } else {
        // handle wallet not existing
    }
} catch {
    // handle error
}
```

{% endtab %}

{% tab title="Kotlin" %}

```kotlin
val id: String = // Wallet identifier
val agent: SudoDIEdgeAgent = // Instantiated agent

launch {
    try {
        val exists: Boolean = agent.wallet.exists(id)
        if (exists) {
            // Handle wallet existing
        } else {
            // Handle wallet not existing
        }
    } catch (e: WalletModule.ExistsException) {
        // Handle/notify user of exception
    }
}
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Note that all `wallet` module operations are performed within the environment of the `storageDirectory` selected during [agent configuration](https://docs.sudoplatform.com/guides/decentralized-identity/decentralized-identity/agent-management#configuration). As such, custom behavior with changing `storageDirectory` may lead to wallets no longer "existing" according to the API (until the original `storageDirectory` is chosen again).
{% endhint %}
