#include "core/foundation.hpp" #include "core/protocol_impl.hpp" #include "core/protobuf_protocol_impl.hpp" #include "core/protocol_impl.inl" #include "core/protobuf_protocol_impl.inl" #include <iostream> #include <emscripten/bind.h> using namespace cpp; using namespace emscripten; using manabar_fn_t = result(const int32_t, const uint32_t, const uint32_t, const uint32_t, const uint32_t, const uint32_t); using ext_json_asset_fn_t = json_asset(const int32_t, const int32_t)const; /// unfortunetely emscripten can't handle correctly C++ set -> JS Set transformation, so we have to use a vector instead. struct required_authority_collectionV { typedef std::vector<std::string> account_vector; typedef account_vector account_collection_t; account_vector posting_accounts; account_vector active_accounts; account_vector owner_accounts; std::vector<wax_authority> other_authorities; }; using authority_verification_trace = hive::protocol::authority_verification_trace; class foundation_wasm : public foundation { private: long long join_lh(int32_t low, int32_t high)const { return (long long) high << 32 | (uint32_t) low; } unsigned long long join_lh(uint32_t low, uint32_t high)const { return (unsigned long long) high << 32 | low; } public: using required_authority_collection_t = required_authority_collectionV; result cpp_calculate_manabar_full_regeneration_time(const int32_t now, const uint32_t max_mana_low, const uint32_t max_mana_high, const uint32_t current_mana_low, const uint32_t current_mana_high, const uint32_t last_update_time) { return foundation::cpp_calculate_manabar_full_regeneration_time(now, join_lh(max_mana_low, max_mana_high), join_lh(current_mana_low, current_mana_high), last_update_time); } result cpp_calculate_current_manabar_value(const int32_t now, const uint32_t max_mana_low, const uint32_t max_mana_high, const uint32_t current_mana_low, const uint32_t current_mana_high, const uint32_t last_update_time) { return foundation::cpp_calculate_current_manabar_value(now, join_lh(max_mana_low, max_mana_high), join_lh(current_mana_low, current_mana_high), last_update_time); } json_asset cpp_general_asset(const uint32_t asset_num, const int32_t amount_low, const int32_t amount_high)const { return foundation::cpp_general_asset(asset_num, join_lh(amount_low, amount_high)); } json_asset cpp_hive(const int32_t amount_low, const int32_t amount_high)const { return foundation::cpp_hive(join_lh(amount_low, amount_high)); } json_asset cpp_hbd(const int32_t amount_low, const int32_t amount_high)const { return foundation::cpp_hbd(join_lh(amount_low, amount_high)); } json_asset cpp_vests(const int32_t amount_low, const int32_t amount_high)const { return foundation::cpp_vests(join_lh(amount_low, amount_high)); } witness_set_properties_serialized cpp_serialize_witness_set_properties(const witness_set_properties_data& value) const { return foundation::cpp_serialize_witness_set_properties(value); } witness_set_properties_data cpp_deserialize_witness_set_properties(const witness_set_properties_serialized& value) const { return foundation::cpp_deserialize_witness_set_properties(value); } std::string cpp_asset_value(const json_asset& value) const { return foundation::cpp_asset_value(value); } std::string cpp_asset_symbol(const json_asset& value) const { return foundation::cpp_asset_symbol(value); } void cpp_throws(int value) const { foundation::cpp_throws(value); } crypto_memo cpp_crypto_memo_from_string(const std::string& value) const { return foundation::cpp_crypto_memo_from_string(value); } std::string cpp_crypto_memo_dump_string(const crypto_memo& value) const { return foundation::cpp_crypto_memo_dump_string(value); } void cpp_scan_text_for_matching_private_keys(const std::string& text, const std::string& account, const wax_authorities& auths, const std::string& memo_key, const std::vector<std::string>& imported_keys) const { return foundation::cpp_check_memo_for_private_keys(text, account, auths, memo_key, imported_keys); } brain_key_data cpp_suggest_brain_key() { return foundation::cpp_suggest_brain_key(); } result cpp_generate_private_key() { return foundation::cpp_generate_private_key(); } private_key_data cpp_generate_private_key_password_based(const std::string& account, const std::string& role, const std::string& password) { return foundation::cpp_generate_private_key(account, role, password); } std::string cpp_convert_raw_private_key_to_wif(const std::string& hexData) { return foundation::cpp_convert_raw_private_key_to_wif(hexData); } std::string cpp_convert_raw_public_key_to_wif(const std::string& hexData) { return foundation::cpp_convert_raw_public_key_to_wif(hexData); } result cpp_get_public_key_from_signature(const std::string& digest, const std::string& signature) { return foundation::cpp_get_public_key_from_signature(digest, signature); } result cpp_calculate_public_key(const std::string& wif) { return foundation::cpp_calculate_public_key(wif); } std::map<std::string, std::string> cpp_get_hive_protocol_config(const std::string& chain_id) { return foundation::cpp_get_hive_protocol_config(chain_id); } ref_block_data cpp_get_tapos_data(const std::string& block_id) { return foundation::cpp_get_tapos_data(block_id); } std::string cpp_get_address_prefix() { return HIVE_ADDRESS_PREFIX; } result cpp_calculate_hp_apr( const uint32_t head_block_num, const uint16_t vesting_reward_percent, const json_asset& virtual_supply, const json_asset& total_vesting_fund_hive) const { return foundation::cpp_calculate_hp_apr( head_block_num, vesting_reward_percent, virtual_supply, total_vesting_fund_hive); } json_asset cpp_hbd_to_hive(const json_asset &hbd, const json_asset& base, const json_asset& quote) const { return foundation::cpp_hbd_to_hive(hbd, base, quote); } json_asset cpp_hive_to_hbd(const json_asset& amount, const json_asset& base, const json_asset& quote) const { return foundation::cpp_hive_to_hbd(amount, base, quote); } json_asset cpp_vests_to_hp(const json_asset& vests, const json_asset& total_vesting_fund_hive, const json_asset& total_vesting_shares) const { return foundation::cpp_vests_to_hp(vests, total_vesting_fund_hive, total_vesting_shares); } json_asset cpp_hp_to_vests(const json_asset& vests, const json_asset& total_vesting_fund_hive, const json_asset& total_vesting_shares) const { return foundation::cpp_hp_to_vests(vests, total_vesting_fund_hive, total_vesting_shares); } result cpp_calculate_inflation_rate_for_block(const uint32_t block_num) const { return foundation::cpp_calculate_inflation_rate_for_block( block_num ); } json_asset cpp_estimate_hive_collateral( const json_price& current_median_history, const json_price& current_min_history, const json_asset& hbd_amount_to_get ) const { return foundation::cpp_estimate_hive_collateral( current_median_history, current_min_history, hbd_amount_to_get ); } bool cpp_is_valid_account_name( const std::string& name ) const { return foundation::cpp_is_valid_account_name( name ); } }; class AccountAuthorityProviderWrapper final : public emscripten::wrapper<IAccountAuthorityProvider> { public: EMSCRIPTEN_WRAPPER(AccountAuthorityProviderWrapper); virtual std::optional<wax_authority> getAuthority(std::string account_name, std::string authorityRole) override { return call<std::optional<wax_authority>>("getAuthority", account_name, authorityRole); } virtual std::optional<std::string> getWitnessPublicKey(std::string account_name) override { return call<std::optional<std::string>>("getWitnessPublicKey", account_name); } }; using protocol_wasm = cpp::protocol_impl<foundation_wasm>; using proto_protocol_wasm = cpp::proto_protocol_impl<foundation_wasm>; EMSCRIPTEN_BINDINGS(wax_api_instance) { enum_<error_code>("error_code") .value("fail", error_code::fail) .value("ok", error_code::ok) ; value_object<result>("result") .field("value", &result::value) .field("content", &result::content) .field("exception_message", &result::exception_message) ; value_object<brain_key_data>("brain_key_data") .field("associated_public_key", &brain_key_data::associated_public_key) .field("brain_key", &brain_key_data::brain_key) .field("wif_private_key", &brain_key_data::wif_private_key) ; value_object<private_key_data>("private_key_data") .field("associated_public_key", &private_key_data::associated_public_key) .field("wif_private_key", &private_key_data::wif_private_key) ; value_object<json_asset>("json_asset") .field("amount", &json_asset::amount) .field("precision", &json_asset::precision) .field("nai", &json_asset::nai) ; value_object<crypto_memo>("crypto_memo") .field("from", &crypto_memo::_from) .field("to", &crypto_memo::to) .field("content", &crypto_memo::content) ; value_object<wax_authority>("wax_authority") .field("weight_threshold", &wax_authority::weight_threshold) .field("account_auths", &wax_authority::account_auths) .field("key_auths", &wax_authority::key_auths) ; value_object<wax_authorities>("wax_authorities") .field("active", &wax_authorities::active) .field("owner", &wax_authorities::owner) .field("posting", &wax_authorities::posting) ; value_object<required_authority_collectionV>("required_authority_collection") .field("posting_accounts", &required_authority_collectionV::posting_accounts) .field("active_accounts", &required_authority_collectionV::active_accounts) .field("owner_accounts", &required_authority_collectionV::owner_accounts) .field("other_authorities", &required_authority_collectionV::other_authorities) ; value_object<ref_block_data>("ref_block_data") .field("ref_block_num", &ref_block_data::ref_block_num) .field("ref_block_prefix", &ref_block_data::ref_block_prefix) ; value_object<json_price>("json_price") .field("base", &json_price::base) .field("quote", &json_price::quote) ; value_object<binary_data_node>("binary_data_node") .field("key", &binary_data_node::key) .field("type", &binary_data_node::type) .field("offset", &binary_data_node::offset) .field("size", &binary_data_node::size) .field("value", &binary_data_node::value) .field("length", &binary_data_node::length) .field("children", &binary_data_node::children) ; value_object<binary_data>("binary_data") .field("binary", &binary_data::binary) .field("offsets", &binary_data::offsets) ; register_optional<std::string>(); register_optional<uint32_t>(); register_optional<uint16_t>(); register_optional<int32_t>(); register_optional<json_asset>(); register_optional<json_price>(); register_vector<std::string>("VectorString"); // Required for map binding -> keys() method register_vector<wax_authority>("VectorWaxAuthority"); register_vector<binary_data_node>("VectorBinaryDataNode"); register_vector<authority_verification_trace::path_entry>("VectorPathEntry"); register_map<std::string, std::string>("MapStringString"); register_map<std::string, uint16_t>("MapStringUInt16"); value_object<witness_set_properties_data>("witness_set_properties_data") .field("key", &witness_set_properties_data::key) .field("new_signing_key", &witness_set_properties_data::new_signing_key) .field("account_creation_fee", &witness_set_properties_data::account_creation_fee) .field("url", &witness_set_properties_data::url) .field("hbd_exchange_rate", &witness_set_properties_data::hbd_exchange_rate) .field("maximum_block_size", &witness_set_properties_data::maximum_block_size) .field("hbd_interest_rate", &witness_set_properties_data::hbd_interest_rate) .field("account_subsidy_budget", &witness_set_properties_data::account_subsidy_budget) .field("account_subsidy_decay", &witness_set_properties_data::account_subsidy_decay) ; value_object<authority_verification_trace::path_entry>("path_entry") .field("processed_entry", &authority_verification_trace::path_entry::processed_entry) .field("processed_role", &authority_verification_trace::path_entry::processed_role) .field("recursion_depth", &authority_verification_trace::path_entry::recursion_depth) .field("threshold", &authority_verification_trace::path_entry::threshold) .field("weight", &authority_verification_trace::path_entry::weight) .field("flags", &authority_verification_trace::path_entry::flags) .field("visited_entries", &authority_verification_trace::path_entry::visited_entries) ; value_object<authority_verification_trace>("authority_verification_trace") .field("root", &authority_verification_trace::root) .field("final_authority_path", &authority_verification_trace::final_authority_path) .field("verification_status", &authority_verification_trace::verification_status) ; class_<IAccountAuthorityProvider>("IAccountAuthorityProvider") .allow_subclass<AccountAuthorityProviderWrapper>("AccountAuthorityProviderWrapper") .function("getAuthority", &IAccountAuthorityProvider::getAuthority, pure_virtual()) .function("getWitnessPublicKey", &IAccountAuthorityProvider::getWitnessPublicKey, pure_virtual()) ; class_<foundation_wasm>("protocol_foundation") .constructor<>() .function("cpp_get_address_prefix", &foundation_wasm::cpp_get_address_prefix) .function("cpp_calculate_public_key", &foundation_wasm::cpp_calculate_public_key) .function("cpp_suggest_brain_key", &foundation_wasm::cpp_suggest_brain_key) .function("cpp_get_hive_protocol_config", &foundation_wasm::cpp_get_hive_protocol_config) .function("cpp_generate_private_key", &foundation_wasm::cpp_generate_private_key) .function("cpp_generate_private_key_password_based", &foundation_wasm::cpp_generate_private_key_password_based) .function("cpp_convert_raw_private_key_to_wif", &foundation_wasm::cpp_convert_raw_private_key_to_wif) .function("cpp_convert_raw_public_key_to_wif", &foundation_wasm::cpp_convert_raw_public_key_to_wif) .function("cpp_get_public_key_from_signature", &foundation_wasm::cpp_get_public_key_from_signature) // Based on https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#overloaded-functions: .function("cpp_general_asset", select_overload<json_asset(const uint32_t, const int32_t, const int32_t)const>(&foundation_wasm::cpp_general_asset)) .function("cpp_hive", select_overload<ext_json_asset_fn_t>(&foundation_wasm::cpp_hive)) .function("cpp_hbd", select_overload<ext_json_asset_fn_t>(&foundation_wasm::cpp_hbd)) .function("cpp_vests", select_overload<ext_json_asset_fn_t>(&foundation_wasm::cpp_vests)) .function("cpp_serialize_witness_set_properties", &foundation_wasm::cpp_serialize_witness_set_properties) .function("cpp_deserialize_witness_set_properties", &foundation_wasm::cpp_deserialize_witness_set_properties) .function("cpp_asset_value", &foundation_wasm::cpp_asset_value) .function("cpp_asset_symbol", &foundation_wasm::cpp_asset_symbol) .function("cpp_throws", &foundation_wasm::cpp_throws) .function("cpp_crypto_memo_from_string", &foundation_wasm::cpp_crypto_memo_from_string) .function("cpp_crypto_memo_dump_string", &foundation_wasm::cpp_crypto_memo_dump_string) .function("cpp_scan_text_for_matching_private_keys", &foundation_wasm::cpp_scan_text_for_matching_private_keys) .function("cpp_calculate_manabar_full_regeneration_time", select_overload<manabar_fn_t>(&foundation_wasm::cpp_calculate_manabar_full_regeneration_time)) .function("cpp_calculate_current_manabar_value", select_overload<manabar_fn_t>(&foundation_wasm::cpp_calculate_current_manabar_value)) .function("cpp_get_tapos_data", &foundation_wasm::cpp_get_tapos_data) .function("cpp_calculate_hp_apr", &foundation_wasm::cpp_calculate_hp_apr) .function("cpp_calculate_inflation_rate_for_block", &foundation_wasm::cpp_calculate_inflation_rate_for_block) .function("cpp_vests_to_hp", &foundation_wasm::cpp_vests_to_hp) .function("cpp_hp_to_vests", &foundation_wasm::cpp_hp_to_vests) .function("cpp_hbd_to_hive", &foundation_wasm::cpp_hbd_to_hive) .function("cpp_hive_to_hbd", &foundation_wasm::cpp_hive_to_hbd) .function("cpp_estimate_hive_collateral", &foundation_wasm::cpp_estimate_hive_collateral) .function("cpp_is_valid_account_name", &foundation_wasm::cpp_is_valid_account_name) ; class_<protocol_wasm, base<foundation_wasm>>("protocol") .constructor<>() .function("cpp_operation_get_impacted_accounts", &protocol_wasm::cpp_operation_get_impacted_accounts) .function("cpp_transaction_get_impacted_accounts", &protocol_wasm::cpp_transaction_get_impacted_accounts) .function("cpp_generate_binary_transaction_metadata", &protocol_wasm::cpp_generate_binary_transaction_metadata) .function("cpp_generate_binary_operation_metadata", &protocol_wasm::cpp_generate_binary_operation_metadata) .function("cpp_validate_operation", &protocol_wasm::cpp_validate_operation) .function("cpp_validate_transaction", &protocol_wasm::cpp_validate_transaction) .function("cpp_calculate_transaction_id", &protocol_wasm::cpp_calculate_transaction_id) .function("cpp_calculate_legacy_transaction_id", &protocol_wasm::cpp_calculate_legacy_transaction_id) .function("cpp_calculate_sig_digest", &protocol_wasm::cpp_calculate_sig_digest) .function("cpp_calculate_legacy_sig_digest", &protocol_wasm::cpp_calculate_legacy_sig_digest) .function("cpp_serialize_transaction", &protocol_wasm::cpp_serialize_transaction) .function("cpp_deserialize_transaction", &protocol_wasm::cpp_deserialize_transaction) .function("cpp_collect_transaction_required_authorities", &protocol_wasm::cpp_collect_transaction_required_authorities) .function("cpp_trace_authority_verification", &protocol_wasm::cpp_trace_authority_verification) .function("cpp_get_hive_protocol_config", &protocol_wasm::cpp_get_hive_protocol_config) ; // We have to use it this way because JavaScript (and emscripten in conclusion) doesn't support multiple inheritance class_<proto_protocol_wasm, base<foundation_wasm>>("proto_protocol") .constructor<>() .function("cpp_operation_get_impacted_accounts", &proto_protocol_wasm::cpp_operation_get_impacted_accounts) .function("cpp_transaction_get_impacted_accounts", &proto_protocol_wasm::cpp_transaction_get_impacted_accounts) .function("cpp_generate_binary_transaction_metadata", &proto_protocol_wasm::cpp_generate_binary_transaction_metadata) .function("cpp_generate_binary_operation_metadata", &proto_protocol_wasm::cpp_generate_binary_operation_metadata) .function("cpp_validate_operation", &proto_protocol_wasm::cpp_validate_operation) .function("cpp_validate_transaction", &proto_protocol_wasm::cpp_validate_transaction) .function("cpp_calculate_transaction_id", &proto_protocol_wasm::cpp_calculate_transaction_id) .function("cpp_calculate_legacy_transaction_id", &proto_protocol_wasm::cpp_calculate_legacy_transaction_id) .function("cpp_calculate_sig_digest", &proto_protocol_wasm::cpp_calculate_sig_digest) .function("cpp_calculate_legacy_sig_digest", &proto_protocol_wasm::cpp_calculate_legacy_sig_digest) .function("cpp_serialize_transaction", &proto_protocol_wasm::cpp_serialize_transaction) .function("cpp_deserialize_transaction", &proto_protocol_wasm::cpp_deserialize_transaction) .function("cpp_proto_to_api", &proto_protocol_wasm::cpp_proto_to_api) .function("cpp_proto_to_legacy_api", &proto_protocol_wasm::cpp_proto_to_legacy_api) .function("cpp_api_to_proto", &proto_protocol_wasm::cpp_api_to_proto) .function("cpp_collect_transaction_required_authorities", &proto_protocol_wasm::cpp_collect_transaction_required_authorities) ; } int main() { // Main should not be run during TypeScript generation. // abort(); // std::cout << "This function does nothing... You have to instantiate wax_api on JS side to play with..." << std::endl; return 0; }