Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON-like data structure #9

Open
conr2d opened this issue Sep 23, 2021 · 1 comment
Open

JSON-like data structure #9

conr2d opened this issue Sep 23, 2021 · 1 comment

Comments

@conr2d
Copy link
Contributor

conr2d commented Sep 23, 2021

Background

We can write EOSIO application with any languages, but JavaScript is widely used and eosjs is considered as de facto. On the contract side, multi_index or action arguments written in C++ require static types unlike its interface written in JavaScript.

In nodeos, we already use fc::variant which can accept the value that fits the predefined set of types.
https://github.com/EOSIO/fc/blob/0b45f08f/include/fc/variant.hpp#L193-L204

eosio::any (Intentionally, I avoid using the name json, because the detailed specification can be different to support extended features.) supports various type of values by one type.

struct [[eosio::table("records")]] record {
  uint64_t id;
  eosio::any data;

  uint64_t primary_key() const { return id; }
};
typedef eosio::multi_index<"records"_n, record> records;

[[eosio::action]]
void storenum(uint64_t num) {
  records rs(_self, _self.value);
  rs.emplace_back(_self, [&](auto& r) {
    r.id = rs.available_primary_key();
    r.data = num;
  });
}

[[eosio::action]]
void storestring(const std::string& str) {
  records rs(_self, _self.value);
  rs.emplace_back(_self, [&](auto& r) {
    r.id = rs.available_primary_key();
    r.data = str;
  });
}

// `any` can replace the memo of eosio.token::transfer or `receipt` inline actions for recording action result.
[[eosio::action]]
void transfer(eosio::name from, eosio::name to, eosio::asset quantity, eosio::any data);

// An action that needs to handle various type of data (like admin) can use `any`.
[[eosio::action]]
void almighty(eosio::name sender, eosio::any data);

Implementation

Above implementation utilizes std::variant infra, so doesn't need consensus change.

// [[eosio::action]]
// void almighty(eosio::name sender, eosio::any data);

(async () => {
  const result = await api.transact({
    actions: [{
      account: 'anytest',
      name: 'almighty',
      authorization: [{
        actor: 'alice',
        permission: 'active',
      }],
      data: {
        sender: 'alice',
        data: {}, // any JSON-compatible type can be here, `null`, boolean, number, string, array, object ...
      },
    }]
  }, {
    blocksBehind: 3,
    expireSeconds: 30,
  });
  console.dir(result);
})();

For utilizing the benefit of eosio::any completely, it's necessary to add new built-in type any. Nodeos adopting this can accept JSON directly or return pretty stringified result when querying eosio::any data. Whether adopting built-in type or not doesn't affect data exchange between nodes. (Not consensus change, but interface-level difference)

Without built-in type support:

// get_table_rows RPC
{
  "rows": [{
    "id": 0,
    "data": ["number", 999]
  }, {
    "id": 1,
    "data": ["string", "alice"]
  }]
}

// CLI
cleos push action anytest almighty '["alice", ["number", 999]]' -p alice@active
cleos push action anytest almighty '["alice", ["string", "alice"]]' -p alice@active

With built-in type support:

// get_table_rows RPC
{
  "rows": [{
    "id": 0,
    "data": 999
  }, {
    "id": 1,
    "data": "alice"
  }]
}

// CLI
cleos push action anytest almighty '["alice", "999"]' -p alice@active
cleos push action anytest almighty '["alice", "\"alice\""]' -p alice@active
@conr2d
Copy link
Contributor Author

conr2d commented Sep 23, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant