-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathchain_api_plugin.cpp
More file actions
160 lines (135 loc) · 8.7 KB
/
chain_api_plugin.cpp
File metadata and controls
160 lines (135 loc) · 8.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <eosio/chain_api_plugin/chain_api_plugin.hpp>
#include <eosio/chain/exceptions.hpp>
#include <fc/io/json.hpp>
namespace eosio {
static appbase::abstract_plugin& _chain_api_plugin = app().register_plugin<chain_api_plugin>();
using namespace eosio;
class chain_api_plugin_impl {
public:
chain_api_plugin_impl(controller& db)
: db(db) {}
controller& db;
};
chain_api_plugin::chain_api_plugin(){}
chain_api_plugin::~chain_api_plugin(){}
void chain_api_plugin::set_program_options(options_description&, options_description&) {}
void chain_api_plugin::plugin_initialize(const variables_map&) {}
struct async_result_visitor : public fc::visitor<fc::variant> {
template<typename T>
fc::variant operator()(const T& v) const {
return fc::variant(v);
}
};
namespace {
template<typename T>
T parse_params(const std::string& body) {
if (body.empty()) {
EOS_THROW(chain::invalid_http_request, "A Request body is required");
}
try {
try {
return fc::json::from_string(body).as<T>();
} catch (const chain::chain_exception& e) { // EOS_RETHROW_EXCEPTIONS does not re-type these so, re-code it
throw fc::exception(e);
}
} EOS_RETHROW_EXCEPTIONS(chain::invalid_http_request, "Unable to parse valid input from POST body");
}
}
#define CALL_WITH_400(api_version, api_name, api_handle, api_namespace, call_name, http_response_code, params_type) \
{std::string("/" #api_version "/" #api_name "/" #call_name), \
[api_handle](string, string body, url_response_callback cb) mutable { \
api_handle.validate(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params, params_type>(body);\
fc::variant result( api_handle.call_name( std::move(params) ) ); \
cb(http_response_code, std::move(result)); \
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
}}
#define CALL_ASYNC_WITH_400(api_version, api_name, api_handle, api_namespace, call_name, call_result, http_response_code, params_type) \
{std::string("/" #api_version "/" #api_name "/" #call_name), \
[api_handle](string, string body, url_response_callback cb) mutable { \
api_handle.validate(); \
try { \
auto params = parse_params<api_namespace::call_name ## _params ## _ ## api_version, params_type>(body);\
api_handle.call_name( std::move(params),\
[cb, body](const std::variant<fc::exception_ptr, call_result>& result){\
if (std::holds_alternative<fc::exception_ptr>(result)) {\
try {\
std::get<fc::exception_ptr>(result)->dynamic_rethrow_exception();\
} catch (...) {\
http_plugin::handle_exception(#api_name, #call_name, body, cb);\
}\
} else {\
cb(http_response_code, std::visit(async_result_visitor(), result));\
}\
});\
} catch (...) { \
http_plugin::handle_exception(#api_name, #call_name, body, cb); \
} \
}\
}
#define CHAIN_RO_CALL(call_name, http_response_code, params_type) CALL_WITH_400(v1, chain, ro_api, chain_apis::read_only, call_name, http_response_code, params_type)
#define CHAIN_RW_CALL(call_name, http_response_code, params_type) CALL_WITH_400(v1, chain, rw_api, chain_apis::read_write, call_name, http_response_code, params_type)
#define CHAIN_TQ_CALL(call_name, http_response_code, params_type) CALL_WITH_400(v1, chain, tq_api, chain_apis::table_query, call_name, http_response_code, params_type)
#define CHAIN_RO_CALL_ASYNC(call_name, call_result, http_response_code, params_type) CALL_ASYNC_WITH_400(v1, chain, ro_api, chain_apis::read_only, call_name, call_result, http_response_code, params_type)
#define CHAIN_RW_CALL_ASYNC(call_name, call_result, http_response_code, params_type) CALL_ASYNC_WITH_400(v1, chain, rw_api, chain_apis::read_write, call_name, call_result, http_response_code, params_type)
#define CHAIN_RO_CALL_WITH_400(call_name, http_response_code, params_type) CALL_WITH_400(v1, chain, ro_api, chain_apis::read_only, call_name, http_response_code, params_type)
#define CHAIN_RO_CALL_V2(call_name, http_response_code, params_type) CALL_WITH_400(v2, chain, ro_api, chain_apis::read_only, call_name, http_response_code, params_type)
#define CHAIN_RW_CALL_V2(call_name, http_response_code, params_type) CALL_WITH_400(v2, chain, rw_api, chain_apis::read_write, call_name, http_response_code, params_type)
#define CHAIN_RO_CALL_ASYNC_V2(call_name, call_result, http_response_code, params_type) CALL_ASYNC_WITH_400(v2, chain, ro_api, chain_apis::read_only, call_name, call_result, http_response_code, params_type)
#define CHAIN_RW_CALL_ASYNC_V2(call_name, call_result, http_response_code, params_type) CALL_ASYNC_WITH_400(v2, chain, rw_api, chain_apis::read_write, call_name, call_result, http_response_code, params_type)
#define CHAIN_RO_CALL_WITH_400_V2(call_name, http_response_code, params_type) CALL_WITH_400(v2, chain, ro_api, chain_apis::read_only, call_name, http_response_code, params_type)
void chain_api_plugin::plugin_startup() {
ilog( "starting chain_api_plugin" );
my.reset(new chain_api_plugin_impl(app().get_plugin<chain_plugin>().chain()));
auto& chain = app().get_plugin<chain_plugin>();
auto tq_api = chain.get_table_query_api();
auto ro_api = chain.get_read_only_api();
auto rw_api = chain.get_read_write_api();
auto& _http_plugin = app().get_plugin<http_plugin>();
ro_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() );
tq_api.set_shorten_abi_errors( !_http_plugin.verbose_errors() );
_http_plugin.add_api({
CHAIN_RO_CALL(get_info, 200, http_params_types::no_params_required)}, appbase::priority::medium_high);
_http_plugin.add_api({
CHAIN_RO_CALL(get_activated_protocol_features, 200, http_params_types::possible_no_params),
CHAIN_RO_CALL(get_block, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_block_info, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_block_header_state, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_account, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_code, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_code_hash, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_abi, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_raw_code_and_abi, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_raw_abi, 200, http_params_types::params_required),
CHAIN_TQ_CALL(get_table_rows, 200, http_params_types::params_required),
CHAIN_TQ_CALL(get_kv_table_rows, 200, http_params_types::params_required),
CHAIN_TQ_CALL(get_table_by_scope, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_currency_balance, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_currency_stats, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_producers, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_producer_schedule, 200, http_params_types::no_params_required),
CHAIN_RO_CALL(abi_json_to_bin, 200, http_params_types::params_required),
CHAIN_RO_CALL(abi_bin_to_json, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_required_keys, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_transaction_id, 200, http_params_types::params_required),
CHAIN_RO_CALL_ASYNC(send_ro_transaction, chain_apis::read_only::send_ro_transaction_results, 200, http_params_types::params_required),
CHAIN_RW_CALL_ASYNC(push_block, chain_apis::read_write::push_block_results, 202, http_params_types::params_required),
CHAIN_RW_CALL_ASYNC(push_transaction, chain_apis::read_write::push_transaction_results, 202, http_params_types::params_required),
CHAIN_RW_CALL_ASYNC(push_transactions, chain_apis::read_write::push_transactions_results, 202, http_params_types::params_required),
CHAIN_RW_CALL_ASYNC_V2(send_transaction, chain_apis::read_write::push_transaction_results, 202, http_params_types::params_required),
CHAIN_RW_CALL_ASYNC(send_transaction, chain_apis::read_write::send_transaction_results, 202, http_params_types::params_required),
CHAIN_RO_CALL(get_all_accounts, 200, http_params_types::params_required),
CHAIN_RO_CALL(get_consensus_parameters, 200, http_params_types::no_params_required),
CHAIN_RO_CALL(get_genesis, 200, http_params_types::no_params_required)
});
if (chain.account_queries_enabled()) {
_http_plugin.add_async_api({
CHAIN_RO_CALL_WITH_400(get_accounts_by_authorizers, 200, http_params_types::params_required),
});
}
}
void chain_api_plugin::plugin_shutdown() {}
}