DQtech Column | Learn from DEX about PlatON Application Development – Javascript (X)

In this chapter, we will implement the function of exporting Digging interface, so that web pages can call it. At the same time, this chapter is also the final chapter of JavaScript.

Write Import Interface

In the previous chapter, we added the following code to the manifest.json, so that the multi networks we added can send requests normally.

"content_scripts": [
    {
      "matches": [
        "file://*/*",
        "http://*/*",
        "https://*/*"
      ],
      "js": [
        "js/contentscript.js"
      ],
      "run_at": "document_start",
      "all_frames": true
    }
  ],

content_ scripts is a js script running in the context of a web page. It can read the dom of a web page or modify it and can be used as a bridge between web pages and plug-ins, but cannot access the functions and variables defined in the web page js. The purpose of matches is to ensure that content script can work on those websites. By default, it works on all websites. js represents the js file to load, and run_ at is used to execute commands after the default web page is loaded.
The code of public/js/contentscript.js is as follows:

// 向页面注入JS
function injectCustomJs(jsPath) {
    // 因为content_script是不能直接访问网页的中的变量的
    // 因此需要给网页注入要一个js文件让其可以访问,
    jsPath = jsPath || 'js/inject.js';
    let scriptDom = document.createElement('script');
    scriptDom.setAttribute('type', 'text/javascript');
    scriptDom.src = chrome.extension.getURL(jsPath);
    let origin = ""
    // inject.js文件加载完成后,执行如下代码
    scriptDom.onload = () => {
        /**
         * 将消息发送给background.js
         */
        function sendMsgToBackground(data) {
            return new Promise((resolve, reject) => {
                chrome.runtime.sendMessage(data, (response) => {
                    resolve(response);
                });
            });
        }
        /**
         * background.js回复消息给inject.js
         * @param {}} id 
         * @param {*} data 
         */
        function sendMsgBackToInject(id, data) {
            window.postMessage({
                to: "diggingInject",
                type: "ack",
                id,
                data
            }, origin);
        }
        /**
         * 监听来自inject的消息
         */
        window.addEventListener("message", async function (e) {
            let data = e.data;
            if (data.to !== 'diggingConent') {
                return;
            }
            origin = data.origin;
            /**
             * 发型消息给后台
             */
            if (data.type === "send") {
                let res = await sendMsgToBackground(data);
                sendMsgBackToInject(data.id, res);
            } 
        }, false);
        /**
         * 接受来自后台的消息
         */
        chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
            return true;
        });
    }
    
    document.body.appendChild(scriptDom);
}
// 网页加载后执行代码
document.addEventListener("DOMContentLoaded", () => {
    injectCustomJs();
});

Since the web page cannot directly access the content script interface, you need to add the web_accessible_resources field in the manifest.json to indicate the js file that can access the web page. The above content script code is used to add the file specified by web_accessible_resources to the web page.

  "web_accessible_resources": [
    "js/inject.js"
  ],

在public/js目录下添加inject.js文件, 代码如下:

class Digging {
    /**
     * 回调函数的map
     */
    static callbackMap = {};
    /**
     * 给每一个请求分配一个唯一的id
     */
    static msgId = 1;

    /**
     * 获取指定钱包的地址
     * @param {} walletAddress
     * @returns
     */
    static async GetBalanceof(walletAddress) {
        /**
         * 这里把参数都打包成一个obj
         */
        return Digging.SendMsg("GetBalanceof", {
            walletAddress
        });
    }

    /**
     * 发送LAT到指定钱包
     * @param {} toAddress
     * @param {*} lat
     * @returns
     */
    static async SendLat(toAddress, lat) {
        /**
         * 这里把参数都打包成一个obj
         */
        return Digging.SendMsg("SendLat", {
            toAddress,
            lat
        });
    }

    /**
     * 发型消息给content script
     * @param {} msgType
     * @param {*} data
     * @returns
     */
    static SendMsg(msgType, data) {
        return new Promise(resolve => {
            let id = ++Digging.msgId;
            Digging.callbackMap[id] = resolve;
           // 发送给contentscript
            window.postMessage(
                {
                    to: "diggingConent",
                    type: "send",
                    id,
                    msgType,
                    origin: '*',
                    data
                },
              '*'
            );
        });
    }
}
// 把接口导出到window
window.Digging = Digging;
/**
 * 监听content script返回来的消息
 */
window.addEventListener(
    "message",
    function(e) {
        let data = e.data;
        if (data.to !== "diggingInject") {
            return;
        }

        if (data.type === "ack") {
            let resolve = Digging.callbackMap[data.id];
            if (!resolve) {
                return;
            }
            delete Digging.callbackMap[data.id];
            resolve(data.data);
            return;
        }
    },
    false
);

This chapter only demonstrates how to obtain the address balance and send lat. Readers can export more interfaces according to their own needs.

Add follow code in the end of background.js:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    // 判断为获取余额的,直接调用 TransactionManager.GetBalanceOf
    if (request.msgType === "GetBalanceOf") {
        TransactionManager.GetBalanceOf(request.data).then(lat => {
            sendResponse({
                errCode: SUCCESS,
                data: lat
            });
        });
    } else if (request.msgType === "SendLat") {
        TransactionManager.SendLATTO(
            request.data.lat,
            request.data.account,
            request.data.toAddress
        ).then(res => {
            sendResponse(res);
        });
    }
    // 这里一定要返回true
    return true;
});

So far, we have completed the function of exporting the interface

Write the code to call the web page

Create demo.html in the current project directory
Code as follows:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div>
      获取指定钱包地址余额: <input id="balanceAddress" />
      <span id="balance">0 LAT</span> <button id="balanceBtn">获取</button>
    </div>

    <div style="margin-top:30px;">
      发送LAT:
      <div>lat数量: <input id="sendLatNum" /></div>
      <div>账号: <input id="account" /></div>
      <div>接收地址: <input id="toAddress" /></div>
      <div>
        <button id="sendBtn">发送</button>
      </div>
    </div>

    <script>
      window.onload = () => {
        let balanceAddressDom = document.getElementById("balanceAddress");
        let balanceDom = document.getElementById("balance");

        let balanceBtnDom = document.getElementById("balanceBtn");

        // 获取指定地址的lat数量
        balanceBtnDom.onclick = async () => {
          let res = await Digging.GetBalanceOf(balanceAddressDom.value);

          balanceDom.innerHTML = res.data + " LAT";
        };

        let sendLatNumDom = document.getElementById("sendLatNum");
        let accountDom = document.getElementById("account");
        let toAddressDom = document.getElementById("toAddress");

        let sendBtnDom = document.getElementById("sendBtn");

        sendBtnDom.onclick = async () => {
          let res = await Digging.SendLat(
            sendLatNumDom.value,
            accountDom.value,
            toAddressDom.value
          );
        };
      };
    </script>
  </body>
</html>

The interface shown as follow:

1640179371(1)

Get the balance of your account:
As this:

1640179371(1)

Then we send lat, as shown in the following picture:

1640179454(1)

On the digging page, we can see the following:

image


The balance changes from 158 to 148, and the sent transaction records can be seen in the transaction list.

Well, that’s the end of the JavaScript serious.

Conclusion:
In this article, we have improved all the core functions of the wallet, but there are many optimizations that readers need to implement themselves. For example, when transferring funds, you need to judge whether the balance is sufficient, add the display function of pop, and so on. If you are interested in these functions, you can add them by yourself. Based on the current foundation, DQT team will continue to complete the browser version of digging until it becomes a user-friendly and fully functional product. After completion, we will open source it. Please pay attention.
Well, we’ll start teaching Android next week. You need to master the development knowledge of Java, kotlin and Android in advance.

Thank you for your support and attention.

The URL of github : https://github.com/DQTechnology/Platon_DevGuideProject

Publisher:PlatONWorld-M6,Please indicate the source for forwarding:https://platonworld.org/?p=6294

(0)
PlatONWorld-M6的头像PlatONWorld-M6Official
上一篇 6 2 月, 2022 22:02
下一篇 13 2 月, 2022 13:19

相关推荐

发表回复

登录后才能评论