# In-wallet applications

The following section serves to guide developers on how to enable wallets to support Ontology's `dAPI`, along with `Provider SDK` integration into mobile wallet apps. It may be worth referring to the respective open source Android and iOS wallet [source code](https://github.com/ontio-cyano).

The two parties involved in the integration process are:

* The `dApp` :  Blanket term that represents`dApps` developed for the users of Ontology ecosystem.
* The `Provider`: Wallets that support `dAPI` , and adhere to it's specifications.

{% hint style="info" %}
Wallets that currently support the `dAPI` protocol:

* [**ONTO**](https://onto.app/)
* [**Cyano Wallet**](http://101.132.193.149/files/app-debug.apk)
* [**O-Wallet**](https://github.com/ontio/OWallet/releases)
* [**Math Wallet**](http://www.mathwallet.org/en/)
* [**Banko**](http://bankowallet.com/pc.html)
* [**Huobi Wallet**](https://www.huobiwallet.com/)
  {% endhint %}

## Interaction process

The URI scheme that the `dApp` uses when sending requests:

```
ontprovider://ont.io?param=Base64.encode(Uri.encode({the json data}.toString()))
```

The process can be broadly divided in the following manner:

![](https://1077617372-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LvPXC4l2V4Z8gRDNIoZ%2F-LwHGzRX_2DAzQBtscV6%2F-LwHH1PTXL7zEXqwsaKD%2Fdapp-wallet-interaction-flow-2-1%20\(1\).svg?generation=1576559723243833\&alt=media)

#### Step 1：Wallet uses Webview to open dApps (H5 design)

Wallet uses `Webview` to open `H5 dApps` in the `dApp` store page layout

#### Step 2：dApp sends a request to fetch wallet's address

There are two ways to retrieve account information-

* Using the `getAccount` method
* Using the `login` method

#### Step 3：dApp sends a contract invocation request

The steps involved-

1. `dApp` sends **invocation request**
2. The wallet initiates transaction, carries out user **authentication** and **signature**
3. Wallet **pre-executes** the transaction
4. Transaction is transmitted to the **blockchain**
5. Wallet returns **transaction `hash`** to the `dApp`

## dAPI protocol usage

The dAPI protocol is extensible in nature. It's core features can be laid out in terms of the following functions.

* Querying `Provider` information
* Querying **wallet** or **account/identity** related information
* **Authentication** and login
* Message **signature**
* Smart contract **invocation**

### Querying provider information

The query request that the `dApp` sends to the wallet to fetch the `provider` information is first encoded in `URI` and `Base64`, and then sent. The data is structured in the following manner:

```yaml
{
    "action": "getProvider",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "version": "v1.0.0",
    "params": {
    }
}
```

Data specification for the fields mentioned above-

|  Field | Data type |   Description  |
| :----: | :-------: | :------------: |
| action |   string  | Operation type |
|   id   |   string  |  Serial number |

The data set of provider information that the wallet returns, after `URI` and `Base64` decoding, is structured in the following manner:

```yaml
{
    "action": "getProvider",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "error": 0,
    "desc": "SUCCESS",
    "result": {
        "provider": "cyano walllet",
        "version": "1.0.0"
    }
}
```

### Querying the wallet account or identity information

The query request that the `dApp` sends to the wallet to fetch the account or identity information is first encoded in `URI` and `Base64`, and then sent. The data is structured in the following manner:

```yaml
{
    "action": "getAccount", // or getIdentity
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "dappName": "dapp Name",
        "dappIcon": "dapp Icon"
    }
}
```

Data specification for the fields mentioned above-

|   Field  | Data type |       Description       |
| :------: | :-------: | :---------------------: |
|  action  |   string  |      Operation type     |
| dappName |   string  |        dApp name        |
| dappIcon |   string  | dApp icon resource link |

The data set that the wallet returns, after `URI` and `Base64` decoding, has the following structure:

```yaml
{
    "action": "getAccount", // or getIdentity
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "error": 0,
    "desc": "SUCCESS",
    "result": "AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ"  // or  "did:ont:AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ"
}
```

### Login

The login request that the `dApp` sends to the wallet is first encoded in `URI` and `Base64`, and then sent. The data is structured in the following manner:

```yaml
{
    "action": "login",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "dappName": "dapp Name",
        "dappIcon": "dapp Icon",
        "message": "helloworld"
    }
}
```

Data specification for the fields mentioned above-

| Fields   | Data type | Description                                                                                                              |
| -------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| action   | string    | Operation type                                                                                                           |
| type     | string    | Specifying the login method. ONT ID login is specified using "ontid", and wallet address login is specified as "address" |
| dappName | string    | dApp name                                                                                                                |
| dappIcon | string    | dApp icon resource link                                                                                                  |
| message  | string    | Randomly generated, used for identity verification                                                                       |

The wallet's response to the login request is of the following format after decoding:

***Success response***

```yaml
{
    "action": "login",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "error": 0,
    "desc": "SUCCESS",
    "result": {
        "type": "ontid or account",
        "user": "did:ont:AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz or AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz",
        "message": "helloworld",
        "publickey": "0205c8fff4b1d21f4b2ec3b48cf88004e38402933d7e914b2a0eda0de15e73ba61",
        "signature": "01abd7ea9d79c857cd838cabbbaad3efb44a6fc4f5a5ef52ea8461d6c055b8a7cf324d1a58962988709705cefe40df5b26e88af3ca387ec5036ec7f5e6640a1754"
    }
}
```

***Failure response***

```yaml
{
  "action": "login",
  "version": "v1.0.0",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 80001,
  "desc": "PARAMS ERROR",
  "result": 1
}
```

Data specification for the fields mentioned above-

| Field     | Data type | Description                                                                                                              |
| --------- | --------- | ------------------------------------------------------------------------------------------------------------------------ |
| action    | string    | Operation type                                                                                                           |
| result    | string    | The result to be returned                                                                                                |
| type      | string    | Specifying the login method. ONT ID login is specified using "ontid", and wallet address login is specified as "address" |
| user      | string    | The account used for signature, ONT ID or wallet address                                                                 |
| message   | string    | Randomly generated, used for identity verification                                                                       |
| publickey | string    | Account's public key                                                                                                     |
| signature | string    | User's signature                                                                                                         |

### Message signature

The structure remains the same as the login request, with the difference being that `dApp` name and icon are not needed. The request is encoded in `URI` and `Base64`, and then sent to the wallet.

```yaml
{
    "action": "signMessage",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "type": "ontid or address",
        "message": "helloworld"
    }
}
```

Data specification for the fields mentioned above-

| Field   | Data type | Description                                                                                                   |
| ------- | --------- | ------------------------------------------------------------------------------------------------------------- |
| action  | string    | Operation type                                                                                                |
| type    | string    | Specifying the access method. ONT ID is specified using "ontid", and wallet address is specified as "address" |
| message | string    | Randomly generated, used for identity verification                                                            |

The wallet's success response to the request is of the following format after decoding:

```yaml
{
    "action": "signMessage",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "error": 0,
    "desc": "SUCCESS",
    "result": {
        "type": "ontid or address",
        "user": "did:ont:AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz or AUEKhXNsoAT27HJwwqFGbpRy8QLHUMBMPz",
        "message": "helloworld",
        "publickey": "0205c8fff4b1d21f4b2ec3b48cf88004e38402933d7e914b2a0eda0de15e73ba61",
        "signature": "01abd7ea9d79c857cd838cabbbaad3efb44a6fc4f5a5ef52ea8461d6c055b8a7cf324d1a58962988709705cefe40df5b26e88af3ca387ec5036ec7f5e6640a1754"
    }
}
```

### Contract invocation

Different invocation methods can be chosen using the `action` parameter. The available options are:

| Parameter value    | Function                                                                                       |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| invoke             | Normal process                                                                                 |
| invokeRead         | Pre-execute the contract, the user does not need to sign, the result is returned to the `dApp` |
| invokePasswordFree | Invoke without the need of authentication, user does not need to enter password                |

{% hint style="info" %}
The `invokePasswordFree` function can be used for scenarios a contract needs to be invoked without prompting the user to enter their password. For example, games that stake money at regular intervals. Though, the use still needs to enter password once.
{% endhint %}

The platform only trusts fixed methods and parameters, and not all the methods that are part of the contract. After authentication, the transaction parameters are saved as `((InvokeCode)txs[0]).code`

{% hint style="success" %}
If another request that requires the same data is submitted, the user does not need to enter the password again, and the smart contract does not need to be pre-executed on more time.
{% endhint %}

{% hint style="danger" %}
When the user exits the `dApp`, please ensure that the parameters and the private key data are cleared from the memory.
{% endhint %}

#### dApp sends an invocation request

The data set of the request is encoded in `URI` and `Base64` and sent out. The structure is:

```yaml
{
    "action": "invoke",
    "version": "v1.0.0",
    "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
    "params": {
        "invokeConfig": {
            "contractHash": "16edbe366d1337eb510c2ff61099424c94aeef02",
            "functions": [{
                "operation": "method name",
                "args": [{
                    "name": "arg0-list",
                    "value": [true, 100, "Long:100000000000", "Address:AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ", "ByteArray:aabb", "String:hello", [true, 100], {
                        "key": 6
                    }]
                }, {
                    "name": "arg1-map",
                    "value": {
                        "key": "String:hello",
                        "key1": "ByteArray:aabb",
                        "key2": "Long:100000000000",
                        "key3": true,
                        "key4": 100,
                        "key5": [100],
                        "key6": {
                            "key": 6
                        }
                    }
                }, {
                    "name": "arg2-str",
                    "value": "String:test"
                }]
            }],
            "payer": "AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ",
            "gasLimit": 20000,
            "gasPrice": 500
        }
    }
}
```

{% hint style="info" %}
Base58 addresses such as `AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ` can be assigned to the `%address` parameter, and the wallet will automatically assign it as the wallet's asset address. If the parameters contain an `%ontid`, the wallet will also automatically assign it to the wallet's `ONT ID` address.
{% endhint %}

#### Wallet responds to the invocation request

First the wallet carries out URI and Base64 decoding. And then,

1. Wallet **initiates** a transaction
2. Wallet carries out user **authentication** and **signature**
3. The transaction is **pre-executed**
4. Wallet receives **user confirmation**
5. The transaction is **transmitted** onto the chain
6. Transaction **hash** is returned to the `dApp`

The success response sent to the `dApp` is:

```yaml
{
  "action": "invoke",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 0,
  "desc": "SUCCESS",
  "result": "tx hash"
}
```

The failure response sent to the `dApp` is:

```yaml
{
  "action": "invoke",
  "id": "10ba038e-48da-487b-96e8-8d3b99b6d18a",
  "error": 80001,
  "desc": "SEND TX ERROR",
  "result": ""
}
```

#### Pre-executing transactions

The amount of `ONT` and `ONG` that the user is going to expend in the transaction can be determined from the `notify` response, which is a result of the pre-execution.

A connection must be established with the following nodes:

* **MainNet** - <http://dappnode3.ont.io/>
* **TestNet** - <http://polaris5.ont.io/>

{% hint style="info" %}
It is advised to first completely analyze the `notify` response before making a judgement pertaining to a transaction, as there may be multiple transfers or events taking place. The nature of the token (`ONT` or `ONG`) can be determined from the contract address, while the `transfer` method and recipient can be determined later.
{% endhint %}

```yaml
{
    "Notify": [{
        "States": ["transfer", "AUr5QUfeBADq6BMY6Tp5yuMsUNGpsD7nLZ", "AecaeSEBkt5GcBCxwz1F41TvdjX3dnKBkJ", 1],
        "ContractAddress": "0100000000000000000000000000000000000000"
    }],
    "State": 1,
    "Gas": 20000,
    "Result": "01"
}
```

## dAPI provider SDK integration

`dAPI provider SDK` aids communication between `Android webview` and a web based `dApp`. It encapsulates a few methods for `webview`. Separate details with respect to [Android](https://github.com/ontio-cyano/cyano-android-sdk) and [iOS](https://github.com/ontio-cyano/cyano-ios-sdk) platforms are available for reference.

#### Android SDK sample code

```java
//init
CyanoWebView cyanoWebView=new CyanoWebView(context);
cyanoWebView.loadUrl(url);

//Action handle
cyanoWebView.getNativeJsBridge().setHandleGetAccount(new NativeJsBridge.HandleGetAccount() {
            @Override
            public void handleAction(String data) {
              /* TODO
               * 1.Send wallet address to webView
               * com.alibaba.fastjson.JSONObject reqJson = JSON.parseObject(data);
               * String action=reqJson.getString("action");
               * String version=reqJson.getString("version");
               * String id=reqJson.getString("id");
               * cyanoWebView.sendSuccessToWeb(action,version, id, *wallet address*);
               */
            }
    });

cyanoWebView.getNativeJsBridge().setHandleInvoke(new NativeJsBridge.HandleInvoke() {
            @Override
            public void handleAction(String data) {
              /* TODO
               * 1. Password input prompt, resolve wallet account, build transaction using the data, carry out signature, pre-execute, note the processing time
               * 
               * 2. Analyze the pre-execution notify reseponse, display transaction fees, if the result contains the contract address determine ONT/ONT, display recipient address and transfer amount
               * 
               * 3. Transmit the transaction onto the chain after user confirmation
               * 
               * 4. Send the transaction hash to webview
               *
               * com.alibaba.fastjson.JSONObject reqJson = JSON.parseObject(data);
               * String action=reqJson.getString("action");
               * String version=reqJson.getString("version");
               * String id=reqJson.getString("id");
               * cyanoWebView.sendSuccessToWeb(action,version, id, 交易 hash);
               */
            }
    });

cyanoWebView.getNativeJsBridge().setHandleInvokeRead(new NativeJsBridge.HandleInvokeRead() {
        @Override
        public void handleAction(String data) {
               /* TODO
                * 1. Build transaction using the data, note the processing time
                * 
                * 2 Send the pre-execution results to webview
                * com.alibaba.fastjson.JSONObject reqJson = JSON.parseObject(data);
                * String action=reqJson.getString("action");
                * String version=reqJson.getString("version");
                * String id=reqJson.getString("id");
                * cyanoWebView.sendSuccessToWeb(action,version, id, 预知行结果);
                */
        }
});


cyanoWebView.getNativeJsBridge().setHandleInvokePasswordFree(new NativeJsBridge.HandleInvokePasswordFree() {
        @Override
        public void handleAction(String data, String message) {
          /* TODO
           * 1. Executing for the first time is the same as action : invoke, both the password and the message are saved
           * 
           * 2. When the same request arrives for the second time, use the saved password for signature and fetch pre-execution result
           * 
           * 3. The pre-execution results need not display for the user to confirmation
           * 
           * 4. Send the transaction hash to the webview
           * com.alibaba.fastjson.JSONObject reqJson = JSON.parseObject(data);
           * String action=reqJson.getString("action");
           * String version=reqJson.getString("version");
           * String id=reqJson.getString("id");
           * cyanoWebView.sendSuccessToWeb(action,version, id, 交易hash);
           */
        }
});

//response
Map map = new HashMap<>();
map.put("action", "");
map.put("error", 0);
map.put("desc", "SUCCESS");
map.put("result", message);
cyanoWebView.sendBack(Base64.encodeToString(Uri.encode(JSON.toJSONString(map)).getBytes(), Base64.NO_WRAP));
```

#### iOS SDK sample code

```objectivec
RNJsWebView * webView = [[RNJsWebView alloc]initWithFrame:CGRectZero];
[webView setURL:@""];

[webView setGetAccountCallback:^(NSDictionary *callbackDic) {

}];


[webView setInvokeTransactionCallback:^(NSDictionary *callbackDic) {

}];

[webView setInvokeReadCallback:^(NSDictionary *callbackDic) {

}];


NSDictionary *params = @{
                         @"action":@"",
                         @"version":@"v1.0.0",
                         @"error":@0,
                         @"desc":@"SUCCESS",
                         @"result":@""
                         };
[webView sendMessageToWeb:params];
```

## Code base for reference

|                                              **Signature verification methods**                                              |                                                     **Transaction event query methods**                                                    |                         **Cyano Wallet**                        |                      **dAPI - Mobile provider SDK**                     | **dAPI - Mobile client SDK**                                |
| :--------------------------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------------------------------------------------: | :-------------------------------------------------------------: | :---------------------------------------------------------------------: | ----------------------------------------------------------- |
| [Java SDK](https://github.com/ontio/ontology-java-sdk/blob/master/docs/cn/interface.md#%E7%AD%BE%E5%90%8D%E9%AA%8C%E7%AD%BE) | [Java SDK](https://github.com/ontio/ontology-java-sdk/blob/master/docs/cn/basic.md#%E4%B8%8E%E9%93%BE%E4%BA%A4%E4%BA%92%E6%8E%A5%E5%8F%A3) | [Cyano - Android](https://github.com/ontio-cyano/cyano-android) | [Cyano - Android SDK](https://github.com/ontio-cyano/cyano-android-sdk) | [Cyano Bridge](https://github.com/ontio-cyano/cyano-bridge) |
|               [TypeScript SDK](https://github.com/ontio/ontology-ts-sdk/blob/master/test/ecdsa.crypto.test.ts)               |                        [TypeScript SDK](https://github.com/ontio/ontology-ts-sdk/blob/master/test/websocket.test.ts)                       |     [Cyano - iOS](https://github.com/ontio-cyano/cyano-ios)     |     [Cyano - iOS SDK](https://github.com/ontio-cyano/cyano-ios-sdk)     |                                                             |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ont.io/guides-and-tutorials/integration-guides/mobile-wallet-integration/dapi-integration/in-wallet-applications.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
