Wallet SDK initialisation

The first steps in the apps life cycle that have to be done is to initialise the wallet SDK. So the wallet SDK is ready to

To initialise the wallet SDK you have to import the SDK in your root navigation anchor e.g. AppViewModel, App struct or similar, which depends on how your project is setup. It is important to initialize it once at the app start of the application.

import wallet_sdk

let configuration = WalletSdkConfiguration(walletProviderUrl: "https://your_wallet_provider")
WalletSdk.shared.configure(config: configuration)

With the WalletSdkConfiguration you can pass needed information to the wallet SDK like the URL to your wallet provider, so the wallet SDK can contact the wallet provider e.g. for login or registration of a user so the use can activate the wallet application. The configuration - as already mentioned - should always happen at the app start and it should be done only once. After this the wallet SDK is ready to be used.

Wallet SDK usage

To use the wallet SDK in the application you always have to import it via

import wallet_sdk

Then you can access the wallet SDK’s functionality by the main entry point WalletSdk.shared that provides all the functions that the application can use.

WalletSdk.shared.someFunction()

Special objects

As the wallet SDK is developed as a Kotlin Multiplatform Project(KMP), it provides a ObjectiveC framework, which is enhanced with an additional Swift interface by Skie from Touchlabs. Therefore you will encounter objects like SkieSwiftFlowIterator and similar. These are helpers that are interoperable to async/await objects giving you the usual Swift possibilities of for example async/await. It’s also providing helper functions or enhanced enums like

enum ErrorEnum: Error {
    case general(value: Error)
    case noConnection
    case parsing(value: Error)
}

Since the ObjectiveC enums can not provide values in cases and also in Kotlin a normal enum can not do this, you will get a support function from Skie using such enums (Kotlin sealed classes) as a normal enum.

switch onEnum(of: wallet_sdk.SealedClassErrorExample) {
    case .generalError(let value):
        // ...
    case .noConnection:
        // ...
}

So you can use it as if it was a normal Swift Enum. In this case it may be a good approach to create a Swift enum and convert the sealed class to it.

enum ErrorEnum: Error {
    case general(value: Error)
    case noConnection
    case parsing(value: Error)

    static func from(value: wallet_sdk.SealedClassErrorExample) -> ErrorEnum {
        switch onEnum(of: value) {
            case .generalError(let value):
                return ErrorEnum.general(value)
            case .noConnection:
                return ErrorEnum.noConnection
            // ...
        }
    }
}

Wallet state (wallet lifecyle)

So the wallets Lifecycle can manage the displayable information to the user, the wallet provides the WalletState enum, which can be observed in the application and will be automatically updated by the wallet SDK. The WalletState will be provided through the WalletUnit object which capsules functionality for wallet unit actions.

To observe the WalletState you can implement it like

Task { @concurrent in
    for await value in WalletSdk.shared.walletUnit.state {
        await MainActor.run {
            switch value {
            case .installed:
                // ... e.g. logout user if he/she was logged in
            case .operational:
                // ...
            case .valid:
                // ...
            }
        }
    }
}

Which will give you an AsyncSequence that will observe value changes on the WalletState published by the wallet SDK.