# 3. Initializing the Wallet and Cloud Agent

High Level Overview of steps

1. Create a sponsor service/endpoint on your app's backend. A minimal sample can be found [here](/examples/simple-sponsor).
2. Ask Evernym to onboard you as a Sponsor. Check below for more details.
3. Complete mobile SDK [project setup guide](1.ProjectSetup.md) first.
4. Implement initialization logic for your application:
   1. Call your sponsor backend API (service set up in Step 1) to get provision token (once for the app).
   2. Call Evernym mobile SDK provision API with provided token to obtain a Cloud Agent (once for the app).
   3. Call Evernym mobile SDK to initialize library (every app run).

All the above steps are explained in detail in this document.

## Introduction

Using the Evernym mobile SDK currently requires that the SDK be connected to and rely on a cloud agent that is hosted and provisioned at Evernym. In the future, this Evernym cloud agent will be replaceable with your own or the one from a different vendor, but still usable with the Evernym Mobile SDK. This agent is used for its store-and-forward services, persistence and availability and ability to push notify to a device or forward via http to the appropriate sponsor. By default, Evernym’s hosted cloud services are locked down. In order for your mobile SDK instance to prove that it has permission to provision a new hosted cloud agent (one unique cloud agent per installation of your mobile app), you must provide a provisioning token.

To register as a sponsor, you will need to contact Evernym at [support@evernym.com](mailto:support@evernym.com)

## Definitions

- Sponsor \
   You are the sponsor. You as the `Sponsor` are the application owner using the mobile sdk to `Sponsor` individual app installs e.g. Example Credit Union is the `Sponsor` using the Evernym mobile SDK inside their own mobile app. Also `Sponsor` should have backend server that will perform token issuing. A sponsor provides a provision token so that their customers can provide authorization with Evernym's cloud agent.

    > **Example** Credit Union is the Sponsor using the Evernym mobile SDK inside their own mobile app.
  
- Sponsee \
    Your customer's individual App installation on mobile device.

    > **Example**  The app on Ryan’s phone is a Sponsee. He is an Example Credit Union member installing Example CU’s mobile app (`Sponsor`)  

- Evernym Cloud Service \
    Evernym hosted cloud service which facilitates provisioning and management of cloud agents.

- VCX Config: The list of options can be set in the config JSON passed to `vcx_get_provision_token` and `vcx_provision_agent_with_token` functions
    can be found in [the document](Configuration.md).

- Provision Token \
    This token is provided by you as a `Sponsor` to enable provisioning of one of your customers (`Sponsee`) on an Evernym hosted cloud agent.

    ```json
     {
       "sponseeId":     String,
       "sponsorId":     String,
       "nonce":         String,
       "timestamp":     String,
       "sig":           String,
       "sponsorVerKey": String,
     } 
    ```

    Provision Token Fields

    - `sponseeId`:
     An identifier you as a `Sponsor` use to identify/reference your customer the `Sponsee`. This can be a customer id used to identify the customer (`Sponsee`) in your (`Sponsor`) back end database. In other words, this is an ID of an app user.
    - `sponsorId`:
     An ID given to you from Evernym's Support Team after the `Sponsor` onboarding process is complete.  
    - `nonce`:
    Randomly generated string. Used as one-time security token during registration. \
    **Example**. `random.number.toString()`
    - `timestamp`:
    An RFC 3339 and ISO 8601 date and time string such as `1996-12-19T16:39:57-08:00`.
    - `sig`:
    You will provide a signature to your customer (the `Sponsee`) so that they can provision with Evernym's Cloud Agent. You (The `Sponsor`) will:  
        1. create a string by concatenating in this order `nonce + timeStamp + sponseeId + sponsorId`
        2. sign the resulting string with the keys registered during the onboarding process. The keys that match the configured `sponsorVerKey`.
        3. Base64 encode the result of the signature
    **Example** Base64Encode(Sign(nonce + timeStamp + sponseeId + sponsorId))
    - `sponsorVerKey`:
    This is the key you as the `Sponsor` provided to Evernym's support team during onboarding. You (`Sponsor`) can register multiple keys during onboarding so this identifies which key to use during authorization. This key is not used unless a corresponding one is found in the configuration.

## Sponsor server

In order to receive messages from other sides each application must have an associated Cloud Agent. 
The process of getting of a Cloud Agent consist of two steps:
1. Application call Sponsor Server to receive a provisioning token.
2. Application call SDK function to provision Cloud Agent with received token.

A simple Sponsor Server performing generation and signing of tokens which can be used for provisioning of a Cloud Agents can be found [here](/examples/simple-sponsor).

> Sponsor Server may also include additional logic like [Push Notifications](./PushNotifications.md) which is not demonstrated in the sample.

## Sponsor (i.e. You) Onboarding with Evernym's Cloud Service

- In order for you to register as a `Sponsor`, contact `support@evernym.com`.
- Onboarding/Registration requires you (the `Sponsor`) to provide these attributes to Evernym's support team. Please include them in your email to support@evernym.com:
    1. Name of you organization
    2. Verification Keys: List (1 or many) of your `Sponsor` VerKeys (verification key or public key) associated with the signing of the token. This is used to verify and authenticate a customer's (`Sponsee`) provision token during the provisioning on Evernym's Cloud Service.
       - The signing keys (including the `verkey` shared with Evernym's Cloud Service) can be generated using this simple tool: `https://github.com/sovrin-foundation/launch/raw/master/sovrin-keygen.zip`
       - The Private keys need to be stored in a safe place under your (`Sponsor's`) control. You should not send private key in email.
       - The public `verkey` should be shared with Evernym for signature validation.
    3. Endpoint: Your (`Sponsor's`) URL that Evernym Cloud Service should forward customer (`Sponsee`) messages to. This is how you can add push notifications to your mobile app. Evernym does not host a push notification service for the mobile SDK, you must create and manage your own. Evernym cloud agents will forward messages to this endpoint for you to push notify to your app.

    ![](/wiki-images/SponsorOnboarding.png)

## Mobile Application Provisioning Overview

1. Get Provision Token
    - You as the `Sponsor` will need to sign a provision token for your customer (`Sponsee`). Your app will have to communicate with you (`Sponsor`) to receive a `token`.
    - This `token` will contain a signature generated by you (`Sponsor`) to ensure the customer's app (`Sponsee`) has authorization to do so.
    - The `sig` field in Token Fields describes how to sign a token.
    - It also contains a timestamp. If the token isn’t delivered to Evernym's Cloud Service in a predefined time frame, the token will be invalid. Your customer's app (`Sponsee`) will need to request another `token` from you (`Sponsor`).
    - If for whatever reason provisioning fails, your customer's app (`Sponsee`) should request a new `token` from you (`Sponsor`) and attempt provisioning again.
2. Provisioning
    - Once your app has a provision token, you need to call SDK function with passing the received token to obtain its associated Cloud Agent.
    - This API expects two parameters of string type. These strings are JSON stringified objects which have following format

        ```json
        vcx_config: { - VCX library config 
            // Target Agency
            agency_endpoint: string, // url of agency to connect
            agency_did: string, // did of agency
            agency_verkey: string, // verkey of agency
            // Creating Wallet 
            wallet_name: string, // name of wallet
            wallet_key: string, // key to be used for wallet encryption
            // Pool Ledger
            path: string, // path to file containing pool genesis transactions
            // User Meta
            logo: string, // url leading to image
            name: string, // name to use
            // Communication Protocol
            protocol_type: '4.0', // aries communication protocol
            // it can be extended with other configuration options (see Configuration.md document)
            ...
        }
        token: { - Token received from Sponsor
           sponseeId:     String,
           sponsorId:     String,
           nonce:         String,
           timestamp:     String,
           sig:           String,
           sponsorVerKey: String,
        }
        ```
    
    - The value returned from this api (it can be ) will be the input for SDK initialization function.
    Note, that provisioning step need to be done only once by each application. On the following runs, the application should use configuration JSON received after provisioning and do library initialization directly.
    At this point, the app will be provisioned on Evernym's Cloud Service with a cloud agent and will have a local wallet initialized but NOT open. As the next step, you need to initialize VCX library with the received configuration JSON ( initialization will open the wallet and set settings).

    - As mentioned above, at this step the **[Mobile SDK Wallet](2.Storage.md#information-stored-by-mobile-sdk)** will be initialized. The only action required for the wallet initialization is providing a key that will initialize/encrypt/decrypt the wallet. `wallet_key` inside `vcx_config` in the above code sample is the key the client's app needs to provide.
    The generation of this key depends on the client's app. Here is an example implementation of the key generation [for Android](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/types/ProvisioningConfig.java#L120) and [iOS](/examples/ios/common/Config.m#L42).  

        **Note**, that the provisioning step needs to be done only on the first application run. On the following runs, the application should use configuration JSON received after provisioning and do library initialization directly.
   
       ![](/wiki-images/ApplicationProvisioning.png)

3. Receiving Your customer's Future Messages

   Cloud Agent is needed to receive messages from other parties.
   Once an application provisioned a Cloud Agent, there are two ways of message receiving from it:

    * Polling - Customer application once in a while calls Cloud Agent to get all received messages. 
        ![](/wiki-images/Polling.png)
        
        This strategy is used in the sample applications.

    * Push Notifications - Cloud Agent forwards messages to `Sponsor` which then notifies application. Go to the [document](PushNotifications.md) to get more information regarding setting push notifications.
        ![](/wiki-images/PushNotifications.png)

> NOTE: In the following tutorials we demonstrate the usage of protocol_type: '4.0'. You need to put it into provisioning config.

## Detailed about Application Provision and Initialization Steps

Overview:
1. Prepare Application [environment data](../environments):
    * Agency information is going to be used for Cloud Agent provisioning.
    * Pool Genesis transactions is going to be used for Pool Ledger Network connection.
    * Application meta information (`name`, `logo`).
    * Default protocol type is `3.0`, but we recommend to use `"protocol_type":"4.0"`.
1. On **first** application init:
    * Create a directory where wallet will be located.
    * Generate wallet key. This key will be used to derive a key used for the encryption of SDK data stored in the wallet.
    * (Optionally) Configure and init logger. 
    * Call Sponsor server backend API to get provision token.
    * Call VCX function to provision a Cloud Agent with received token.
        * iOS - `agentProvisionWithToken`
        * Android - `UtilsApi.vcxAgentProvisionWithToken`
    * Store received JSON config for the next usages.
    * Call VCX function to initialize library with JSON config.
        * iOS - `initWithConfig`
        * Android - `VcxApi.vcxInitWithConfig`
1. On **second and other** application runs:
    * Read provisioned JSON config received after **first** application init.
    * Call VCX function to initialize library with prepared JSON config.
        * iOS - `initWithConfig`
        * Android - `VcxApi.vcxInitWithConfig`

### Referenced implementation of Initialization steps in the sample applications

#### iOS

Refer to [AppDelegate.m](/examples/ios/MSDKSampleAppObjC/MSDKSampleAppObjC/AppDelegate.m).

#### Android

1. Pool genesis transaction using for Ledger connection can be found [here](/examples/android/MSDKSampleAppJava/app/src/main/res/raw/genesis.txt).
   <br>This configuration targets **Production** network.<br>
   In case your app works with another network, corresponding genesis transaction files for different environment could be found
   [here](https://github.com/sovrin-foundation/sovrin/tree/master/sovrin).
   Genesis transaction should be saved on a filesystem and be accessible to libVcx.
   For sample, [writeGenesisFile()](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/types/PoolConfig.java).

1. Selected Agency and other application configuration settings can be found [here](/examples/android/MSDKSampleAppJava/app/src/main/java/msdk/java/sample/Constants.java).

1. On first init (if you don't have populated JSON config) following steps should be performed:

    1. Configure application file system permissions. See [configureStoragePermissions](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/utils/StorageUtils.java) function.  
    
    1. Configure application logger. See[configureLogger](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/logger/Logger.java) function.

    2. Generate wallet key. See [createWalletKey()](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/utils/CommonUtils.java) function.

    3. Prepare configuration JSON (see [config sample](#sdk-provisioning-config-sample-single-pool-ledger)).

    4. Call Sponsor server backend API to get provision token. See [retrieveToken()](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/handlers/Initialization.java)

    5. Call `UtilsApi.vcxAgentProvisionWithTokenAsync` function with prepared config to provision a Cloud Agent.

    6. Resulting JSON must be stored for latter usage. This JSON will be used to initialize libVcx.
    
    7. Call `VcxApi.vcxInitWithConfig` function with JSON received after provisioning to initialize library. 

1. On second and other application initializations skip provisioning and do library initialization with previously stored config.
   1. Fetch config (generated on the step 3 during the first application launch) from the storage.

   2. Call `VcxApi.vcxInitWithConfig` function with JSON received after provisioning to initialize library.

> **NOTE:** If the initialization of the wallet does not work after you followed these steps, please contact Evernym. If you had to do extra steps to get it working, please also let us know what you had to do so that we can update this document.

### Errors you might see while calling provision functions

- **GNR-115**: This `statusCode` is returned when your `sponsor` details are not saved on agency which you are trying to use. To resolve this problem, send an email as described in section `Sponsor (i.e You) onboarding` above in this file. 
- **GNR-117**: This `statusCode` tells that the `provisioningToken` is already used. So, app should call your Sponsor token endpoint, and get a new provisioning token. Then call `agentProvisionToken` again with new token.
- 
    ```
    Provision Agent Error: Error Creating a wallet
    Caused by: Could not create wallet ...: "Error: IO error Caused by: Operation not permitted (os error 1)"
    ```
  The error relates to application permissions. MSDK tries to create `.indy_sdk` folder in android external storage but gets IO error.
  The issue should be solved by adding `Os.setenv("EXTERNAL_STORAGE", Utils.getRootDir(config.context), true);` into some place before provisioning step.
  
## Selecting the Ledger and Cloud Service

### Pool Ledger

The Indy-based Pool Ledgers Networks represent a publicly available distributed storages using for storing entities used for verifiable credential exchange. 

There are different Ledgers you may use (see `Pool Genesis Transactions` value):
- [**`demo`**](../environments/DemoEnvironment.md): for testing purposes during development and testing.
- [**`prod`**](../environments/ProductionEnvironment.md): production environment, for app releases in AppStores.

Use the `Pool Genesis Transactions` value in the particular environment to prepare a file with Pool Genesis Transactions.
The path to this file will be used as `genesis_path` parameter of SDK provisioning config.

You also can use different available Indy Pool Ledgers.
In the same way, you just need to store their Genesis Transactions into a file and use the path to the file in the library config.

### Evernym Cloud Service

As we already mentioned before Evernym Cloud Service is used for provisioning of Cloud Agents.

There are different Evernym Cloud Services you may use (see `Agency*` values):
- [**`demo`**](../environments/DemoEnvironment.md): for testing purposes during development and testing.
- [**`prod`**](../environments/ProductionEnvironment.md): production environment, for app releases in AppStores.

Use `Agency Url`, `Agency DID`, and `Agency Verification Key` values in the particular environment to prepare `agency_did`, `agency_endpoint`, and `agency_verkey` fields in the SDK initialization config.

#### SDK provisioning config sample (single Pool Ledger)

```json
{
  // These fields are used for agency configuration
  "agency_endpoint": "http://agency.pps.evernym.com", // URL of agency to use
  "agency_did": "3mbwr7i85JNSL3LoNQecaW", // DID of agency
  "agency_verkey": "2WXxo6y1FJvXWgZnoYUP5BJej2mceFrqBDNPE3p6HDPf", // Verification key of the agency

  //These fields are used for wallet configuration
  "wallet_name": "wallet-name-wwwww-wallet",  // Name of the wallet
  "wallet_key": "viM/BUU7I+Ypn+AdXAIQUAGX59pteVzau7Z7Jv3Ll6nzmYsSHrFqRdT71tjoMhTPRM2uSnqt8tDTSOLMP1KVf0fl1uP/dPsWu7cjucMsqfK8ohb92amhAWnNn+8s8UWC5owLN3EXZuilqYtjtRZtRUm/hhK5ycQ/OuxMgNPpfUQ=", // Key of the wallet

  // Communication Protocol
  "protocol_type": "4.0", // Type of the protocol

  // Pool Ledger
  "genesis_path": "/data/user/0/me.connect.sdk.java.sample/files/connectMeVcx/pool_transactions_genesis", // path to file containing pool genesis transactions

  // User Meta
  "logo": "https://robothash.com/logo.png", // url leading to image
  "name": "real institution name" // name to use
}
```

### Multi Pool Ledger Connection 

In most cases it is enough to have a connection only to one specific Pool Ledger Network.
But in some cases it can be useful to work with multiple Pool Ledger Netoworks at the same time.
For example, there is several organisations running their own Indy Pool Ledger Networks, and you want to make your application able to work with each of them at the same time.

In order to achieve this goal you need to specify multiple Pool Ledgers (using `pool_networks` field) in the library configuration JSON.
When the library is need to get some public information from the ledger (like schema or credential definition) it will query all connection ledger for this data.

#### SDK provisioning config sample (multiple Pool Ledgers)

```json
{
  // These fields are used for agency configuration
  "agency_endpoint": "http://agency.pps.evernym.com", // URL of agency to use
  "agency_did": "3mbwr7i85JNSL3LoNQecaW", // DID of agency
  "agency_verkey": "2WXxo6y1FJvXWgZnoYUP5BJej2mceFrqBDNPE3p6HDPf", // Verification key of the agency

  //These fields are used for wallet configuration
  "wallet_name": "wallet-name-wwwww-wallet",  // Name of the wallet
  "wallet_key": "viM/BUU7I+Ypn+AdXAIQUAGX59pteVzau7Z7Jv3Ll6nzmYsSHrFqRdT71tjoMhTPRM2uSnqt8tDTSOLMP1KVf0fl1uP/dPsWu7cjucMsqfK8ohb92amhAWnNn+8s8UWC5owLN3EXZuilqYtjtRZtRUm/hhK5ycQ/OuxMgNPpfUQ=", // Key of the wallet

  // Communication Protocol
  "protocol_type": "4.0", // Type of the protocol

  // Pool Ledger
  "indy_pool_networks": [
    {
      'genesis_path': '/data/user/0/me.connect.sdk.java.sample/files/connectMeVcx/pool_transactions_genesis',
      'namespace_list': ['demo']
    },
    {
      'genesis_path': '/data/user/0/me.connect.sdk.java.sample/files/connectMeVcx/pool_transactions_genesis_dev',
      'namespace_list': ['dev']
    },
    {
      'genesis_path': '/data/user/0/me.connect.sdk.java.sample/files/connectMeVcx/pool_transactions_genesis_live',
      'namespace_list': ['live']
    }
  ],
  
  // User Meta
  "logo": "https://robothash.com/logo.png", // url leading to image
  "name": "real institution name" // name to use
}
```

## Logging

### Android

Android SDK uses `slf4j` logging library. \
Sample of configuration to store SDK logs in specified file could be found [here](/examples/android/MSDKSampleAppJava/lib/src/main/java/msdk/java/logger/Logger.java).\
For additional information about logging configuration see [slf4j documentation](http://www.slf4j.org/docs.html).

### iOS

iOS sdk provides `VcxLogger setLogger` function accepting a callback which will be called to log records inside SDK.

```
[VcxLogger setLogger: ^(NSObject *context, NSNumber *level, NSString *target, NSString *message, NSString *modulePath, NSString *file, NSNumber *line) {
    NSLog(@"[Inside VcxLogger.setLogger callback] %@    %@:%@ | %@", [levelMappings valueForKey: [NSString stringWithFormat: @"%@", level]], file, line, message);
}];
```

## Next Step

Congratulations! Now your application initialized and obtained their Cloud Agent. 
You are ready to read how to [receive message](4.MessagesFlow.md) from the Cloud Agent.
