DQtech Column | Learn from DEX about PlatON Application Development – Android (VIII)

Author Dex_DQT

In this chapter, we will learn how to build the function of redemption entrustment and receiving entrustment reward, as well as how to analyze the return results of smart contracts.

Create a delegate details page

Check out the layout code in the res/layout/activity_delegate_detail.xml file. The page will look like this:

DQtech Column | Learn from DEX about PlatON Application Development – Android (VIII)

Then create the corresponding Delegate Detail Activity in the activity package

This page needs to get information about all the delegate nodes of the wallet. In chapter 9 of the javascript chapter, this information can be obtained directly at the blockchain node, but in this chapter we obtain the list of delegate nodes through the API provided by ATON. The interface address is: /app/v0760/node/delegateDetails. (The implementation of this interface can be found in the Get Delegate Detail List method of the AtonApi class)
And the interface returns the following information:

class DelegateNodeDetail {
    /**
     * 可委托LAT
     */
    var availableDelegationBalance: String? = null

    /**
     * 总委托LAT数量
     */
    var delegated: String? = null

    /**
     * 委托的节点列表
     */
    @JSONField(name = "item")
    var item: List<DelegateItemInfo>? = null
}

class DelegateItemInfo {
    /**
     * 投票节点Id(节点地址 )
     */
     var nodeId: String? = null

    /**
     * 节点名称
     */
    var nodeName: String? = null

    /**
     * 机构官网(链接)
     */
    var website: String? = null

    /**
     * 节点头像
     */
    var url: String? = null

    /**
     * 竞选状态:
     * Active —— 活跃中
     * Candidate —— 候选中
     * Exiting —— 退出中
     * Exited —— 已退出
     * Locked —— 锁定中
     */
    var nodeStatus: String? = null

    /**
     * 已解除委托
     */
    var released: String? = null

    var walletAddress: String? = null

    /**
     * 是否为链初始化时内置的候选人
     * 0.7.3 新增字段
     */
    var isInit = false

    /**
     * 已委托  单位von
     */
    var delegated: String? = null

    /**
     * 0.7.5新增字段
     */
    var isConsensus = false

    /**
     * 待领取的奖励
     */
    var withdrawReward: String? = null

    fun getIsInit(): Boolean {
        return isInit
    }

    fun setIsInit(init: Boolean) {
        isInit = init
    }
    fun getIsConsensus(): Boolean {
        return isConsensus
    }

    fun setIsConsensus(consensus: Boolean) {
        isConsensus = consensus
    }
}

Note that the isConsensus and isInit fields in the Delegate Item Info structure both start with “is”, so you need to override the set and get methods for these two fields. Display the list of nodes after getting it.

Realize the Function of Delegating Redemption

The layout code can be found in res/layout/activity_withdraw_delegate.xml, and the page will look like this:

1659C2F945C9F9C379A2036880F06C5D

Then create the corresponding logic class Withdraw Delegate Activity under the activity package:
The interface information for Delegating Redemption:
1, Interface name: 1005
2, The parameters are: staking Block Num, node ID, The number of redeemed LAT

So we need to get staking Block Num, which could be got from the interface get Related List By Del Addr which is used to delegate Smart Contracts.

The information of the interface is shown as below:
1, Interface name: 1103
2, The parameter is wallet addresses
The return message is:

class DelegationIdInfo {
    var addr: String? = null //  验证人节点的地址

    var nodeId: String? = null //  验证人的节点Id

    var stakingBlockNum: BigInteger? = null // 发起委托时的区块高度
}

The code to call this interface is as follows:

    /**
     * 获取指定钱包的委托的节点的信息
     */
    suspend fun GetRelatedListByDelAddr(address: String): List<DelegationIdInfo> {
        // 获取钱包委托列表函数名为 1103
        // 参数为钱包地址
        val result = ArrayList<RlpType>()
        with(result) {
            // 构造函数名
            add(RlpString.create(RlpEncoder.encode(RlpString.create(1103))))
            // 钱包地址
            add(RlpString.create(RlpEncoder.encode(RlpString.create(Bech32.addressDecode(address)))))
        }
        //
        val data = Hex.toHexString(RlpEncoder.encode(RlpList(result)))
        // 添加 0x
        val preHexData = Numeric.prependHexPrefix(data)
        val params = ArrayList<Any>()
        //param的格式为
        // {
        //  from: "" 调用钱包地址
        //  to: ""  委托智能合约地址
        //  data: ""  调用的参数
        // }
        // 这里用一个map做参数传递
        val callData = HashMap<String, String>()
        callData["from"] = address
        // 委托智能合约的地址
        callData["to"] = "lat1zqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzsjx8h7"
        callData["data"] = preHexData
        params.add(callData)

        params.add("latest")
        val platonResult = doCall("platon_call", params)
        // 返回结果是以0x开头的16进制字符串, 需要把0x去掉
        val callResult = Numeric.cleanHexPrefix(platonResult.result)
        // 解析返回结果, 返回的是16进制格式需要, 解码成普通字符串
        val jsonMap = JSONUtil.jsonToMap(String(Hex.decode(callResult)))

        // 如果没有委托信息,则返回空列表
        val ret = jsonMap["Ret"] ?: return ArrayList()

        val jsonStr = JSONUtil.toJSONString(ret)
        //
        return JSONUtil.parseArray(jsonStr, DelegationIdInfo::class.java)
    }

The call to this interface is serialized in the same way as the previous call to the delegate, since it is called in the platon_call method, there is no need to sign it with a private key. Also, note that the results obtained from the node using this method start with 0x which need to be removed when processing the results.

This interface returns information about all the delegated nodes at the wallet address, and if you need to redeem a specific node, you need to get the corresponding staking Block Num from the nodeId. The code is as follows:

    /**
     * 获取在指定节点的委托信息
     */
    private suspend fun getDelegationIdInfo(): BigInteger {
        val walletAddress = WalletManager.GetWalletAddress(walletName)

        val delegateNodeList = PlatonApi.GetRelatedListByDelAddr(walletAddress)
        delegateNodeList.forEach {

            // 从区块链中获取的nodeId是不带0x, 需要手动加上
            if (Numeric.prependHexPrefix(it.nodeId) == nodeId) {
                return it.stakingBlockNum!!
            }
        }
        return BigInteger.ZERO
    }

It should be noted that since the node IDs we display on the interface start with 0x, while the node Id returned by this interface does not start with 0x, so when comparing the node IDs, you need to add 0x.
Once you have obtained the staking Block Num, you can redeem the delegate with the following code:

    /**
     * 赎回委托的LAT
     */
    suspend fun UnDelegate(privateKey: String,  stakingBlockNum: BigInteger, nodeId: String, lat: String): PlatonReceiptInfo? {
        // 赎回委托的函数名为 1005
        // 参数依次为委托时的块高, 委托的节点ID, 赎回委托lat的数量
        val result = ArrayList<RlpType>()
        // 委托的函数名为1005
        with(result) {
            // 构造函数名
            add(RlpString.create(RlpEncoder.encode(RlpString.create(1005))))
            // 委托时的块高
            add(RlpString.create(RlpEncoder.encode(RlpString.create(stakingBlockNum))))
            // 委托的节点id
            add(
                RlpString.create(
                    RlpEncoder.encode(
                        RlpString.create(
                            Numeric.hexStringToByteArray(
                                nodeId
                            )
                        )
                    )
                )
            )
            //赎回委托金额
            val von = Convert.toVon(lat, Convert.Unit.LAT).toBigInteger()
            add(RlpString.create(RlpEncoder.encode(RlpString.create(von))))
        }

        val data = Hex.toHexString(RlpEncoder.encode(RlpList(result)))
        // 委托的智能合约地址为: lat1zqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzsjx8h7
        return sendRawTransaction(
            privateKey, "lat1zqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzsjx8h7", 0,
            49920, data
        )
    }

Here the gaslimit is 49920.

Here we demonstrate how to redeem 12.5 LATs, as shown below:

2CF3E12229AA63C8BE46F01E1D681621

Then see the record of the redemption order from the transaction list:

B3743EC7DC3D527DF4CB4B8313D06DFB

Implementing the Function of Collecting Delegated Rewards

The page where you can collect your rewards is a pop-up dialogue box, the layout code of which can be found in res/layout/dialog_claim_rewards.xml,

The effect is like below:

BA107954DD4F5BBB34FB6787413CA5D7

Then create the corresponding logic Claim Rewards Dialog under the dialog package.

Here is an explanation of the interface for collecting rewards:
1, The contract address is: lat1zqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxlcypcy
2, The name of interface is: 5000
3, None parameter here
4, A maximum of 20 nodes can be claimed at any one time. If more than that, multiple actions will be required.

The code to call this interface is as follows:

    /**
     * 领取委托奖励
     */
    suspend fun WithdrawDelegateReward(privateKey: String): PlatonReceiptInfo? {

        // 领取委托的奖励函数名为 5000
        // 没有参数,因此只需要序列化调用 函数名即可
        val result = ArrayList<RlpType>()
        //
        result.add(RlpString.create(RlpEncoder.encode(RlpString.create(5000))))

        val data = Hex.toHexString(RlpEncoder.encode(RlpList(result)))

        return sendRawTransaction(
            privateKey,
            "lat1zqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxlcypcy",
            0,
            38640,
            data
        )
    }

After receiving your award, the commission page will look like this:

622614ADFA9110FE20EE6D8ADC37B99A

You can see that there are currently no more rewards to collect, and a record of rewards collected has been added to the transaction list, as shown below:

793569981DE68A1E088E362F3F31ACE7

Well, that’s all of this chapter.

In Chapter 7 and this chapter, we learned how to build the functions to initiate a commission, redeem a commission and receive a commission reward, and we also learned how to call a smart contract and parse the returned results.

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

Publisher:PlatOnWorld-Kita,Please indicate the source for forwarding:https://platonworld.org/?p=6931

Like (0)
PlatOnWorld-Kita's avatarPlatOnWorld-KitaOfficial
Previous March 22, 2022 12:00
Next March 22, 2022 19:17

相关推荐

Leave a Reply

Please Login to Comment