# Extensible Message Interface

Sending.Network provides an extension plug-in platform, enabling developers to enrich the messaging features by interacting with third-party dapps or smart contracts.

Currently, Sending.Network has 3 built-in plugin projects: _message-type-plugin_, _did-method-plugin_ and _social-graph-plugin_, and developers are free to develop other plugin projects. Plugin projects are lightweight, pluggable, and easy to deploy. The following sections introduce how to compile and deploy _message-type-plugin_ plugin projects in environments like Web, IOS, and Android.

## 1. JavaScript

### 1.1 Compile and install

{% hint style="info" %}
Please contact developer@sending.network for the wasm files.
{% endhint %}

At the root directory of message-type-plugin

```bash
// generate the wasm package of the plugin project
cd message-type-plugin
./build-wasm.sh
```

A package called `message-type-plugin.wasm` will be found in the directory `web/`.

At the root directory of the Radix main project

```bash
// generate the wasm package of the Radix main project
cd radix
./build-wasm.sh

// generate service worker sw.js
cd web/
yarn install
yarn build
```

A package called _server.wasm_ will be found in the directory `web/`. _sw.js_ will be generated in the `web/dist/`.

### 1.2 Deploy and Register

#### **1.2.1 Deploy**

Replace the _sw.js_ and two wasm packages with the newly built ones, clear the web page cache data and refresh it.

#### **1.2.2 Register the Plugin**&#x20;

By launching the `message-type-plugin.wasm`, the plugin will be automatically registered into Radix main Process. However, you can also register/unregister the plugin by executing console scripts. In the console of your Chrome browser, run the following scripts to register/unregister trading Dapp plugins like Lucky Box and Peer Swap.

```javascript
//Register LuckyBox
fetch('http://pluginoperate/register_plugin', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'type': 'MessageType',
            'name': 'LuckyBox',
            'http_base_url': 'http://messagetypeplugin'
        })
    })
        .then(response => response.json())
        .then(response => console.log(JSON.stringify(response)));
        
//Unregister LuckyBox
fetch('http://pluginoperate/unregister_plugin', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'type': 'MessageType',
            'name': 'LuckyBox'
        })
    })
        .then(response => response.json())
        .then(response => console.log(JSON.stringify(response)));
        
//Register PeerSwap
fetch('http://pluginoperate/register_plugin', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'type': 'MessageType',
            'name': 'PeerSwap',
            'http_base_url': 'http://messagetypeplugin'
        })
    })
        .then(response => response.json())
        .then(response => console.log(JSON.stringify(response)));
        
//Unregister PeerSwap
fetch('http://pluginoperate/unregister_plugin', {
        method: 'POST',
        headers: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            'type': 'MessageType',
            'name': 'PeerSwap'
        })
    })
        .then(response => response.json())
        .then(response => console.log(JSON.stringify(response)));
```

### 1.3. Use the Plugin

Plugin features can be used by calling the interfaces from the frontend.

For instance, `http://localhost/_api/media/v3/query_message_type` this interface can return all of the supported trading Dapp message types.

The frontend can fetch all of the registered plugins by calling this API.

## 2. iOS & Android

### 2.1 Compile the Plugin Project

At the root directory of _message-type-plugin:_

```bash
// iOS
cd message-type-plugin
bash build/gobind-plugin/build.sh -i

//Android
cd message-type-plugin
bash build/gobind-plugin/build.sh -a
```

Then integrate the generated packages into your iOS or Android SDK.

## 3. Dapp Callback

In Web3 trading Dapps, there are always some scenes that you need to call a JS API to query data like a user profile. In Sending.Network, trading Dapps like LuckyBox and PeerSwap will fetch user profiles and interact with the P2P nodes. The following section provides a generic guide on how to call a JS API from third-party Dapps.

### 3.1 Preparation

1. Install `postmate`

```bash
yarn add postmate
```

### 3.2 API Provider (Web applications that provide APIs to Dapps)

1.  Provide an _iframe_ container to load Dapps:

    <pre class="language-html"><code class="lang-html"><strong>&#x3C;div className="iframeContainer" ref={frameContainerRef}>&#x3C;/div>
    </strong></code></pre>
2.  Create an _iframe_ and load Dapp:

    ```javascript
    const postmateRef = new Postmate({
          url,
          container: frameContainerRef.current,
          classListArray: ["iframe"],
        });
    ```
3.  Define an API for Dapps:

    ```javascript
      const actionMethods = (payload) => {
        if (payload.action === "api名称") {
          //  fetch data
          let data = fetch('**')
          //  callback and return the data to DApps
          payload.callback({
            id: payload.id,
            data,
          });
        }
      }  

    const bindPostmate = () => {
        postmateRef.then((child) => {
          child.on("message.sending.me", ({ payload }) => {
            if (payload?.id) {
              payload.callback = (data) => {
                child.call("message.sending.me", data);
              };
            }
            actionMethods(payload);
          });
        });
      };
    ```

### 3.3 Call an API

1.  Define a JS class to perform callback:

    ```typescript
    class SdmCallback {
        static callbacks: any = {}

        static addCallback(id:any, cb:any) {
          console.log(`add callback: \nid: ${id}\ncb:${cb}\n`);
          this.callbacks[id] = cb
        };
        static executeCallback(id: any, error: any, value: any) {
            console.log(`executing callback: \nid: ${id}\nvalue: ${value}\nerror: ${error}\n`)

            let callback = this.callbacks[id]

            if (error) {
                console.log(`executing error callback: \nid: ${id}\nvalue: ${value}\nerror: ${error}\n`)
                callback(error)
            } else {
                console.log(`executing success callback: \nid: ${id}\nvalue: ${value}\nerror: ${error}\n`)
                callback(value)
            }

            delete this.callbacks[id]
        };
    }
    ```
2.  Expose your model to the Parent. Property values may be functions, promises, or regular values.

    ```javascript
        const postmate = new Postmate.Model({
          "message.sending.me": ({id, error, data}: any )=>{
            SdmCallback.executeCallback(id, error, data)
          }
        });
    ```
3.  Call the Parent's API

    ```javascript
        postmate.then((parent)=>{
          const { id = Math.floor((Math.random() * 200000) + 1) } = {}
          SdmCallback.addCallback(id, callback)
          parent.emit('message.sending.me', {
            payload: {
              action: 'getMyProfile',
              id,
            }
          });
        })
    ```
