EOS 中如何传递结构体 struct 给 action

yufei       5 年, 6 月 前       1373

如果一个 action 需要的参数越来越多,可能选择定义一个 struct 参数是一个更明智的选择。比如下面这个 action

hello.cpp

#include<eosiolib/eosio.hpp>
#include<eosiolib/asset.hpp>
using namespace eosio;

class [[eosio::contract]] hello: eosio::contract {
public:
    using eosio::contract::contract;

    [[eosio::action]] void hi(
        name from_contract,
        asset from_currency,
        name to_contract,
        asset to_currency,
        uint64_t ratio,
        bool  enabled,
        name  owner
    ){}
};

EOSIO_DISPATCH(hello,(hi))

7 个参数,够吓人的了,我在某个合约的时候最多看到 14 个参数。

本着简单化的原则,我们可以把这些参数都放到一个结构体 struct 中,例如

#include<eosiolib/eosio.hpp>
#include<eosiolib/asset.hpp>
using namespace eosio;

struct setting {
    name from_contract;
    asset from_currency;
    name to_contract;
    asset to_currency;
    uint64_t ratio;
    bool  enabled;
    name  owner;
};

class [[eosio::contract]] hello: eosio::contract {
public:
    using eosio::contract::contract;
    [[eosio::action]] void hi(const setting& s){}
};

EOSIO_DISPATCH(hello,(hi))

使用下面的命令编译

eosio-cpp -o hello.wasm hello.cpp --abigen

然后使用下面的命令来部署下这个合约

cleos set contract hello ../hello -p hello@active

编译完成后,我们打开 hello.abi 可以看到内容如下

{
    "____comment": "This file was generated with eosio-abigen. DO NOT EDIT Sat Nov 10 07:37:54 2018",
    "version": "eosio::abi/1.0",
    "structs": [
        {
            "name": "hi",
            "base": "",
            "fields": [
                {
                    "name": "s",
                    "type": "setting"
                }
            ]
        },
        {
            "name": "setting",
            "base": "",
            "fields": [
                {
                    "name": "from_contract",
                    "type": "name"
                },
                {
                    "name": "from_currency",
                    "type": "asset"
                },
                {
                    "name": "to_contract",
                    "type": "name"
                },
                {
                    "name": "to_currency",
                    "type": "asset"
                },
                {
                    "name": "ratio",
                    "type": "uint64"
                },
                {
                    "name": "enabled",
                    "type": "bool"
                },
                {
                    "name": "owner",
                    "type": "name"
                }
            ]
        }
    ],
    "types": [],
    "actions": [
        {
            "name": "hi",
            "type": "hi",
            "ricardian_contract": ""
        }
    ],
    "tables": [],
    "ricardian_clauses": [],
    "abi_extensions": []
}

那么,面对这个结构体,我们要如何传递参数呢 ?

首先,想到的肯定是常规的传递方式

cleos push action hello hi '[{"from_contract":"hello","from_currency":"0.0000 EOS","to_contract":"hi","to_currency":"0.0000 SYS","ratio":"50","enabled":true,"owner":"eosio"}]' -p hello@active

上面这个是没啥问题的对吧,但是,如果有两个参数,其中有一个参数是普通参数,又会发生什么事情呢?

我们把结构体精简下,哈哈,不然看起来太复杂了

#include<eosiolib/eosio.hpp>
#include<eosiolib/asset.hpp>
using namespace eosio;

struct setting {
    name from_contract;
    asset from_currency;
};

class [[eosio::contract]] hello: eosio::contract {
public:
    using eosio::contract::contract;
    [[eosio::action]] void hi(const name &from , const setting& s){}
};

EOSIO_DISPATCH(hello,(hi))

可以看到 hello.abi 内容如下

{
    "____comment": "This file was generated with eosio-abigen. DO NOT EDIT Sat Nov 10 07:50:30 2018",
    "version": "eosio::abi/1.0",
    "structs": [
        {
            "name": "hi",
            "base": "",
            "fields": [
                {
                    "name": "from",
                    "type": "name"
                },
                {
                    "name": "s",
                    "type": "setting"
                }
            ]
        },
        {
            "name": "setting",
            "base": "",
            "fields": [
                {
                    "name": "from_contract",
                    "type": "name"
                },
                {
                    "name": "from_currency",
                    "type": "asset"
                }
            ]
        }
    ],
    "types": [],
    "actions": [
        {
            "name": "hi",
            "type": "hi",
            "ricardian_contract": ""
        }
    ],
    "tables": [],
    "ricardian_clauses": [],
    "abi_extensions": []
}

部署完成后,还可以采用传参方式

cleos push action hello hi '["from",{"from_contract":"hello","from_currency":"0.0000 EOS"}]' -p hello@active

P.S 这个在早期的版本是有 bug 的,不过最新的版本已经修正了。 如果你发现不能这样做,那么,将 eosio.cdt 升级到最新的版本吧

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.