# 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,
           }
         });
       })
   ```
