From e8a06a70c74fb174d811b014efc87bdf19e786e7 Mon Sep 17 00:00:00 2001 From: feruzm <fmiboy@gmail.com> Date: Fri, 21 Jun 2024 05:29:39 +0300 Subject: [PATCH] tutorials update, sq --- _data/apidefinitions/database_api.yml | 363 ++++----- _data/nav.yml | 4 +- _layouts/default.html | 26 +- _sass/_main.scss | 30 + _tutorials-javascript/account_reputation.md | 64 +- _tutorials-javascript/blog_feed.md | 40 +- _tutorials-javascript/claim_rewards.md | 65 ++ _tutorials-javascript/client_signing.md | 192 +++++ _tutorials-javascript/convert_hbd_to_hive.md | 83 +++ _tutorials-javascript/convert_hive_to_hbd.md | 83 +++ _tutorials-javascript/convert_sbd_to_steem.md | 10 - _tutorials-javascript/create_account.md | 202 +++++ _tutorials-javascript/delegate_power.md | 75 ++ .../edit_content_patching.md | 125 ++++ _tutorials-javascript/follow_a_user.md | 98 +++ _tutorials-javascript/get_account_comments.md | 66 +- _tutorials-javascript/get_account_replies.md | 58 +- .../get_delegations_by_user.md | 104 ++- .../get_follower_and_following_list.md | 104 ++- _tutorials-javascript/get_post_comments.md | 101 ++- _tutorials-javascript/get_post_details.md | 74 +- _tutorials-javascript/get_posts.md | 66 +- .../get_state_replacement_api.md | 91 ++- .../get_voters_list_on_post.md | 80 +- _tutorials-javascript/getting_started.md | 2 + .../grant_active_permission.md | 184 ++++- .../grant_posting_permission.md | 182 ++++- _tutorials-javascript/hivesigner.md | 71 ++ _tutorials-javascript/power_down.md | 75 ++ _tutorials-javascript/power_up_hive.md | 60 ++ _tutorials-javascript/reblogging_post.md | 109 +++ _tutorials-javascript/search_accounts.md | 30 +- _tutorials-javascript/search_tags.md | 40 +- _tutorials-javascript/set_withdraw_route.md | 73 ++ .../stream_blockchain_transactions.md | 59 +- _tutorials-javascript/submit_comment_reply.md | 78 ++ _tutorials-javascript/submit_post.md | 72 ++ .../transfer_hive_and_hbd.md | 74 ++ _tutorials-javascript/vote_on_content.md | 139 ++++ .../witness_listing_and_voting.md | 115 +++ _tutorials-python/account_recovery.md | 148 +++- _tutorials-python/account_reputation.md | 31 +- _tutorials-python/claim_rewards.md | 86 ++- _tutorials-python/convert_hbd_to_hive.md | 48 +- _tutorials-python/convert_hive_to_hbd.md | 49 +- _tutorials-python/delegate_power.md | 86 ++- _tutorials-python/edit_content_patching.md | 90 ++- _tutorials-python/follow_a_user.md | 87 ++- _tutorials-python/get_account_comments.md | 41 +- _tutorials-python/get_account_replies.md | 51 +- _tutorials-python/get_delegations_by_user.md | 54 +- .../get_follower_and_following_list.md | 48 +- _tutorials-python/get_post_comments.md | 42 +- _tutorials-python/get_post_details.md | 41 +- _tutorials-python/get_posts.md | 41 +- _tutorials-python/get_voters_list_on_post.md | 38 +- _tutorials-python/getting_started.md | 5 +- _tutorials-python/grant_active_permission.md | 61 +- _tutorials-python/grant_posting_permission.md | 61 +- _tutorials-python/password_key_change.md | 78 +- _tutorials-python/power_down.md | 82 +- _tutorials-python/power_up_hive.md | 66 +- _tutorials-python/rcdemo.md | 702 +++++++++++++++++- _tutorials-python/reblogging_post.md | 59 +- _tutorials-python/search_accounts.md | 45 +- _tutorials-python/search_tags.md | 42 ++ .../stream_blockchain_transactions.md | 22 +- _tutorials-python/submit_comment_reply.md | 43 +- _tutorials-python/submit_post.md | 51 +- _tutorials-python/transfer_hive_and_hbd.md | 75 +- ...ransfer_hive_and_hbd_to_savings_balance.md | 81 +- _tutorials-python/using_keys_securely.md | 22 + _tutorials-python/vote_on_content.md | 72 +- .../witness_listing_and_voting.md | 64 +- _tutorials-ruby/blog_feed.md | 38 + _tutorials-ruby/convert_hbd_to_hive.md | 32 + _tutorials-ruby/edit_content_patching.md | 56 ++ _tutorials-ruby/follow_another_user.md | 73 ++ _tutorials-ruby/get_account_comments.md | 61 ++ _tutorials-ruby/get_account_replies.md | 61 ++ .../get_follower_and_following_list.md | 39 + _tutorials-ruby/get_post_comments.md | 22 + _tutorials-ruby/get_post_details.md | 165 ++++ _tutorials-ruby/get_posts.md | 63 ++ _tutorials-ruby/get_voters_list_on_post.md | 28 + _tutorials-ruby/reblogging_post.md | 41 + _tutorials-ruby/search_accounts.md | 18 + _tutorials-ruby/search_tags.md | 35 + .../stream_blockchain_transactions.md | 40 + _tutorials-ruby/submit_comment_reply.md | 40 + _tutorials-ruby/submit_post.md | 40 + _tutorials-ruby/vote_on_content.md | 34 + 92 files changed, 6698 insertions(+), 367 deletions(-) delete mode 100644 _tutorials-javascript/convert_sbd_to_steem.md diff --git a/_data/apidefinitions/database_api.yml b/_data/apidefinitions/database_api.yml index 30b3bf09..b38baff0 100644 --- a/_data/apidefinitions/database_api.yml +++ b/_data/apidefinitions/database_api.yml @@ -28,11 +28,12 @@ parameter_json: '{"accounts":[]}' expected_response_json: '{"requests":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_account_recovery_requests", "params": {"accounts":["hiveio"]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_account_recovery_requests", "params": {"accounts":["hiveio"]}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-recovery-request)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_account_recovery_requests)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-recovery-request)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_accounts purpose: | Returns accounts, queried by name. Parameters: `account:string array`; `delayed_votes_active:boolean` @@ -214,13 +215,14 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_accounts", "params": {"accounts":["hiveio"]}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_accounts", "params": {"accounts":["hiveio", "alice"], "delayed_votes_active": false}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_accounts", "params": {"accounts":["hiveio"]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_accounts", "params": {"accounts":["hiveio", "alice"], "delayed_votes_active": false}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-accounts)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.get_all_accounts)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/accounts)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_accounts)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-accounts)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.get_all_accounts)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/accounts)" - api_method: database_api.find_change_recovery_account_requests since: HF11 purpose: | @@ -242,31 +244,34 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_change_recovery_account_requests", "params": {"accounts":["hiveio"]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_change_recovery_account_requests", "params": {"accounts":["hiveio"]}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.find_change_recovery_account_requests)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_change_recovery_account_requests)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.find_change_recovery_account_requests)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_comments purpose: Search for comments by author/permlink. parameter_json: '{"comments":[["author", "permlink"]]}' expected_response_json: '{"comments":[]}' curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_comments", "params": {"comments":[["hiveio", "around-the-hive-reflections"]]}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_comments", "params": {"comments":[["alice", "a-post-by-alice"]]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_comments", "params": {"comments":[["hiveio", "around-the-hive-reflections"]]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_comments", "params": {"comments":[["alice", "a-post-by-alice"]]}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-content)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-content)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_comments)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-content)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-content)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_decline_voting_rights_requests since: HF14 purpose: Returns a list of requests to decline voting rights. parameter_json: '{"accounts":[]}' expected_response_json: '{"requests":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_decline_voting_rights_requests", "params": {"accounts":["temp","null"]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_decline_voting_rights_requests", "params": {"accounts":["temp","null"]}, "id":1}' client_docs: - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_decline_voting_rights_requests)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_escrows since: HF14 purpose: Returns a list of escrows. @@ -304,11 +309,12 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_escrows", "params": {"from": "temp"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_escrows", "params": {"from": "temp"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-escrow)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-escrow)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_escrows)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-escrow)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-escrow)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_limit_orders purpose: Returns a list of limit orders. parameter_json: '{"account":""}' @@ -338,9 +344,10 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_limit_orders", "params": {"account":"temp"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_limit_orders", "params": {"account":"temp"}, "id":1}' client_docs: - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_limit_orders)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_owner_histories purpose: | Returns owner authority history. Parameters: `owner:string` @@ -352,12 +359,13 @@ parameter_json: '{"owner":""}' expected_response_json: '{"owner_auths":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_owner_histories", "params": {"owner":"hiveio"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_owner_histories", "params": {"owner":"alice"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_owner_histories", "params": {"owner":"hiveio"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_owner_histories", "params": {"owner":"alice"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-owner-history)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-owner-history)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_owner_histories)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-owner-history)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-owner-history)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_savings_withdrawals since: HF14 purpose: | @@ -369,11 +377,12 @@ parameter_json: '{"start":null,"limit":0,"order":"by_name"}' expected_response_json: '{"withdrawals":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_savings_withdrawals", "params": {"start":"temp"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_savings_withdrawals", "params": {"start":"temp"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-savings-withdraw-from)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-savings-withdraw-from)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_savings_withdrawals)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-savings-withdraw-from)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-savings-withdraw-from)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_hbd_conversion_requests purpose: | Returns the list of HBD conversion requests for an account. Parameters: `account:string` @@ -385,10 +394,11 @@ parameter_json: '{"account":""}' expected_response_json: '{"requests":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_hbd_conversion_requests", "params": {"account":"hiveio"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_hbd_conversion_requests", "params": {"account":"alice"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_hbd_conversion_requests", "params": {"account":"hiveio"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_hbd_conversion_requests", "params": {"account":"alice"}, "id":1}' client_docs: - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_hbd_conversion_requests)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_vesting_delegation_expirations since: HF17 purpose: | @@ -415,13 +425,14 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegation_expirations", "params": {"account":"hiveio"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegation_expirations", "params": {"account":"alice"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegation_expirations", "params": {"account":"hiveio"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegation_expirations", "params": {"account":"alice"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-vesting-delegations)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_expiring_vesting_delegations)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/delegations)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_vesting_delegation_expirations)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-vesting-delegations)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_expiring_vesting_delegations)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/delegations)" - api_method: database_api.find_vesting_delegations since: HF17 purpose: | @@ -449,13 +460,14 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegations", "params": {"account":"hiveio"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegations", "params": {"account":"alice"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegations", "params": {"account":"hiveio"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_vesting_delegations", "params": {"account":"alice"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-vesting-delegations)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_vesting_delegations)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/delegations)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_vesting_delegations)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-vesting-delegations)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_vesting_delegations)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/delegations)" - api_method: database_api.find_votes purpose: | Returns all votes for the given post. Required (non-empty) parameters: `author:string`; `permlink:string` @@ -482,15 +494,16 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_votes", "params": {"author":"hiveio", "permlink":"announcing-the-launch-of-hive-blockchain"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.find_votes", "params": {"author":"alice", "permlink":"a-post-by-alice"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_votes", "params": {"author":"hiveio", "permlink":"announcing-the-launch-of-hive-blockchain"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_votes", "params": {"author":"alice", "permlink":"a-post-by-alice"}, "id":1}' expected_curl_responses: - - - - Could not find comment alice/a-post-by-alice + - + - Could not find comment alice/a-post-by-alice client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-account-votes)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_account_votes)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_votes)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-account-votes)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_account_votes)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_withdraw_vesting_routes purpose: Returns the list of vesting withdraw routes for an account. parameter_json: '{"account":"","order":"by_name"}' @@ -507,11 +520,12 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_withdraw_vesting_routes", "params": {"account":"temp", "order":"by_destination"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_withdraw_vesting_routes", "params": {"account":"temp", "order":"by_destination"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-withdraw-routes)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_withdraw_routes)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_withdraw_vesting_routes)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-withdraw-routes)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_withdraw_routes)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.find_witnesses purpose: Search for witnesses. parameter_json: '{"owners":[]}' @@ -565,12 +579,13 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.find_witnesses", "params": {"owners":["initminer"]}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.find_witnesses", "params": {"owners":["initminer"]}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-witnesses)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-active-witnesses)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=find_witnesses)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-witnesses)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-active-witnesses)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" - api_method: database_api.get_active_witnesses purpose: Returns the list of active witnesses. parameter_json: "{}" @@ -601,12 +616,13 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_active_witnesses", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_active_witnesses", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-active-witnesses)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-active-witnesses)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_active_witnesses)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-active-witnesses)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-active-witnesses)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" - api_method: database_api.get_config purpose: | Returns information about compile-time constants. Some properties may @@ -881,11 +897,12 @@ "HIVE_DB_FORMAT_VERSION": "1" } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_config", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_config", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-config)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-config)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_config)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-config)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-config)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_current_price_feed purpose: Returns the current price feed. parameter_json: "{}" @@ -903,11 +920,12 @@ } } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_current_price_feed", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_current_price_feed", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-current-median-history-price)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_median_price)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_current_price_feed)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-current-median-history-price)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_median_price)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_dynamic_global_properties purpose: | Returns the current dynamic global properties. See: [Understanding @@ -1010,12 +1028,13 @@ } } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_dynamic_global_properties", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_dynamic_global_properties", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-dynamic-global-properties)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_dynamic_global_properties)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/dynamicglobalproperties)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_dynamic_global_properties)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-dynamic-global-properties)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_dynamic_global_properties)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/dynamicglobalproperties)" - api_method: database_api.get_feed_history purpose: Returns the history of price feed values. parameter_json: "{}" @@ -1037,11 +1056,12 @@ "price_history": [] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_feed_history", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_feed_history", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-current-median-history-price)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_median_price)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_feed_history)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-current-median-history-price)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_median_price)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_hardfork_properties purpose: | Returns the current properties about the blockchain's hardforks. @@ -1086,8 +1106,9 @@ "next_hardfork_time": "2022-10-11T12:00:00" } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_hardfork_properties", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_hardfork_properties", "id":1}' client_docs: + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_hardfork_properties)" - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-hardfork-version)" - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchaininstance.html#beem.blockchaininstance.BlockChainInstance.get_hardfork_properties)" - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" @@ -1097,13 +1118,14 @@ parameter_json: '{"limit":0,"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}}' expected_response_json: '{"asks":[],"bids":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_order_book", "params":{"limit":10,"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}}, - "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.get_order_book", "params":{"limit":50,"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}}, - "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_order_book", "params":{"limit":10,"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}}, + "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_order_book", "params":{"limit":50,"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}}, + "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-order-book)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_order_book)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-order-book)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_potential_signatures purpose: | This method will return the set of all public keys that could possibly @@ -1113,12 +1135,12 @@ parameter_json: '{"trx":{"ref_block_num":0,"ref_block_prefix":0,"expiration":"1970-01-01T00:00:00","operations":[],"extensions":[],"signatures":[]}}' expected_response_json: '{"keys":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_potential_signatures", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]}}, - "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_potential_signatures", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]}}, + "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-potential-signatures)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-potential-signatures)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-potential-signatures)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-potential-signatures)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_required_signatures purpose: This API will take a partially signed transaction and a set of public keys that the owner has the ability to sign for and return the minimal subset @@ -1126,12 +1148,12 @@ parameter_json: '{"trx":{"ref_block_num":0,"ref_block_prefix":0,"expiration":"1970-01-01T00:00:00","operations":[],"extensions":[],"signatures":[]},"available_keys":[]}' expected_response_json: '{"keys":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_required_signatures", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]},"available_keys":[]}, - "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_required_signatures", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]},"available_keys":[]}, + "id ":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-required-signatures)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-required-signatures)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-required-signatures)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-required-signatures)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_reward_funds since: HF17 purpose: Returns information about the current reward funds. @@ -1158,22 +1180,23 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_reward_funds", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_reward_funds", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-reward-fund)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-reward-fund)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_reward_funds)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-reward-fund)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-reward-fund)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_transaction_hex purpose: Returns a hexdump of the serialized binary form of a transaction. parameter_json: '{"trx":{"ref_block_num":0,"ref_block_prefix":0,"expiration":"1970-01-01T00:00:00","operations":[],"extensions":[],"signatures":[]}}' expected_response_json: '{"hex":"00000000000000000000000000"}' curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_transaction_hex", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]}}, - "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_transaction_hex", "params":{"trx":{"ref_block_num":1097,"ref_block_prefix":2181793527,"expiration":"2016-03-24T18:00:21","operations":[{"type":"pow_operation","value":{"worker_account":"cloop3","block_id":"00000449f7860b82b4fbe2f317c670e9f01d6d9a","nonce":3899,"work":{"worker":"STM7P5TDnA87Pj9T4mf6YHrhzjC1KbPZpNxLWCcVcHxNYXakpoT4F","input":"ae8e7c677119d22385f8c48026fee7aad7bba693bf788d7f27047f40b47738c0","signature":"1f38fe9a3f9989f84bd94aa5bbc88beaf09b67f825aa4450cf5105d111149ba6db560b582c7dbb026c7fc9c2eb5051815a72b17f6896ed59d3851d9a0f9883ca7a","work":"000e7b209d58f2e64b36e9bf12b999c6c7af168cc3fc41eb7f8a4bf796c174c3"},"props":{"account_creation_fee":{"amount":"100000","precision":3,"nai":"@@000000021"},"maximum_block_size":131072,"hbd_interest_rate":1000}}}],"extensions":[],"signatures":[]}}, + "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-transaction-hex)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-transaction-hex)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-transaction-hex)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-transaction-hex)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_version since: HF20 purpose: Returns the compile time versions of blockchain, hived, FC. Also returns @@ -1188,11 +1211,12 @@ "chain_id": "beeab0de00000000000000000000000000000000000000000000000000000000" } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_version", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_version", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-version)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-version)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_version)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-version)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-version)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.get_witness_schedule purpose: Returns the current witness schedule. parameter_json: "{}" @@ -1270,12 +1294,13 @@ "min_witness_account_subsidy_decay": 0 } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.get_witness_schedule", "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.get_witness_schedule", "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-witness-schedule)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-witness-schedule)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=get_witness_schedule)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-witness-schedule)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-witness-schedule)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivesql](https://docs.hivesql.io/technical-informations/state-tables/witnesses)" - api_method: database_api.list_account_recovery_requests since: HF11 purpose: | @@ -1293,12 +1318,13 @@ parameter_json: '{"start":null,"limit":0,"order":"by_name"}' expected_response_json: '{"requests":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_account_recovery_requests", "params": {"start":"", "limit":10, "order":"by_account"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_account_recovery_requests", "params": {"start":["1960-01-01T00:00:00"], "limit":10, "order":"by_expiration"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_account_recovery_requests", "params": {"start":"", "limit":10, "order":"by_account"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_account_recovery_requests", "params": {"start":["1960-01-01T00:00:00"], "limit":10, "order":"by_expiration"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" - - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-recovery-request)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_account_recovery_requests)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" + - "[beem](https://beem.readthedocs.io/en/latest/apidefinitions.html#get-recovery-request)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_accounts purpose: | List accounts ordered by specified key. Parameters: `start:object`, `limit:int`, `order:string`, `delayed_votes_active:boolean` @@ -1481,13 +1507,14 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":"", "limit":10, "order":"by_name"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":["", ""], "limit":10, "order":"by_proxy"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":["1960-01-01T00:00:00", ""], "limit":10, "order":"by_next_vesting_withdrawal","delayed_votes_active":false}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":"", "limit":10, "order":"by_name"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":["", ""], "limit":10, "order":"by_proxy"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_accounts", "params": {"start":["1960-01-01T00:00:00", ""], "limit":10, "order":"by_next_vesting_withdrawal","delayed_votes_active":false}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-accounts)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.get_all_accounts)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_accounts)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-accounts)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.get_all_accounts)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_change_recovery_account_requests since: HF11 purpose: | @@ -1520,12 +1547,12 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_change_recovery_account_requests", "params": {"start":"alice", "limit":10, "order":"by_account"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_change_recovery_account_requests", "params": {"start":["1960-01-01T00:00:00",""], "limit":10, "order":"by_effective_date"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_change_recovery_account_requests", "params": {"start":"alice", "limit":10, "order":"by_account"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_change_recovery_account_requests", "params": {"start":["1960-01-01T00:00:00",""], "limit":10, "order":"by_effective_date"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.list_change_recovery_account_requests)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-recovery-request)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.blockchain.html#beem.blockchain.Blockchain.list_change_recovery_account_requests)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_comments purpose: | Returns all comments, starting with the specified options. Parameters: `start:array`; `limit:int`; `order:string` @@ -1612,16 +1639,17 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["1970-01-01T00:00:00","",""], "limit":10, "order":"by_cashout_time"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["",""], "limit":10, "order":"by_permlink"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","announcing-the-launch-of-hive-blockchain","",""], "limit":10, "order":"by_root"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","announcing-the-launch-of-hive-blockchain","",""], "limit":10, "order":"by_parent"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","1970-01-01T00:00:00","",""], "limit":10, "order":"by_last_update"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","1970-01-01T00:00:00","",""], "limit":10, "order":"by_author_last_update"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["1970-01-01T00:00:00","",""], "limit":10, "order":"by_cashout_time"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["",""], "limit":10, "order":"by_permlink"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","announcing-the-launch-of-hive-blockchain","",""], "limit":10, "order":"by_root"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","announcing-the-launch-of-hive-blockchain","",""], "limit":10, "order":"by_parent"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","1970-01-01T00:00:00","",""], "limit":10, "order":"by_last_update"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_comments", "params": {"start":["hiveio","1970-01-01T00:00:00","",""], "limit":10, "order":"by_author_last_update"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-discussions-by-created)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.comment.html#module-beem.comment)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_comments)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-discussions-by-created)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.comment.html#module-beem.comment)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_decline_voting_rights_requests since: HF14 purpose: | @@ -1644,10 +1672,10 @@ parameter_json: '{"start":null,"limit":0,"order":"by_name"}' expected_response_json: '{"requests":[]}' # TODO - recheck in HF23 curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_decline_voting_rights_requests", "params": {"start":"", "limit":10, "order":"by_account"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_decline_voting_rights_requests", "params": {"start":["1970-01-01T00:00:00","",""], "limit":10, "order":"by_effective_date"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_decline_voting_rights_requests", "params": {"start":"", "limit":10, "order":"by_account"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_decline_voting_rights_requests", "params": {"start":["1970-01-01T00:00:00","",""], "limit":10, "order":"by_effective_date"}, "id":1}' client_docs: - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_escrows since: HF14 purpose: | @@ -1701,12 +1729,13 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_escrows", "params": {"start":["",0], "limit":10, "order":"by_from_id"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_escrows", "params": {"start":[true, "1970-01-01T00:00:00", 0], "limit":10, "order":"by_ratification_deadline"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_escrows", "params": {"start":["",0], "limit":10, "order":"by_from_id"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_escrows", "params": {"start":[true, "1970-01-01T00:00:00", 0], "limit":10, "order":"by_ratification_deadline"}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-escrow)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_escrow)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_escrows)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-escrow)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_escrow)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_limit_orders purpose: | Returns a list of limit orders. Parameters: `start:array`; `limit:int`; `order:string` @@ -1752,10 +1781,11 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_limit_orders", "params": {"start":[{"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}},0], "limit":10, "order":"by_price"}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_limit_orders", "params": {"start":["alice",0], "limit":10, "order":"by_account"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_limit_orders", "params": {"start":[{"base":{"amount":"1000","precision":3,"nai":"@@000000021"},"quote":{"amount":"1","precision":3,"nai":"@@000000013"}},0], "limit":10, "order":"by_price"}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_limit_orders", "params": {"start":["alice",0], "limit":10, "order":"by_account"}, "id":1}' client_docs: - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_limit_orders)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_owner_histories purpose: | Returns a list of owner authority histories. Parameters: `start:array`, `limit:int` @@ -1788,12 +1818,13 @@ ] } curl_examples: - - '{"jsonrpc":"2.0", "method":"database_api.list_owner_histories", "params": {"start":["hiveio","1970-01-01T00:00:00"], "limit":10}, "id":1}' - - '{"jsonrpc":"2.0", "method":"database_api.list_owner_histories", "params": {"start":["alice","1970-01-01T00:00:00"], "limit":10}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_owner_histories", "params": {"start":["hiveio","1970-01-01T00:00:00"], "limit":10}, "id":1}' + - '{"jsonrpc":"2.0", "method":"database_api.list_owner_histories", "params": {"start":["alice","1970-01-01T00:00:00"], "limit":10}, "id":1}' client_docs: - - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-owner-history)" - - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_owner_history)" - - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" + - "[hivexplorer](https://hivexplorer.com/api-docs?q=list_owner_histories)" + - "[hive-js](https://gitlab.syncad.com/hive/hive-js/tree/master/doc#get-owner-history)" + - "[beem](https://beem.readthedocs.io/en/latest/beem.account.html#beem.account.Account.get_owner_history)" + - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.list_savings_withdrawals since: HF14 purpose: | @@ -2196,7 +2227,7 @@ - "[hive-ruby](https://www.rubydoc.info/gems/hive-ruby/Hive/Api)" - api_method: database_api.verify_signatures purpose: - This method validates if transaction was signed by person listed in required_owner, required_active or required_posting parameter. `Hash` is a mix of chain_id and transaction data. + This method validates if transaction was signed by person listed in required_owner, required_active or required_posting parameter. `Hash` is a mix of chain_id and transaction data. parameter_json: '{"hash":"0000000000000000000000000000000000000000000000000000000000000000","signatures":[],"required_owner":[],"required_active":[],"required_posting":[],"required_other":[]}' expected_response_json: '{"valid":false}' curl_examples: diff --git a/_data/nav.yml b/_data/nav.yml index baf0a80f..f40101e9 100644 --- a/_data/nav.yml +++ b/_data/nav.yml @@ -21,10 +21,10 @@ toc: docs: - title: Javascript collection: tutorials-javascript - - title: Php - collection: tutorials-php - title: Python collection: tutorials-python + - title: Php + collection: tutorials-php - title: Ruby collection: tutorials-ruby - title: Recipes diff --git a/_layouts/default.html b/_layouts/default.html index 2065c8a6..b11a0314 100644 --- a/_layouts/default.html +++ b/_layouts/default.html @@ -7,7 +7,7 @@ <meta name="apple-mobile-web-app-title" content="Hive Devportal" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> - + <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script> <link rel="shortcut icon" type="image/png" href="{{ '/favicon.png' | relative_url }}" /> <link rel="apple-touch-icon" type="image/png" href="{{ '/favicon.png' | relative_url }}" /> @@ -71,6 +71,30 @@ document.getElementById("open-nav").addEventListener("click", function () { document.body.classList.toggle("nav-open"); }); + // assets/js/post.js + let codeBlocks = document.querySelectorAll('pre.highlight'); + + codeBlocks.forEach(function (codeBlock) { + let copyButton = document.createElement('button'); + copyButton.className = 'copy'; + copyButton.type = 'button'; + copyButton.ariaLabel = 'Copy code to clipboard'; + copyButton.innerText = 'Copy'; + + codeBlock.append(copyButton); + + copyButton.addEventListener('click', function () { + let code = codeBlock.querySelector('code').innerText.trim(); + window.navigator.clipboard.writeText(code); + + copyButton.innerText = 'Copied'; + let fourSeconds = 4000; + + setTimeout(function () { + copyButton.innerText = 'Copy'; + }, fourSeconds); + }); + }); </script> </body> </html> diff --git a/_sass/_main.scss b/_sass/_main.scss index 4d0b7591..b3d8bff2 100644 --- a/_sass/_main.scss +++ b/_sass/_main.scss @@ -750,3 +750,33 @@ a[href*='hivexplorer'] { background-position: right top; padding-left: .90em; } + +pre.highlight { + position: relative; +} +pre.highlight > button { + opacity: 0; + color: #f0f0f8; + background: #27313E; + border-radius: .75rem; + border: none; + font-size: 16px; + cursor: pointer; + position: absolute; + right: 1.2rem; + top: 1.2rem; +} + +pre.highlight:hover > button { + opacity: 1; +} + +pre.highlight > button:active, +pre.highlight > button:focus { + background: rgba(0, 0, 0, 0.7); + opacity: 1; +} + +img { + max-width: 100%; +} diff --git a/_tutorials-javascript/account_reputation.md b/_tutorials-javascript/account_reputation.md index 01ff9f63..ee8b8da9 100644 --- a/_tutorials-javascript/account_reputation.md +++ b/_tutorials-javascript/account_reputation.md @@ -101,13 +101,69 @@ for (var i = 0; i < _accounts.length; i++) { document.getElementById('accList').innerHTML = _accounts.join('<br/>'); ``` ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); -#### Try it +/** + This is a rough approximation of log10 that works with huge digit-strings. + Warning: Math.log10(0) === NaN + The 0.00000001 offset fixes cases of Math.log(1000)/Math.LN10 = 2.99999999~ +*/ +function log10(str) { + const leadingDigits = parseInt(str.substring(0, 4)); + const log = Math.log(leadingDigits) / Math.LN10 + 0.00000001; + const n = str.length - 1; + return n + (log - parseInt(log)); +} -Click the play button below: +export const repLog10 = rep2 => { + if (rep2 == null) return rep2; + let rep = String(rep2); + const neg = rep.charAt(0) === '-'; + rep = neg ? rep.substring(1) : rep; -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js20accountreputation?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> + let out = log10(rep); + if (isNaN(out)) out = 0; + out = Math.max(out - 9, 0); // @ -9, $0.50 earned is approx magnitude 1 + out = (neg ? -1 : 1) * out; + out = out * 9 + 25; // 9 points per magnitude. center at 25 + // base-line 0 to darken and < 0 to auto hide (grep rephide) + out = parseInt(out); + return out; +}; + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _accounts = await client.database.call('lookup_accounts', [ + accSearch, + max, + ]); + console.log(`_accounts:`, _accounts); + + const acc = await client.database.call('get_accounts', [_accounts]); + + //disply list of account names and reputation with line breaks + for (var i = 0; i < _accounts.length; i++) { + _accounts[i] = `${_accounts[i]} - ${repLog10(acc[i].reputation)}`; + } + document.getElementById('accList').innerHTML = _accounts.join('<br/>'); +}; + +``` + +--- ### To run this tutorial diff --git a/_tutorials-javascript/blog_feed.md b/_tutorials-javascript/blog_feed.md index acddfe9f..df8c4eb0 100644 --- a/_tutorials-javascript/blog_feed.md +++ b/_tutorials-javascript/blog_feed.md @@ -162,13 +162,45 @@ The result returned form the service is a `JSON` object with the following prope From this result we have access to everything associated to the post including additional metadata which is a `JSON` string that must be decoded to use. This `JSON` object has additional information and properties for the post including a reference to the image uploaded. And we are displaying this data in meaningful user interface. _Note: it is truncated to one element, but you would get five posts in array_ ---- +Final code: + +```javascript +const { Client } = require("@hiveio/dhive"); + +const client = new Client('https://api.hive.blog'); -#### Try it +function fetchBlog() { + const query = { + tag: 'hiveio', + limit: 5, + }; + client.database + .getDiscussions('blog', query) + .then(result => { + var posts = []; + result.forEach(post => { + const json = JSON.parse(post.json_metadata); + const image = json.image ? json.image[0] : ''; + const title = post.title; + const author = post.author; + const created = new Date(post.created).toDateString(); + posts.push( + `<div class="list-group-item"><h4 class="list-group-item-heading">${title}</h4><p>by ${author}</p><center><img src="${image}" class="img-responsive center-block" style="max-width: 450px"/></center><p class="list-group-item-text text-right text-nowrap">${created}</p></div>` + ); + }); + + document.getElementById('postList').innerHTML = posts.join(''); + }) + .catch(err => { + alert('Error occured' + err); + }); +} -Click the play button below: +fetchBlog(); -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js01blogfeed?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` + +--- ### To Run the tutorial diff --git a/_tutorials-javascript/claim_rewards.md b/_tutorials-javascript/claim_rewards.md index 958628f1..d610ae6f 100644 --- a/_tutorials-javascript/claim_rewards.md +++ b/_tutorials-javascript/claim_rewards.md @@ -104,6 +104,71 @@ window.submitTx = async () => { That's it! +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _accounts = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_accounts:`, _accounts); + const name = _accounts[0].name; + const reward_hive = _accounts[0].reward_hive_balance.split(' ')[0]; + const reward_hbd = _accounts[0].reward_hbd_balance.split(' ')[0]; + const reward_hp = _accounts[0].reward_vesting_hive.split(' ')[0]; + const reward_vests = _accounts[0].reward_vesting_balance.split(' ')[0]; + const unclaimed_balance = `Unclaimed balance for ${name}: ${reward_hive} HIVE, ${reward_hbd} HBD, ${reward_hp} HP = ${reward_vests} VESTS<br/>`; + document.getElementById('accList').innerHTML = unclaimed_balance; + document.getElementById('hive').value = reward_hive; + document.getElementById('hbd').value = reward_hbd; + document.getElementById('hp').value = reward_vests; + + document.getElementById('hc').style.display = 'block'; + const link = `https://hivesigner.com/sign/claim-reward-balance?account=${name}&reward_hive=${reward_hive}&reward_hbd=${reward_hbd}&reward_vests=${reward_vests}`; + document.getElementById('hc').innerHTML = `<br/><a href=${link} target="_blank">Hive Signer signing</a>`; +}; + +window.submitTx = async () => { + const privateKey = dhive.PrivateKey.fromString( + document.getElementById('wif').value + ); + const op = [ + 'claim_reward_balance', + { + account: document.getElementById('username').value, + reward_hive: document.getElementById('hive').value + ' HIVE', + reward_hbd: document.getElementById('hbd').value + ' HBD', + reward_vests: document.getElementById('hp').value + ' VESTS', + }, + ]; + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/client_signing.md b/_tutorials-javascript/client_signing.md index 08877c1a..7b310757 100644 --- a/_tutorials-javascript/client_signing.md +++ b/_tutorials-javascript/client_signing.md @@ -120,6 +120,198 @@ const res = await client.broadcast.send(stx) That's it! +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; //import the api client library +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; +const client = new Client(NetConfig.url, opts); + +let elMessage; +let privateKey = ''; +let accountAddress = ''; +let opType = ''; +let op = {}; +let stx; +let expireTime = 60 * 1000; //1 min +let head_block_number = 0; +let head_block_id = ''; + +async function main() { + //get current state of network + const props = await client.database.getDynamicGlobalProperties(); + //extract last/head block number + head_block_number = props.head_block_number; + //extract block id + head_block_id = props.head_block_id; + + elMessage.innerText = 'Ready'; +} + +window.onload = () => { + //prep for user interactions + elMessage = document.getElementById('ui-message'); + //populate our account chooser + document.getElementById('account').innerHTML += NetConfig.accounts + .map((account, i) => `<option value="${i}">${account.address}</option>`) + .join(''); + + elMessage.innerText = + 'Give it a moment. We do not yet have the head block....'; + main().catch(error => { + console.error('ERROR', error); + elMessage.innerText = + 'Unable to get head block. Tutorial may not function properly'; + }); +}; + +//account change selection function +window.accountChange = async () => { + const account = + NetConfig.accounts[document.getElementById('account').value]; + //get private key for selected account + privateKey = PrivateKey.fromString(account.privActive); + + //get selected account address/name + accountAddress = account.address; +}; + +//operation type change selection function +window.opChange = async () => { + //get operation type + opType = document.getElementById('optype').value; +}; + +//generate transaction function +window.generateTx = () => { + //check operation type + if (opType == 'vote') { + //vote operation/transaction + op = { + ref_block_num: head_block_number, //reference head block number required by tapos (transaction as proof of stake) + ref_block_prefix: Buffer.from(head_block_id, 'hex').readUInt32LE(4), //reference buffer of block id as prefix + expiration: new Date(Date.now() + expireTime) + .toISOString() + .slice(0, -5), //set expiration time for transaction (+1 min) + operations: [ + [ + 'vote', + { + voter: accountAddress, + author: 'test', + permlink: 'test', + weight: 10000, + }, + ], + ], //example of operation object for vote + extensions: [], //extensions for this transaction + }; + //set operation output + document.getElementById('OpInput').innerHTML = JSON.stringify( + op, + undefined, + 2 + ); + } + if (opType == 'follow') { + //follow operation + op = { + ref_block_num: head_block_number, + ref_block_prefix: Buffer.from(head_block_id, 'hex').readUInt32LE(4), + expiration: new Date(Date.now() + expireTime) + .toISOString() + .slice(0, -5), + operations: [ + [ + 'custom_json', + { + required_auths: [], + required_posting_auths: [accountAddress], + id: 'follow', + json: + '["follow",{"follower":"' + + accountAddress + + '","following":"test","what":["blog"]}]', + }, + ], + ], //example of custom_json for follow operation + extensions: [], + }; + document.getElementById('OpInput').innerHTML = JSON.stringify( + op, + undefined, + 2 + ); + } + if (opType == 'reblog') { + //reblog operation + op = { + ref_block_num: head_block_number, + ref_block_prefix: Buffer.from(head_block_id, 'hex').readUInt32LE(4), + expiration: new Date(Date.now() + expireTime) + .toISOString() + .slice(0, -5), + operations: [ + [ + 'custom_json', + { + required_auths: [], + required_posting_auths: [accountAddress], + id: 'follow', + json: + '["reblog",{"account":"' + + accountAddress + + '","author":"test","permlink":"test"}]', + }, + ], + ], //example of custom_json for reblog operation + extensions: [], + }; + document.getElementById('OpInput').innerHTML = JSON.stringify( + op, + undefined, + 2 + ); + } +}; + +window.signTx = () => { + //sign transaction/operations with user's privatekey + stx = client.broadcast.sign(op, privateKey); + //set output + document.getElementById('TxOutput').innerHTML = JSON.stringify( + stx, + undefined, + 2 + ); + console.log(stx); +}; + +window.verifyTx = async () => { + //verify signed transaction authority + const rv = await client.database.verifyAuthority(stx); + //set checkmark or crossmark depending on outcome + let node = document.getElementById('verifyBtn'); + rv + ? node.insertAdjacentHTML('afterend', ' ✔ ') + : node.insertAdjacentHTML('afterend', ' ✗ '); +}; + +window.broadcastTx = async () => { + //broadcast/send transaction to the network + const res = await client.broadcast.send(stx); + //set output + document.getElementById('ResOutput').innerHTML = JSON.stringify( + res, + undefined, + 2 + ); +}; + +``` + ### To Run the tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/convert_hbd_to_hive.md b/_tutorials-javascript/convert_hbd_to_hive.md index cc49730b..6ec0a0b0 100644 --- a/_tutorials-javascript/convert_hbd_to_hive.md +++ b/_tutorials-javascript/convert_hbd_to_hive.md @@ -142,6 +142,89 @@ client.broadcast.sendOperations([op], privateKey).then( The results of the operation is displayed on the UI along with a block number in the console to confirm a successful operation. +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a hive node, tesetnet in this case +const client = new Client(NetConfig.url, opts); + +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_account:`, _account); + + const availHBD = _account[0].hbd_balance + const availHIVE = _account[0].balance + + const balance = `Available balance: ${availHBD} and ${availHIVE} <br/>`; + document.getElementById('accBalance').innerHTML = balance; + + //create random number for requestid paramter + var x = Math.floor(Math.random() * 10000000); + document.getElementById("requestID").value = x +} + +//submit convert function executes when you click "Convert" button +window.submitConvert = async () => { + //get all values from the UI + //get account name + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get convert amount + const quantity = document.getElementById('quantity').value; + //create correct format + const convert = quantity.concat(' HBD'); + //assign integer value of ID + const requestid = parseInt(document.getElementById('requestID').value); + + //create convert operation + const op = [ + 'convert', + { owner: username, amount: convert, requestid: requestid }, + ]; + + //broadcast the conversion + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('convertResultContainer').style.display = + 'flex'; + document.getElementById('convertResult').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('convertResult').innerHTML = 'Success'; + }, + function(error) { + console.error(error); + document.getElementById('convertResultContainer').style.display = + 'flex'; + document.getElementById('convertResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('convertResult').innerHTML = + error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('privateKey').value = account.privActive; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/convert_hive_to_hbd.md b/_tutorials-javascript/convert_hive_to_hbd.md index 54de17bd..7b7f8eae 100644 --- a/_tutorials-javascript/convert_hive_to_hbd.md +++ b/_tutorials-javascript/convert_hive_to_hbd.md @@ -141,6 +141,89 @@ client.broadcast.sendOperations([op], privateKey).then( The results of the operation is displayed on the UI along with a block number in the console to confirm a successful operation. +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { PublicTestnetHive as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a hive node, tesetnet in this case +const client = new Client(NetConfig.url, opts); + +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_account:`, _account); + + const availHIVE = _account[0].balance + const availHBD = _account[0].hbd_balance + + const balance = `Available balance: ${availHIVE} and ${availHBD} <br/>`; + document.getElementById('accBalance').innerHTML = balance; + + //create random number for requestid paramter + var x = Math.floor(Math.random() * 10000000); + document.getElementById("requestID").value = x +} + +//submit convert function executes when you click "Convert" button +window.submitConvert = async () => { + //get all values from the UI + //get account name + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get convert amount + const quantity = document.getElementById('quantity').value; + //create correct format + const convert = quantity.concat(' TESTS'); // HIVE = mainnet symbol; TESTS = testnet symbol + //assign integer value of ID + const requestid = parseInt(document.getElementById('requestID').value); + + //create convert operation + const op = [ + 'collateralized_convert', + { owner: username, amount: convert, requestid: requestid }, + ]; + + //broadcast the conversion + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('convertResultContainer').style.display = + 'flex'; + document.getElementById('convertResult').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('convertResult').innerHTML = 'Success'; + }, + function(error) { + console.error(error); + document.getElementById('convertResultContainer').style.display = + 'flex'; + document.getElementById('convertResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('convertResult').innerHTML = + error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('privateKey').value = account.privActive; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/convert_sbd_to_steem.md b/_tutorials-javascript/convert_sbd_to_steem.md deleted file mode 100644 index 73abd9f9..00000000 --- a/_tutorials-javascript/convert_sbd_to_steem.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: 'JS: Convert HBD To HIVE' -position: 32 -description: "_How to convert HBD to HIVE for a specified account._" -exclude_in_index: true -excluded_in_search: true -layout: full -canonical_url: /tutorials-javascript/convert_hbd_to_hive.html ---- -{% include redirect-to-canonical-url.html %} diff --git a/_tutorials-javascript/create_account.md b/_tutorials-javascript/create_account.md index 8ab351a4..71b908f8 100644 --- a/_tutorials-javascript/create_account.md +++ b/_tutorials-javascript/create_account.md @@ -198,6 +198,208 @@ client.broadcast.sendOperations(ops, privateKey).then( That's it! +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +// const dhive = require('@hiveio/dhive'); +// //define network parameters +// let opts = {}; +// opts.addressPrefix = 'TST'; +// opts.chainId = +// '18dcf0a285365fc58b71f18b3d3fec954aa0c141c44e4e5cb4cf777b9eab274e'; +// //connect to a hive node, testnet in this case +// const client = new dhive.Client('http://127.0.0.1:8090', opts); + +//submit Account search function from html input +const max = 5; +window.searchAcc = async () => { + const accSearch = document.getElementById('username').value; + let avail = 'Account is NOT available to register'; + if (accSearch.length > 2) { + const _account = await client.database.call('get_accounts', [ + [accSearch], + ]); + console.log(`_account:`, _account, accSearch.length); + + if (_account.length == 0) { + avail = 'Account is available to register'; + } + } + document.getElementById('accInfo').innerHTML = avail; +}; + +//create with HIVE function +window.submitTx = async () => { + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + + const ownerKey = dhive.PrivateKey.fromLogin(username, password, 'owner'); + const activeKey = dhive.PrivateKey.fromLogin(username, password, 'active'); + const postingKey = dhive.PrivateKey.fromLogin( + username, + password, + 'posting' + ); + const memoKey = dhive.PrivateKey.fromLogin( + username, + password, + 'memo' + ).createPublic(opts.addressPrefix); + + const ownerAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[ownerKey.createPublic(opts.addressPrefix), 1]], + }; + const activeAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[activeKey.createPublic(opts.addressPrefix), 1]], + }; + const postingAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[postingKey.createPublic(opts.addressPrefix), 1]], + }; + + const privateKey = dhive.PrivateKey.fromString( + document.getElementById('wif').value + ); + + const op = [ + 'account_create', + { + fee: document.getElementById('hive').value, + creator: document.getElementById('account').value, + new_account_name: username, + owner: ownerAuth, + active: activeAuth, + posting: postingAuth, + memo_key: memoKey, + json_metadata: '', + }, + ]; + + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +//create with RC function +window.submitDisc = async () => { + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + + //create keys + const ownerKey = dhive.PrivateKey.fromLogin(username, password, 'owner'); + const activeKey = dhive.PrivateKey.fromLogin(username, password, 'active'); + const postingKey = dhive.PrivateKey.fromLogin( + username, + password, + 'posting' + ); + const memoKey = dhive.PrivateKey.fromLogin( + username, + password, + 'memo' + ).createPublic(opts.addressPrefix); + + const ownerAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[ownerKey.createPublic(opts.addressPrefix), 1]], + }; + const activeAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[activeKey.createPublic(opts.addressPrefix), 1]], + }; + const postingAuth = { + weight_threshold: 1, + account_auths: [], + key_auths: [[postingKey.createPublic(opts.addressPrefix), 1]], + }; + + //private active key of creator account + const privateKey = dhive.PrivateKey.fromString( + document.getElementById('wif').value + ); + + let ops = []; + + //claim discounted account operation + const creator = document.getElementById('account').value; + const _account = await client.database.call('get_accounts', [[creator]]); + console.log( + 'current pending claimed accounts: ' + + _account[0].pending_claimed_accounts + ); + if (_account[0].pending_claimed_accounts == 0) { + const claim_op = [ + 'claim_account', + { + creator: creator, + fee: '0.000 HIVE', + extensions: [], + }, + ]; + console.log('You have claimed a token'); + ops.push(claim_op); + } + + //create operation to transmit + const create_op = [ + 'create_claimed_account', + { + creator: document.getElementById('account').value, + new_account_name: username, + owner: ownerAuth, + active: activeAuth, + posting: postingAuth, + memo_key: memoKey, + json_metadata: '', + extensions: [], + }, + ]; + ops.push(create_op); + + //broadcast operation to blockchain + client.broadcast.sendOperations(ops, privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/delegate_power.md b/_tutorials-javascript/delegate_power.md index 5ac39666..cf34d1f8 100644 --- a/_tutorials-javascript/delegate_power.md +++ b/_tutorials-javascript/delegate_power.md @@ -106,6 +106,81 @@ window.submitTx = async () => { That's it! +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Mainnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_account:`, _account); + + const name = _account[0].name; + const avail = + parseFloat(_account[0].vesting_shares) - + (parseFloat(_account[0].to_withdraw) - + parseFloat(_account[0].withdrawn)) / + 1e6 - + parseFloat(_account[0].delegated_vesting_shares); + + const props = await client.database.getDynamicGlobalProperties(); + const vestHive = parseFloat( + parseFloat(props.total_vesting_fund_hive) * + (parseFloat(avail) / parseFloat(props.total_vesting_shares)), + 6 + ); + + const balance = `Available Vests for ${name}: ${avail} VESTS ~ ${vestHive} HIVE POWER<br/><br/>`; + document.getElementById('accBalance').innerHTML = balance; + document.getElementById('hive').value = + Number(avail).toFixed(6) + ' VESTS'; +}; +window.openSC = async () => { + const link = `https://hivesigner.com/sign/delegate-vesting-shares?delegator=${ + document.getElementById('username').value + }&vesting_shares=${document.getElementById('hive').value}&delegatee=${ + document.getElementById('account').value + }`; + window.open(link); +}; +window.submitTx = async () => { + const privateKey = PrivateKey.fromString( + document.getElementById('wif').value + ); + const op = [ + 'delegate_vesting_shares', + { + delegator: document.getElementById('username').value, + delegatee: document.getElementById('account').value, + vesting_shares: document.getElementById('hive').value, + }, + ]; + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/edit_content_patching.md b/_tutorials-javascript/edit_content_patching.md index 09933e27..e4fe5984 100644 --- a/_tutorials-javascript/edit_content_patching.md +++ b/_tutorials-javascript/edit_content_patching.md @@ -177,6 +177,131 @@ The next step is to pass all of these parameters to the `client.broadcast.commen After the post has been broadcasted to the network, we can simply set all the fields to empty strings and show the post link to check it from a condenser instance running on the selected testnet. That's it! +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +const client = new Client(NetConfig.url, opts); + +const diff_match_patch = require('diff-match-patch'); +const dmp = new diff_match_patch(); +let o_body = ''; +let o_permlink = ''; + +//fetch list of comments for certain account +async function getLatestPost() { + const query = { + tag: document.getElementById('username').value, + limit: '1', + }; + client.database + .call('get_discussions_by_blog', [query]) + .then(result => { + document.getElementById('title').value = result[0].title; + document.getElementById('body').value = result[0].body; + document.getElementById('tags').value = JSON.parse( + result[0].json_metadata + ).tags.join(' '); + o_body = result[0].body; + o_permlink = result[0].permlink; + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} + +window.getLatestPost = getLatestPost; +//catch error messages + +function createPatch(text, out) { + if (!text && text === '') return undefined; + const patch_make = dmp.patch_make(text, out); + const patch = dmp.patch_toText(patch_make); + return patch; +} + +//submit post function +window.submitPost = async () => { + //get private key + const privateKey = PrivateKey.fromString( + document.getElementById('postingKey').value + ); + //get account name + const account = document.getElementById('username').value; + //get title + const title = document.getElementById('title').value; + //get body + const edited_body = document.getElementById('body').value; + + let body = ''; + + //computes a list of patches to turn o_body to edited_body + const patch = createPatch(o_body, edited_body); + + //check if patch size is smaller than edited content itself + if (patch && patch.length < new Buffer(edited_body, 'utf-8').length) { + body = patch; + } else { + body = edited_body; + } + + //get tags and convert to array list + const tags = document.getElementById('tags').value; + const taglist = tags.split(' '); + //make simple json metadata including only tags + const json_metadata = JSON.stringify({ tags: taglist }); + //generate random permanent link for post + const permlink = o_permlink; + + client.broadcast + .comment( + { + author: account, + body: body, + json_metadata: json_metadata, + parent_author: '', + parent_permlink: taglist[0], + permlink: permlink, + title: title, + }, + privateKey + ) + .then( + function(result) { + document.getElementById('title').value = ''; + document.getElementById('body').value = ''; + document.getElementById('tags').value = ''; + document.getElementById('postLink').style.display = 'block'; + document.getElementById( + 'postLink' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/><a href="http://127.0.0.1:8080/${ + taglist[0] + }/@${account}/${permlink}">Check post here</a>`; + }, + function(error) { + console.error(error); + } + ); +}; + +window.onload = () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('usernameInText').innerHTML = account.address; + document.getElementById('postingKey').value = account.privPosting; + + getLatestPost().catch(console.error); +}; + +``` + ### To Run the tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/follow_a_user.md b/_tutorials-javascript/follow_a_user.md index 4c0e26ee..41936e32 100644 --- a/_tutorials-javascript/follow_a_user.md +++ b/_tutorials-javascript/follow_a_user.md @@ -156,6 +156,104 @@ If either of the values for the user or author does not exist the proper error r curl -s --data '{"jsonrpc":"2.0", "method":"condenser_api.get_following", "params":["YOUR_ACCOUNT",null,"blog",10], "id":1}' http://127.0.0.1:8090 ``` +Final code: + +```javascript +//Step 1. +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Mainnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//Follow function +window.submitFollow = async () => { + //get private key + const privateKey = PrivateKey.fromString( + document.getElementById('postingKey').value + ); + //get account name + const follower = document.getElementById('username').value; + //get author permalink + const following = document.getElementById('author').value; + + //Step 3. checking whether author is already followed + //for full explanation of the process refer to tutorial 19_get_follower_and_following_list + + let status = await client.call('follow_api', 'get_following', [ + follower, + following, + 'blog', + 1, + ]); + + console.log({ status: status }); + + if (status.length > 0 && status[0].following == following) { + var type = ''; + } else { + var type = 'blog'; + } + + //Step 4. follow and unfollow is executed by the same operation with a change in only one of the parameters + + const json = JSON.stringify([ + 'follow', + { + follower: follower, + following: following, + what: [type], //null value for unfollow, 'blog' for follow + }, + ]); + + const data = { + id: 'follow', + json: json, + required_auths: [], + required_posting_auths: [follower], + }; + + //with variables assigned we can broadcast the operation + + client.broadcast.json(data, privateKey).then( + function(result) { + console.log('user follow result: ', result); + document.getElementById('followResultContainer').style.display = + 'flex'; + document.getElementById('followResult').className = + 'form-control-plaintext alert alert-success'; + if (type == 'blog') { + document.getElementById('followResult').innerHTML = + 'Author followed'; + } else { + document.getElementById('followResult').innerHTML = + 'Author unfollowed'; + } + }, + function(error) { + console.error(error); + document.getElementById('followResultContainer').style.display = + 'flex'; + document.getElementById('followResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('followResult').innerHTML = + error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + const accountI = NetConfig.accounts[1]; + document.getElementById('username').value = account.address; + document.getElementById('postingKey').value = account.privPosting; + document.getElementById('author').value = accountI.address; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/get_account_comments.md b/_tutorials-javascript/get_account_comments.md index 5f5cad4e..d563c1a5 100644 --- a/_tutorials-javascript/get_account_comments.md +++ b/_tutorials-javascript/get_account_comments.md @@ -157,13 +157,71 @@ We first check if `result` is not an empty object. We then iterate through each We format `created` date and time, parse `body` markdown and get `totalVotes` on that comment. Each line is then pushed and displayed separately. ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); -#### Try it +const Remarkable = require('remarkable'); +const md = new Remarkable({ html: true, linkify: true }); -Click the play button below: +//fetch list of comments for certain account +async function main() { + const author = prompt('Account?', 'hiveio'); + + client.hivemind + .call('get_account_posts', {sort: 'comments', account: author, limit: 100}) + .then(result => { + console.log(result); + if ( + !( + Object.keys(result).length === 0 && + result.constructor === Object + ) + ) { + var comments = []; + Object.keys(result).forEach(key => { + const comment = result[key]; + const parent_author = comment.parent_author; + const parent_permlink = comment.parent_permlink; + const created = new Date(comment.created).toDateString(); + const body = md.render(comment.body); + const totalVotes = comment.stats.total_votes; + comments.push( + `<div class="list-group-item list-group-item-action flex-column align-items-start">\ + <div class="d-flex w-100 justify-content-between">\ + <h6 class="mb-1">@${comment.author}</h6>\ + <small class="text-muted">${created}</small>\ + </div>\ + <p class="mb-1">${body}</p>\ + <small class="text-muted">▲ ${totalVotes}, Replied to: @${parent_author}/${parent_permlink}</small>\ + </div>` + ); + }); + document.getElementById('author').innerHTML = author; + document.getElementById('comments').style.display = 'block'; + document.getElementById('comments').innerHTML = comments.join( + '' + ); + } + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} +//catch error messages +main().catch(console.error); -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js09getaccountcomments?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` +--- ### To Run the tutorial diff --git a/_tutorials-javascript/get_account_replies.md b/_tutorials-javascript/get_account_replies.md index d11ae654..1d3209c8 100644 --- a/_tutorials-javascript/get_account_replies.md +++ b/_tutorials-javascript/get_account_replies.md @@ -19,6 +19,7 @@ Also see: * [get discussions]({{ '/search/?q=get discussions' | relative_url }}) * [tags_api.get_content_replies]({{ '/apidefinitions/#tags_api.get_content_replies' | relative_url }}) * [condenser_api.get_content_replies]({{ '/apidefinitions/#condenser_api.get_content_replies' | relative_url }}) +* [bridge.get_account_posts]({{ '/apidefinitions/#bridge.get_account_posts' | relative_url }}) ## Steps @@ -267,13 +268,62 @@ if ( We check if `content` is not an empty object and we iterate through each object via its key and extract, `author`, format `created` date and time, parse `body` markdown, get `net_votes` on that reply. Pushing each list item separately and displaying it. That's it! ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +const Remarkable = require('remarkable'); +const md = new Remarkable({html: true, linkify: true}); -#### Try it -Click the play button below: +//fetch list of replies for certain account +async function main() { + const query = '/@hiveio/recent-replies'; + client.database + .call('get_state', [query]) + .then(result => { + if (!(Object.keys(result.content).length === 0 && result.content.constructor === Object)) { + var replies = []; + Object.keys(result.content).forEach(key => { + const reply = result.content[key]; + const author = reply.author; + const created = new Date(reply.created).toDateString(); + const body = md.render(reply.body); + const netvotes = reply.net_votes; + replies.push( + `<div class="list-group-item list-group-item-action flex-column align-items-start">\ + <div class="d-flex w-100 justify-content-between">\ + <h5 class="mb-1">@${author}</h5>\ + <small class="text-muted">${created}</small>\ + </div>\ + <p class="mb-1">${body}</p>\ + <small class="text-muted">▲ ${netvotes}</small>\ + </div>` + ); + }); + document.getElementById('replies').style.display = 'block'; + document.getElementById('replies').innerHTML = replies.join(''); + } + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} +//catch error messages +main().catch(console.error); + +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js08getaccountreplies?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-javascript/get_delegations_by_user.md b/_tutorials-javascript/get_delegations_by_user.md index c652108d..31c3cdf0 100644 --- a/_tutorials-javascript/get_delegations_by_user.md +++ b/_tutorials-javascript/get_delegations_by_user.md @@ -155,13 +155,109 @@ delegationdata.forEach(newObj => { }); ``` ---- +Final code: -#### Try it +```javascript +// const dhive = require('@hiveio/dhive'); +// //define network parameters +// let opts = {}; +// opts.addressPrefix = 'TST'; +// opts.chainId = +// '18dcf0a285365fc58b71f18b3d3fec954aa0c141c44e4e5cb4cf777b9eab274e'; +// //connect to a steem node, testnet in this case +// const client = new dhive.Client('http://127.0.0.1:8090', opts); -Click the play button below: +const dhive = require('@hiveio/dhive'); +let opts = {}; +//define network parameters +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to a steem node, production in this case +const client = new dhive.Client('https://api.hive.blog'); + +//active delegations function +window.createList = async () => { + //clear list + document.getElementById('delegationList').innerHTML = ''; + + //get username + const delegator = document.getElementById('username').value; -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js29getdelegationsbyuser?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> + //account, from, limit + delegationdata = await client.database.getVestingDelegations( + delegator, + '', + 100 + ); + console.log(JSON.stringify(delegationdata)); + + if (delegationdata[0] == null) { + console.log('No delegation information'); + document.getElementById('searchResultContainer').style.display = 'flex'; + document.getElementById('searchResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('searchResult').innerHTML = + 'No delegation information'; + } else { + document.getElementById('searchResultContainer').style.display = 'flex'; + document.getElementById('searchResult').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('searchResult').innerHTML = + 'Active Delegations'; + } + + //delegator, delegatee, vesting_shares, min_delegation_time + delegationdata.forEach(newObj => { + name = newObj.delegatee; + shares = newObj.vesting_shares; + document.getElementById('delegationList').innerHTML += + delegator + ' delegated ' + shares + ' to ' + name + '<br>'; + }); +}; + +//expiring delegations function +window.displayExpire = async () => { + //clear list + document.getElementById('delegationList').innerHTML = ''; + + //get username + const delegator = document.getElementById('username').value; + + //user, from time, limit + const delegationdata = await client.database.call( + 'get_expiring_vesting_delegations', + [delegator, '2018-01-01T00:00:00', 100] + ); + console.log(delegationdata); + + if (delegationdata[0] == null) { + console.log('No delegation information'); + document.getElementById('searchResultContainer').style.display = 'flex'; + document.getElementById('searchResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('searchResult').innerHTML = + 'No delegation information'; + } else { + document.getElementById('searchResultContainer').style.display = 'flex'; + document.getElementById('searchResult').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('searchResult').innerHTML = + 'Expiring Delegations'; + } + + //vesting_shares, expiration + delegationdata.forEach(newObj => { + shares = newObj.vesting_shares; + date = expiration; + document.getElementById('delegationList').innerHTML += + shares + ' will be released at ' + date + '<br>'; + }); +}; + +``` + +--- ### To run this tutorial diff --git a/_tutorials-javascript/get_follower_and_following_list.md b/_tutorials-javascript/get_follower_and_following_list.md index 114c1fbb..f0f27f4a 100644 --- a/_tutorials-javascript/get_follower_and_following_list.md +++ b/_tutorials-javascript/get_follower_and_following_list.md @@ -116,13 +116,109 @@ followlist.forEach(newObj => { }); ``` ---- +Final code: -#### Try it +```javascript +//Step 1. -Click the play button below: +// const dhive = require('@hiveio/dhive'); +// //define network parameters +// let opts = {}; +// opts.addressPrefix = 'TST'; +// opts.chainId = '18dcf0a285365fc58b71f18b3d3fec954aa0c141c44e4e5cb4cf777b9eab274e'; +// //connect to a hive node, testnet in this case +// const client = new dhive.Client('http://127.0.0.1:8090', opts); -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js19getfollowerandfollowinglist?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +const dhive = require('@hiveio/dhive'); +let opts = {}; +//define network parameters +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to a hive node, production in this case +const client = new dhive.Client('https://api.hive.blog'); + + +//Step 2. user fills in the values on the UI + +//Followers function +window.submitFollower = async () => { + //clear list + document.getElementById('followList').innerHTML = ''; + + //get user name + const username = document.getElementById('username').value; + //get starting letters / word + const startFollow = document.getElementById('startFollow').value; + //get limit + var limit = document.getElementById('limit').value; + +//Step 3. Call followers list + + //get list of followers + //getFollowers(following, startFollower, followType, limit) + let followlist = await client.call('follow_api', 'get_followers', [ + username, + startFollow, + 'blog', + limit, + ]); + + document.getElementById('followResultContainer').style.display = 'flex'; + document.getElementById('followResult').className = 'form-control-plaintext alert alert-success'; + document.getElementById('followResult').innerHTML = 'Followers'; + +//Step 4. Display results on console for control check and on UI + + followlist.forEach((newObj) => { + name = newObj.follower; + document.getElementById('followList').innerHTML += name + '<br>'; + console.log(name); + }); + +}; + +//Step 2. user fills in the values on the UI + +//Following function +window.submitFollowing = async () => { + //clear list + document.getElementById('followList').innerHTML = ''; + + //get user name + const username = document.getElementById('username').value; + //get starting letters / word + const startFollow = document.getElementById('startFollow').value; + //get limit + var limit = document.getElementById('limit').value; + +//Step 3. Call following list + + //get list of authors you are following + //getFollowing(follower, startFollowing, followType, limit) + let followlist = await client.call('follow_api', 'get_following', [ + username, + startFollow, + 'blog', + limit, + ]); + + document.getElementById('followResultContainer').style.display = 'flex'; + document.getElementById('followResult').className = 'form-control-plaintext alert alert-success'; + document.getElementById('followResult').innerHTML = 'Following'; + +//Step 4. Display results on console for control check and on UI + + followlist.forEach((newObj) => { + name = newObj.following; + document.getElementById('followList').innerHTML += name + '<br>'; + console.log(name); + }); +}; + +``` + +--- ### To run this tutorial diff --git a/_tutorials-javascript/get_post_comments.md b/_tutorials-javascript/get_post_comments.md index 0db6509e..6615ee53 100644 --- a/_tutorials-javascript/get_post_comments.md +++ b/_tutorials-javascript/get_post_comments.md @@ -17,6 +17,7 @@ Each post might have comments/replies that is interesting and contributes to the Also see: * [get discussions]({{ '/search/?q=get discussions' | relative_url }}) +* [bridge.get_discussion]({{ '/apidefinitions/#bridge.get_discussion' | relative_url }}) * [database_api.find_comments]({{ '/apidefinitions/#database_api.find_comments' | relative_url }}) * [condenser_api.get_content]({{ '/apidefinitions/#condenser_api.get_content' | relative_url }}) * [tags_api.get_content_replies]({{ '/apidefinitions/#tags_api.get_content_replies' | relative_url }}) @@ -158,13 +159,105 @@ The result is returned from the post content as a `JSON` object with the followi From this result, you have access to comments made on selected post. ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +const Remarkable = require('remarkable'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); -#### Try it +//fetch list of trending posts +async function main() { + const query = { + tag: '', + limit: 5, + truncate_body: 1, + }; + client.database + .getDiscussions('trending', query) + .then(result => { + var posts = []; + result.forEach(post => { + const json = JSON.parse(post.json_metadata); + const image = json.image ? json.image[0] : ''; + const title = post.title; + const author = post.author; + const permlink = post.permlink; + const created = new Date(post.created).toDateString(); + posts.push( + `<div class="list-group-item" onclick=openPost("${author}","${permlink}")><h4 class="list-group-item-heading">${title}</h4><p>by ${author}</p><center><img src="${image}" class="img-responsive center-block" style="max-width: 450px"/></center><p class="list-group-item-text text-right text-nowrap">${created}</p></div>` + ); + }); + document.getElementById('postList').style.display = 'block'; + document.getElementById('postList').innerHTML = posts.join(''); + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} +//catch error messages +main().catch(console.error); -Click the play button below: +//get_content of the post and get_content_replies +window.openPost = async (author, permlink) => { + client.database.call('get_content', [author, permlink]).then(result => { + const md = new Remarkable({ html: true, linkify: true }); + const body = md.render(result.body); + const content = `<div class='pull-right'><button onclick=goback()>Close</button></div><br><h2>${ + result.title + }</h2><br>${body}<br>`; -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js07getpostcomments?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> + document.getElementById('postList').style.display = 'none'; + document.getElementById('postBody').style.display = 'block'; + document.getElementById('postBody').innerHTML = content; + + //get_content_replies of the selected post + client.database + .call('get_content_replies', [author, permlink]) + .then(result => { + const comments = []; + for (var i = 0; i < result.length; i++) { + comments.push( + `<div class="list-group-item list-group-item-action flex-column align-items-start">\ + <div class="d-flex w-100 justify-content-between">\ + <h5 class="mb-1">@${result[i].author}</h5>\ + <small class="text-muted">${new Date( + result[i].created + ).toString()}</small>\ + </div>\ + <p class="mb-1">${md.render(result[i].body)}</p>\ + <small class="text-muted">▲ ${ + result[i].net_votes + }</small>\ + </div>` + ); + } + document.getElementById('postComments').style.display = 'block'; + document.getElementById( + 'postComments' + ).innerHTML = comments.join(''); + }); + }); +}; +//go back from post view to list +window.goback = async () => { + document.getElementById('postList').style.display = 'block'; + document.getElementById('postBody').style.display = 'none'; + document.getElementById('postComments').style.display = 'none'; +}; + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-javascript/get_post_details.md b/_tutorials-javascript/get_post_details.md index 04d82dc7..cc53fa27 100644 --- a/_tutorials-javascript/get_post_details.md +++ b/_tutorials-javascript/get_post_details.md @@ -17,6 +17,7 @@ Accounts have unique `permlink` - permanent link for each of their posts. And Hi Also see: * [get discussions]({{ '/search/?q=get discussions' | relative_url }}) +* [bridge.get_post]({{ '/apidefinitions/#bridge.get_post' | relative_url }}) * [database_api.find_comments]({{ '/apidefinitions/#database_api.find_comments' | relative_url }}) * [condenser_api.get_content]({{ '/apidefinitions/#condenser_api.get_content' | relative_url }}) @@ -158,13 +159,78 @@ From this result, you have access to everything associated with the selected pos {% include structures/comment.html %} ---- +Final code: -#### Try it +```javascript +const dhive = require('@hiveio/dhive'); +const Remarkable = require('remarkable'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +//fetch list of trending posts +async function main() { + const query = { + tag: '', + limit: 5, + truncate_body: 1, + }; + client.database + .getDiscussions('trending', query) + .then(result => { + var posts = []; + result.forEach(post => { + console.log(post); + const json = JSON.parse(post.json_metadata); + const image = json.image ? json.image[0] : ''; + const title = post.title; + const author = post.author; + const permlink = post.permlink; + const created = new Date(post.created).toDateString(); + posts.push( + `<div class="list-group-item" onclick=openPost("${author}","${permlink}")><h4 class="list-group-item-heading">${title}</h4><p>by ${author}</p><center><img src="${image}" class="img-responsive center-block" style="max-width: 450px"/></center><p class="list-group-item-text text-right text-nowrap">${created}</p></div>` + ); + }); + document.getElementById('postList').style.display = 'block'; + document.getElementById('postList').innerHTML = posts.join(''); + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} +//catch error messages +main().catch(console.error); + +//get_content of the post +window.openPost = async (author, permlink) => { + client.database.call('get_content', [author, permlink]).then(result => { + const md = new Remarkable({ html: true, linkify: true }); + const body = md.render(result.body); + const content = `<div class='pull-right'><button onclick=goback()>Close</button></div><br><h2>${ + result.title + }</h2><br>${body}<br>`; + + document.getElementById('postList').style.display = 'none'; + document.getElementById('postBody').style.display = 'block'; + document.getElementById('postBody').innerHTML = content; + }); +}; +//go back from post view to list +window.goback = async () => { + document.getElementById('postList').style.display = 'block'; + document.getElementById('postBody').style.display = 'none'; +}; -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js05getpostdetails?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-javascript/get_posts.md b/_tutorials-javascript/get_posts.md index 4650cf7a..a3025439 100644 --- a/_tutorials-javascript/get_posts.md +++ b/_tutorials-javascript/get_posts.md @@ -24,6 +24,7 @@ application. Also see: * [get discussions]({{ '/search/?q=get discussions' | relative_url }}) +* [get ranked posts]({{ '/search/?q=get ranked posts' | relative_url }}) ## Steps @@ -207,13 +208,70 @@ The result returned from the service is a `JSON` list. This is an example list w **And that's all there is to getting top-level posts.** _See [Get post comments](get_post_comments.html) for getting comments_ ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; + +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +//filter change selection function +window.getPosts = async () => { + const filter = document.getElementById('filters').value; + const query = { + tag: document.getElementById('tag').value, + limit: 5, + }; + + console.log('Post assembled.\nFilter:', filter, '\nQuery:', query); + + client.call('bridge', 'get_ranked_posts', [ + username, + startFollow, + 'blog', + limit, + ]) + + client.database + .getDiscussions(filter, query) + .then(result => { + console.log('Response received:', result); + if (result) { + var posts = []; + result.forEach(post => { + const json = JSON.parse(post.json_metadata); + const image = json.image ? json.image[0] : ''; + const title = post.title; + const author = post.author; + const created = new Date(post.created).toDateString(); + posts.push( + `<div class="list-group-item"><h4 class="list-group-item-heading">${title}</h4><p>by ${author}</p><center><img src="${image}" class="img-responsive center-block" style="max-width: 450px"/></center><p class="list-group-item-text text-right text-nowrap">${created}</p></div>` + ); + }); + + document.getElementById('postList').innerHTML = posts.join(''); + } else { + document.getElementById('postList').innerHTML = 'No result.'; + } + }) + .catch(err => { + console.log(err); + alert(`Error:${err}, try again`); + }); +}; -#### Try it +``` -Click the play button below: -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js04getposts?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-javascript/get_state_replacement_api.md b/_tutorials-javascript/get_state_replacement_api.md index 9981615d..adbd0cbc 100644 --- a/_tutorials-javascript/get_state_replacement_api.md +++ b/_tutorials-javascript/get_state_replacement_api.md @@ -521,13 +521,96 @@ This detailed information can be used to track the performance of a specific wit } ``` ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; + +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + + +window.showAccount = async () => { + console.log('account : '); + var _info = new Array + _info = await client.database.getAccounts(['hiveio']); + console.log(_info[0]); + +} -#### Try it +window.showContent = async () => { + console.log('content : '); -Click the play button below: + const filter = 'trending'; + const query = { + limit: 20, + }; + var _info = new Array + _info = await client.database.getDiscussions(filter, query) + console.log(_info) + +} + +window.showPrice = async () => { + console.log('feed_price : '); + + _info = await client.database.getCurrentMedianHistoryPrice() + console.log(_info) + +} + +window.showProps = async () => { + console.log('props : '); + + _info = await client.database.getDynamicGlobalProperties() + console.log(_info) + +} -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js34getstatereplacementapi?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +window.showTags = async () => { + console.log('tags : '); + + _info = await client.database.call('get_trending_tags',['', 10]) + console.log(_info) + +} + +window.showTagidx = async () => { + console.log('tag_idx : '); + + _info = await client.database.call('get_trending_tags',['', 10]) + _info.forEach(post => { + console.log(post.name) + }); + +} + +window.showSchedule = async () => { + console.log('witness schedule : '); + + _info = await client.database.call('get_witness_schedule',[]); + console.log(_info); + +} + +window.showWitness = async () => { + console.log('witnesses : '); + + var _info = await client.database.call('get_witnesses_by_vote',['',10]) + console.log(_info) + +} + +``` + +--- ### To run this tutorial diff --git a/_tutorials-javascript/get_voters_list_on_post.md b/_tutorials-javascript/get_voters_list_on_post.md index 7904a0b1..3842a744 100644 --- a/_tutorials-javascript/get_voters_list_on_post.md +++ b/_tutorials-javascript/get_voters_list_on_post.md @@ -103,13 +103,85 @@ From this result, you have access to everything associated with the selected pos * `reputation` - The [reputation]({{ '/glossary/#reputation' | relative_url }}) of the account that voted. * `time` - Time the vote was submitted. ---- +Final code: -#### Try it +```javascript +const dhive = require('@hiveio/dhive'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +//fetch list of trending posts +async function main() { + const query = { + tag: '', + limit: 5, + truncate_body: 1, + }; + client.database + .getDiscussions('trending', query) + .then(result => { + var posts = []; + result.forEach(post => { + console.log('post', post); + const json = JSON.parse(post.json_metadata); + const image = json.image ? json.image[0] : ''; + const title = post.title; + const author = post.author; + const permlink = post.permlink; + const created = new Date(post.created).toDateString(); + posts.push( + `<div class="list-group-item" onclick=openPost("${author}","${permlink}")><h4 class="list-group-item-heading">${title}</h4><p>by ${author}</p><center><img src="${image}" class="img-responsive center-block" style="max-width: 450px"/></center><p class="list-group-item-text text-right text-nowrap">${created}</p></div>` + ); + }); + document.getElementById('postList').style.display = 'block'; + document.getElementById('postList').innerHTML = posts.join(''); + }) + .catch(err => { + console.log(err); + alert('Error occured, please reload the page'); + }); +} +//catch error messages +main().catch(console.error); + +//get_content of the post +window.openPost = async (author, permlink) => { + client.database + .call('get_active_votes', [author, permlink]) + .then(result => { + console.log('votes', result, JSON.stringify(result)); + + var voters = []; + voters.push( + `<div class='pull-right'><button onclick=goback()>Close</button></div><br>` + ); + result.forEach(voter => { + const name = voter.voter; + const time = new Date(voter.time).toDateString(); + voters.push(`${name} (${time})`); + }); + + document.getElementById('postList').style.display = 'none'; + document.getElementById('postBody').style.display = 'block'; + document.getElementById('postBody').innerHTML = voters.join('<li>'); + }); +}; +//go back from post view to list +window.goback = async () => { + document.getElementById('postList').style.display = 'block'; + document.getElementById('postBody').style.display = 'none'; +}; -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js06getvoterslistonpost?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-javascript/getting_started.md b/_tutorials-javascript/getting_started.md index d2a399b5..81210ab9 100644 --- a/_tutorials-javascript/getting_started.md +++ b/_tutorials-javascript/getting_started.md @@ -36,6 +36,8 @@ npm run dev-server Then open http://localhost:3000/ in your web browser. +You can also **copy** code from pages here and add into your project for quick tests. + ### Github If you'd rather clone projects in a windowed environment rather than the terminal, consider [Github Desktop](https://desktop.github.com/). diff --git a/_tutorials-javascript/grant_active_permission.md b/_tutorials-javascript/grant_active_permission.md index 99842fa8..c23c7afd 100644 --- a/_tutorials-javascript/grant_active_permission.md +++ b/_tutorials-javascript/grant_active_permission.md @@ -174,9 +174,187 @@ client.broadcast.updateAccount(accObj, privateKey).then( The results of the operation is displayed on the UI along with a block number in the console to confirm a successful operation. If you add permission to an account that already has permission, or if your private key has been entered incorrectly, an error of "Missing Active Authority" will be displayed. -Hiveconnect offers an alternative to revoking active permission with a "simple link" solution. Instead of running through a list of operations on your account, you can simply use a link similar to the one below. You will be prompted to enter your usename and password and the specified user will have their permissions removed instantly. -https://v2.hivesigner.com/revoke/@username -This is similar to the Hive Signer links that have been covered in previous tutorials. For a list of signing operations that work in this manner you can go to https://v2.hivesigner.com/sign +Hivesigner offers an alternative to revoking active permission with a "simple link" solution. Instead of running through a list of operations on your account, you can simply use a link similar to the one below. You will be prompted to enter your username and password and the specified user will have their permissions removed instantly. +https://hivesigner.com/revoke/@username +This is similar to the Hive Signer links that have been covered in previous tutorials. For a list of signing operations that work in this manner you can go to https://hivesigner.com/signs + +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a steem node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//check permission status +window.submitCheck = async () => { + //get username + const username = document.getElementById('username').value; + //get account to provide active auth + const newAccount = document.getElementById('newAccount').value; + + //query database for active array + var _data = new Array + _data = await client.database.getAccounts([username]); + const activeAuth = _data[0].active; + + //check for username duplication + const checkAuth = _data[0].active.account_auths; + var arrayindex = -1; + var checktext = " does not yet have active permission" + for (var i = 0,len = checkAuth.length; i<len; i++) { + if (checkAuth[i][0]==newAccount) { + arrayindex = i + var checktext = " has active permission" + } + } + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = newAccount + checktext; + console.log(checkAuth); +} + +//grant permission function +window.submitPermission = async () => { + //get username + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get account to provide active auth + const newAccount = document.getElementById('newAccount').value; + + var _data = new Array + _data = await client.database.getAccounts([username]); + const activeAuth = _data[0].active; + + //check for user index in active array + const checkAuth = _data[0].active.account_auths; + var arrayindex = -1; + for (var i = 0,len = checkAuth.length; i<len; i++) { + if (checkAuth[i][0]==newAccount) { + arrayindex = i + } + } + + if (arrayindex>-1) { + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = newAccount + " already has active permission and cannot be added twice"; + return; + } + + //adding of new account to active array + activeAuth.account_auths.push([ + newAccount, + parseInt(activeAuth.weight_threshold) + ]); + //sort array required for Hive blockchain + activeAuth.account_auths.sort(); + + //object creation + const accObj = { + account: username, + json_metadata: _data[0].json_metadata, + memo_key: _data[0].memo_key, + active: activeAuth, + } + + //account update broadcast + client.broadcast.updateAccount(accObj, privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = "active permission has been granted to " + newAccount; + }, + function(error) { + console.error(error); + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = error.jse_shortmsg; + } + ); +} + +//revoke permission function +window.submitRevoke = async () => { + //get username + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get account to provide active auth + const newAccount = document.getElementById('newAccount').value; + + var _data = new Array + _data = await client.database.getAccounts([username]); + const activeAuth = _data[0].active; + + //check for user index in active array + const checkAuth = _data[0].active.account_auths; + var arrayindex = -1; + for (var i = 0,len = checkAuth.length; i<len; i++) { + if (checkAuth[i][0]==newAccount) { + arrayindex = i + } + } + + if (arrayindex<0) { + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = newAccount + " does not yet have active permission to revoke"; + return; + } + + //removal of array element in order to revoke active permission + activeAuth.account_auths.splice(arrayindex, 1); + + //object creation + const accObj = { + account: username, + json_metadata: _data[0].json_metadata, + memo_key: _data[0].memo_key, + active: activeAuth, + } + + //account update broadcast + client.broadcast.updateAccount(accObj, privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = "permission has been revoked for " + newAccount; + }, + function(error) { + console.error(error); + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + const accountI = NetConfig.accounts[1]; + document.getElementById('username').value = account.address; + document.getElementById('privateKey').value = account.privActive; + document.getElementById('newAccount').value = accountI.address; +}; + +``` ### To run this tutorial diff --git a/_tutorials-javascript/grant_posting_permission.md b/_tutorials-javascript/grant_posting_permission.md index daa1c0db..7e088d39 100644 --- a/_tutorials-javascript/grant_posting_permission.md +++ b/_tutorials-javascript/grant_posting_permission.md @@ -165,9 +165,185 @@ client.broadcast.updateAccount(accObj, privateKey).then( The results of the operation is displayed on the UI along with a block number in the console to confirm a successful operation. If you add permission to an account that already has permission will display an error of "Missing Active Authority". -Hiveconnect offers an alternative to revoking posting permission with a "simple link" solution. Instead of running through a list of opetions on your account, you can simply use a link similar to the one below. You will be prompted to enter your usename and password and the specified user will have their posting permission removed instantly. -https://v2.hivesigner.com/revoke/@username -This is similar to the Hive Signer links that have been covered in previous tutorials. For a list of signing operations that work in this manner you can go to https://v2.hivesigner.com/sign +Hivesigner offers an alternative to revoking posting permission with a "simple link" solution. Instead of running through a list of opetions on your account, you can simply use a link similar to the one below. You will be prompted to enter your usename and password and the specified user will have their posting permission removed instantly. +https://hivesigner.com/revoke/@username +This is similar to the Hive Signer links that have been covered in previous tutorials. For a list of signing operations that work in this manner you can go to https://hivesigner.com/signs + + +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//check permission status +window.submitCheck = async () => { + //get username + const username = document.getElementById('username').value; + //get account to provide posting auth + const newAccount = document.getElementById('newAccount').value; + + //query database for posting array + var _data = new Array(); + _data = await client.database.getAccounts([username]); + const postingAuth = _data[0].posting; + + //check for username duplication + const checkAuth = _data[0].posting.account_auths; + var arrayindex = -1; + var checktext = ' does not yet have posting permission'; + for (var i = 0, len = checkAuth.length; i < len; i++) { + if (checkAuth[i][0] == newAccount) { + arrayindex = i; + var checktext = ' already has posting permission'; + } + } + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = newAccount + checktext; + console.log(checkAuth); +}; + +//grant permission function +window.submitPermission = async () => { + //get username + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get account to provide posting auth + const newAccount = document.getElementById('newAccount').value; + + var _data = new Array(); + _data = await client.database.getAccounts([username]); + const postingAuth = _data[0].posting; + + //adding of new account to posting array + postingAuth.account_auths.push([ + newAccount, + parseInt(postingAuth.weight_threshold), + ]); + //sort array required for hive blockchain + postingAuth.account_auths.sort(); + + //object creation + const accObj = { + account: username, + json_metadata: _data[0].json_metadata, + memo_key: _data[0].memo_key, + posting: postingAuth, + }; + + //account update broadcast + client.broadcast.updateAccount(accObj, privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('permCheckContainer').style.display = + 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = + 'posting permission has been granted to ' + newAccount; + }, + function(error) { + console.error(error); + document.getElementById('permCheckContainer').style.display = + 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = error.jse_shortmsg; + } + ); +}; + +//revoke permission function +window.submitRevoke = async () => { + //get username + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get account to provide posting auth + const newAccount = document.getElementById('newAccount').value; + + var _data = new Array(); + _data = await client.database.getAccounts([username]); + const postingAuth = _data[0].posting; + + //check for user index in posting array + const checkAuth = _data[0].posting.account_auths; + var arrayindex = -1; + for (var i = 0, len = checkAuth.length; i < len; i++) { + if (checkAuth[i][0] == newAccount) { + arrayindex = i; + } + } + + if (arrayindex < 0) { + document.getElementById('permCheckContainer').style.display = 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = + newAccount + ' does not yet have posting permission to revoke'; + return; + } + + //removal of array element in order to revoke posting permission + postingAuth.account_auths.splice(arrayindex, 1); + + //object creation + const accObj = { + account: username, + json_metadata: _data[0].json_metadata, + memo_key: _data[0].memo_key, + posting: postingAuth, + }; + + //account update broadcast + client.broadcast.updateAccount(accObj, privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('permCheckContainer').style.display = + 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('permCheck').innerHTML = + 'permission has been revoked for ' + newAccount; + }, + function(error) { + console.error(error); + document.getElementById('permCheckContainer').style.display = + 'flex'; + document.getElementById('permCheck').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('permCheck').innerHTML = error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + const accountI = NetConfig.accounts[1]; + document.getElementById('username').value = account.address; + document.getElementById('privateKey').value = account.privActive; + document.getElementById('newAccount').value = accountI.address; +}; + +``` ### To run this tutorial diff --git a/_tutorials-javascript/hivesigner.md b/_tutorials-javascript/hivesigner.md index ce286884..68555b05 100644 --- a/_tutorials-javascript/hivesigner.md +++ b/_tutorials-javascript/hivesigner.md @@ -103,6 +103,77 @@ Now that `hivesigner` is initialized we can start authentication and perform sim **That's all there is to it.** +Final code: + +```javascript +const hivesigner = require('hivesigner'); + +// init hivesigner +let api = hivesigner.Initialize({ + app: 'demo-app', + callbackURL: 'http://localhost:3000', + accessToken: 'access_token', + scope: ['vote', 'comment'], +}); +// get login URL +let link = api.getLoginURL(); + +// acquire access_token and username after authorization +let access_token = new URLSearchParams(document.location.search).get( + 'access_token' +); +let username = new URLSearchParams(document.location.search).get('username'); + +let lt = '', + ut = '', + lo = '', + jt = '', + t = ''; +if (access_token) { + // set access token after login + api.setAccessToken(access_token); + + // Logout button + lt = `<a href="#" onclick='logOut()'>Log Out</a>`; + // User name after successfull login + ut = `<p>User: <b>${username}</b></p>`; + // Get user details button + lo = `<a href="#" onclick='getUserDetails()'>Get User details</a>`; + // User details JSON output + jt = `<pre id="userDetailsJSON"></pre>`; + + t = lt + ut + lo + jt; +} else { + // Login button + t = `<a href=${link}>Log In</a>`; +} + +// set template +document.getElementById('content').innerHTML = t; + +// Logout function, revoke access token +logOut = () => { + api.revokeToken(function(err, res) { + if (res && res.success) { + access_token = null; + document.location.href = '/'; + } + }); + return false; +}; + +// Get User details function, returns user data via Hivesigner API +getUserDetails = () => { + api.me(function(err, res) { + if (res) { + const user = JSON.stringify(res, undefined, 2); + document.getElementById('userDetailsJSON').innerHTML = user; + } + }); +}; + +``` + To learn more about [Hivesigner SDK](https://github.com/ecency/hivesigner-sdk) or integration guide check [official Hivesigner docs](https://docs.hivesigner.com). ### To Run the tutorial diff --git a/_tutorials-javascript/power_down.md b/_tutorials-javascript/power_down.md index 49a2b410..1b67bb30 100644 --- a/_tutorials-javascript/power_down.md +++ b/_tutorials-javascript/power_down.md @@ -116,6 +116,81 @@ window.submitTx = async () => { That's it! +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { TestnetHive as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_account:`, _account); + + const name = _account[0].name; + const avail = + parseFloat(_account[0].vesting_shares) - + (parseFloat(_account[0].to_withdraw) - + parseFloat(_account[0].withdrawn)) / + 1e6 - + parseFloat(_account[0].delegated_vesting_shares); + + const props = await client.database.getDynamicGlobalProperties(); + const vestHive = parseFloat( + parseFloat(props.total_vesting_fund_hive) * + (parseFloat(avail) / parseFloat(props.total_vesting_shares)), + 6 + ); + + const balance = `Available Vests for ${name}: ${avail} VESTS ~ ${vestHive} HIVE POWER<br/><br/>`; + document.getElementById('accBalance').innerHTML = balance; + document.getElementById('hive').value = vestHive; + + document.getElementById('sc').style.display = 'block'; + const link = `https://testnet.hivesigner.com/sign/withdraw-vesting?account=${name}&vesting_shares=${avail}`; + document.getElementById('sc').innerHTML = `<br/><a href=${encodeURI( + link + )} target="_blank">Hive Signer signing</a>`; +}; + +window.submitTx = async () => { + const props = await client.database.getDynamicGlobalProperties(); + const vests = parseFloat(document.getElementById('hive').value) / + (parseFloat(props.total_vesting_fund_hive) / parseFloat(props.total_vesting_shares)); + const privateKey = PrivateKey.fromString( + document.getElementById('wif').value + ); + const op = [ + 'withdraw_vesting', + { + account: document.getElementById('username').value, + vesting_shares: vests.toFixed(6) + ' VESTS', + }, + ]; + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/power_up_hive.md b/_tutorials-javascript/power_up_hive.md index 020eac95..a68b47b0 100644 --- a/_tutorials-javascript/power_up_hive.md +++ b/_tutorials-javascript/power_up_hive.md @@ -99,6 +99,66 @@ window.submitTx = async () => { That's it! +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Mainnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_accounts', [[accSearch]]); + console.log(`_account:`, _account); + const name = _account[0].name; + const hive_balance = _account[0].balance; + const balance = `Available Hive balance for ${name}: ${hive_balance}<br/>`; + document.getElementById('accBalance').innerHTML = balance; + document.getElementById('hive').value = hive_balance; + const receiver = document.getElementById('receiver').value; + + document.getElementById('sc').style.display = 'block'; + const link = `https://hivesigner.com/sign/transfer-to-vesting?from=${name}&to=${receiver}&amount=${hive_balance}`; + document.getElementById('sc').innerHTML = `<br/><a href=${encodeURI( + link + )} target="_blank">Hive Signer signing</a>`; +}; + +window.submitTx = async () => { + const privateKey = PrivateKey.fromString( + document.getElementById('wif').value + ); + const op = [ + 'transfer_to_vesting', + { + from: document.getElementById('username').value, + to: document.getElementById('receiver').value, + amount: document.getElementById('hive').value, + }, + ]; + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/reblogging_post.md b/_tutorials-javascript/reblogging_post.md index 4d7ad86b..4cb37d07 100644 --- a/_tutorials-javascript/reblogging_post.md +++ b/_tutorials-javascript/reblogging_post.md @@ -136,6 +136,115 @@ There is a line in the error log indicating "Account has already reblogged this It should be noted that reblogging a post does not create a new post on the blockchain but merely shares the post to whomever is following the user doing the reblog. Along with `reblogging` the `custom_json` broadcast operation also includes options for following users and editing blog content. More information on how to use the `broadcast` operation and options surrounding the operation can be found on the Hive [Devportal]({{ '/apidefinitions/#broadcast_ops_comment' | relative_url }}) +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; + +//define network parameters +let opts = {}; +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to a Hive node. This is currently setup on production, but we recommend using a testnet +const client = new Client('https://api.hive.blog', opts); +window.client = client; + +//This is a convenience function for the UI. +window.autofillAuthorAndPermlink = function(el) { + document.getElementById('theAuthor').value = el.dataset.author; + document.getElementById('thePermLink').value = el.dataset.permlink; +}; + +function fetchBlog() { + const query = { + tag: 'hiveio', + limit: 5, + }; + + client.database + .getDiscussions('blog', query) //get a list of posts for easy reblogging. + .then(result => { + //when the response comes back ... + const postList = []; + console.log('Listing blog posts by ' + query.tag); + result.forEach(post => { + //... loop through the posts ... + const author = post.author; + const permlink = post.permlink; + console.log(author, permlink, post); + postList.push( + // and render the table rows + `<tr><td><button class="btn-sm btn-success" data-author="${author}" data-permlink="${permlink}" onclick="autofillAuthorAndPermlink(this)">Autofill</button></td><td>${author}</td><td>${permlink}</td></tr>` + ); + }); + + document.getElementById('postList').innerHTML = postList.join(''); + }) + .catch(err => { + console.error(err); + alert('Error occured' + err); + }); +} + +//this function will execute when the "Reblog!" button is clicked +window.submitPost = async () => { + reblogOutput('preparing to submit'); + //get private key + try { + const privateKey = PrivateKey.from( + document.getElementById('postingKey').value + ); + + //get account name + const myAccount = document.getElementById('username').value; + //get blog author + const theAuthor = document.getElementById('theAuthor').value; + //get blog permLink + const thePermLink = document.getElementById('thePermLink').value; + + const jsonOp = JSON.stringify([ + 'reblog', + { + account: myAccount, + author: theAuthor, + permlink: thePermLink, + }, + ]); + + const data = { + id: 'follow', + json: jsonOp, + required_auths: [], + required_posting_auths: [myAccount], + }; + reblogOutput('reblogging:\n', JSON.stringify(data, 2)); + console.log('reblogging:', data); + client.broadcast.json(data, privateKey).then( + function(result) { + reblogOutput(result); + console.log('reblog result: ', result); + }, + function(error) { + console.error(error); + } + ); + } catch (e) { + reblogOutput(e.message); + console.log(e); + } +}; + +function reblogOutput(output) { + document.getElementById('results').innerText = output; +} + +window.onload = async () => { + fetchBlog(); +}; + +``` + ## To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/search_accounts.md b/_tutorials-javascript/search_accounts.md index 77a3f72c..39dfbb57 100644 --- a/_tutorials-javascript/search_accounts.md +++ b/_tutorials-javascript/search_accounts.md @@ -72,13 +72,35 @@ document.getElementById('accList').innerHTML = _accounts.join('<br>'); } ``` ---- +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); -#### Try it -Click the play button below: -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js15searchaccounts?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +//submitAcc function from html input +const max = 10; +window.submitAcc = async () => { + const accSearch = document.getElementById("username").value; + + const _accounts = await client.database.call('lookup_accounts',[accSearch, max]); + console.log(`_accounts:`, _accounts); + +//disply list of account names with line breaks + document.getElementById('accList').innerHTML = _accounts.join('<br>'); +} + +``` + +--- ## To run this tutorial diff --git a/_tutorials-javascript/search_tags.md b/_tutorials-javascript/search_tags.md index 21909c70..1bc069f9 100644 --- a/_tutorials-javascript/search_tags.md +++ b/_tutorials-javascript/search_tags.md @@ -76,13 +76,45 @@ _tags.forEach(post => { document.getElementById('tagList').innerHTML = posts.join('<br>'); ``` ---- +Final code: -#### Try it +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); -Click the play button below: +//submitTab function from html input +const max = 10; +window.submitTag = async () => { + const tagSearch = document.getElementById('tagName').value; + + //get list of tags from blockchain + const _tags = await client.database.call('get_trending_tags', [ + tagSearch, + max, + ]); + + console.log('tags: ', _tags); + var posts = []; + _tags.forEach(post => { + posts.push( + `<div class="list-group-item"><h5 class="list-group-item-heading">${ + post.name + }</h5></div>` + ); + }); + //disply list of tags with line breaks + document.getElementById('tagList').innerHTML = posts.join('<br>'); +}; -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js16searchtags?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` + +--- ### To run this tutorial diff --git a/_tutorials-javascript/set_withdraw_route.md b/_tutorials-javascript/set_withdraw_route.md index a82cf0c7..f95f6999 100644 --- a/_tutorials-javascript/set_withdraw_route.md +++ b/_tutorials-javascript/set_withdraw_route.md @@ -119,6 +119,79 @@ window.submitTx = async () => { That's it! +Final code: + +```javascript +const dhive = require('@hiveio/dhive'); +let opts = {}; +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; +//connect to server which is connected to the network/production +const client = new dhive.Client('https://api.hive.blog'); + +//submitAcc function from html input +const max = 5; +window.submitAcc = async () => { + const accSearch = document.getElementById('username').value; + + const _account = await client.database.call('get_withdraw_routes', [ + accSearch, + ]); + console.log(`_account:`, _account); + let info = ''; + let sum = 0; + if (_account.length > 0) { + for (var i = 0; i < _account.length; i++) { + info += `${_account[i].to_account} - ${_account[i].percent / + 100}%<br>`; + sum += _account[i].percent / 100; + } + } else { + info += `No route is available!<br>`; + } + info += `You can set ${100 - sum}% remaining part to other accounts!`; + document.getElementById('accInfo').innerHTML = info; +}; +window.openSC = async () => { + const link = `https://hivesigner.com/sign/set-withdraw-vesting-route?from_account=${ + document.getElementById('username').value + }&percent=${document.getElementById('hive').value * 100}&to_account=${ + document.getElementById('account').value + }&auto_vest=${document.getElementById('percent').checked}`; + window.open(link); +}; +window.submitTx = async () => { + const privateKey = dhive.PrivateKey.fromString( + document.getElementById('wif').value + ); + const op = [ + 'set_withdraw_vesting_route', + { + from_account: document.getElementById('username').value, + to_account: document.getElementById('account').value, + percent: document.getElementById('hive').value * 100, + auto_vest: document.getElementById('percent').checked, + }, + ]; + client.broadcast.sendOperations([op], privateKey).then( + function(result) { + document.getElementById('result').style.display = 'block'; + document.getElementById( + 'result' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/>`; + }, + function(error) { + console.error(error); + } + ); +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/stream_blockchain_transactions.md b/_tutorials-javascript/stream_blockchain_transactions.md index c5c44f48..0fe1bbca 100644 --- a/_tutorials-javascript/stream_blockchain_transactions.md +++ b/_tutorials-javascript/stream_blockchain_transactions.md @@ -124,13 +124,64 @@ Example of output: } ``` ---- +Final code: + +```javascript +const dsteem = require('@hiveio/dhive'); + +let opts = {}; + +//connect to production server +opts.addressPrefix = 'STM'; +opts.chainId = + 'beeab0de00000000000000000000000000000000000000000000000000000000'; + +//connect to server which is connected to the network/production +const client = new dsteem.Client('https://api.hive.blog'); + +let stream; +let state; +let blocks = []; +//start stream +async function main() { + stream = client.blockchain.getBlockStream(); + stream + .on('data', function(block) { + //console.log(block); + blocks.unshift( + `<div class="list-group-item"><h5 class="list-group-item-heading">Block id: ${ + block.block_id + }</h5><p>Transactions in this block: ${ + block.transactions.length + } <br>Witness: ${ + block.witness + }</p><p class="list-group-item-text text-right text-nowrap">Timestamp: ${ + block.timestamp + }</p></div>` + ); + document.getElementById('blockList').innerHTML = blocks.join(''); + }) + .on('end', function() { + // done + console.log('END'); + }); +} +//catch error messages +main().catch(console.error); + +//pause stream +window.pauseStream = async () => { + state = stream.pause(); +}; -#### Try it +//resume stream +window.resumeStream = async () => { + state = state.resume(); +}; -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/js13streamblockchaintransactions?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-javascript/submit_comment_reply.md b/_tutorials-javascript/submit_comment_reply.md index 19dde55e..9ef6fd04 100644 --- a/_tutorials-javascript/submit_comment_reply.md +++ b/_tutorials-javascript/submit_comment_reply.md @@ -142,6 +142,84 @@ That's all there is to it. The `broadcast` operation has more to offer than just committing a post/comment to the blockchain. It provides a mulititude of options that can accompany this commit. The max payout and percent of hive dollars can be set. When authors don't want all of the benifits from a post, they can set the payout factors to zero or beneficiaries can be set to receive part of the rewards. You can also set whether votes are allowed or not. The broadcast to the blockchain can be modified to meet the exact requirements of the author. More information on how to use the `broadcast` operation can be found on the Hive [Devportal]({{ '/apidefinitions/#broadcast_ops_comment' | relative_url }}) with a list of the available broadcast options under the specific [Appbase API]({{ '/apidefinitions/#broadcast_ops_comment_options' | relative_url }}) +Final code: + +```javascript +//Step 1. +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to server which is connected to the network/testnet +const client = new Client(NetConfig.url, opts); + +//Step 2. user fills in the values for 'parent_author' and 'parent_permlink' +//Step 3. user adds content for the comment in the 'body' textarea + +//submit post function +window.submitComment = async () => { + //Step 4. get all values from the UI + + //get private key + const privateKey = PrivateKey.fromString( + document.getElementById('postingKey').value + ); + //get account name + const account = document.getElementById('username').value; + //get body + const body = document.getElementById('body').value; + //get parent author permalink + const parent_author = document.getElementById('parent_author').value; + //get parent author permalink + const parent_permlink = document.getElementById('parent_permlink').value; + + //generate random permanent link for post + const permlink = Math.random() + .toString(36) + .substring(2); + + const payload = { + author: account, + title: '', + body: body, + parent_author: parent_author, + parent_permlink: parent_permlink, + permlink: permlink, + json_metadata: '', + }; + + console.log('client.broadcast.comment payload:', payload); + client.broadcast.comment(payload, privateKey).then( + function(result) { + console.log('client.broadcast.comment response', result); + document.getElementById('postLink').style.display = 'block'; + document.getElementById( + 'postLink' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/><a href="http://127.0.0.1:8080/@${parent_author}/${parent_permlink}">Check post here</a>`; + }, + function(error) { + console.error(error); + } + ); +}; + +window.clearFields = function() { + document.getElementById('body').value = ''; + document.getElementById('parent_author').value = ''; + document.getElementById('parent_permlink').value = ''; +}; + +window.onload = () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('postingKey').value = account.privPosting; +}; + +``` + ### To Run the tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/submit_post.md b/_tutorials-javascript/submit_post.md index 92dc093a..4a4bd362 100644 --- a/_tutorials-javascript/submit_post.md +++ b/_tutorials-javascript/submit_post.md @@ -115,6 +115,78 @@ After the post has been broadcast to the network, we can simply set all the fiel The `broadcast` operation has more to offer than just committing a post/comment to the blockchain. It provides a mulititude of options that can accompany this commit. The max payout and percent of hive dollars can be set. When authors don't want all of the benifits from a post, they can set the payout factors to zero or beneficiaries can be set to receive part of the rewards. You can also set whether votes are allowed or not. The broadcast to the blockchain can be modified to meet the exact requirements of the author. More information on how to use the `broadcast` operation can be found on the Hive [Devportal]({{ '/apidefinitions/#broadcast_ops_comment' | relative_url }}) with a list of the available broadcast options under the specific [Appbase API]({{ '/apidefinitions/#broadcast_ops_comment_options' | relative_url }}) +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to server which is connected to the network/testnet +const client = new Client(NetConfig.url, opts); + +//submit post function +window.submitPost = async () => { + //get private key + const privateKey = PrivateKey.fromString( + document.getElementById('postingKey').value + ); + //get account name + const account = document.getElementById('username').value; + //get title + const title = document.getElementById('title').value; + //get body + const body = document.getElementById('body').value; + //get tags and convert to array list + const tags = document.getElementById('tags').value; + const taglist = tags.split(' '); + //make simple json metadata including only tags + const json_metadata = JSON.stringify({ tags: taglist }); + //generate random permanent link for post + const permlink = Math.random() + .toString(36) + .substring(2); + + const payload = { + author: account, + body: body, + json_metadata: json_metadata, + parent_author: '', + parent_permlink: taglist[0], + permlink: permlink, + title: title, + }; + console.log('client.broadcast.comment:', payload); + client.broadcast.comment(payload, privateKey).then( + function(result) { + console.log('response:', result); + document.getElementById('title').value = ''; + document.getElementById('body').value = ''; + document.getElementById('tags').value = ''; + document.getElementById('postLink').style.display = 'block'; + document.getElementById( + 'postLink' + ).innerHTML = `<br/><p>Included in block: ${ + result.block_num + }</p><br/><br/><a href="http://127.0.0.1:8080/${ + taglist[0] + }/@${account}/${permlink}">Check post here</a>`; + }, + function(error) { + console.error(error); + } + ); +}; + +window.onload = () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('postingKey').value = account.privPosting; +}; + +``` + ### To Run the tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/transfer_hive_and_hbd.md b/_tutorials-javascript/transfer_hive_and_hbd.md index a81f6039..11711014 100644 --- a/_tutorials-javascript/transfer_hive_and_hbd.md +++ b/_tutorials-javascript/transfer_hive_and_hbd.md @@ -124,6 +124,80 @@ client.broadcast.transfer(transf, privateKey).then( ); ``` +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +// //connect to a Hive node, tesetnet in this case +const client = new Client(NetConfig.url, opts); + +//submit transfer function executes when you click "Transfer" button +window.submitTransfer = async () => { + //get all values from the UI + //get account name of sender + const username = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('privateKey').value + ); + //get recipient + const recipient = document.getElementById('recipient').value; + //get comments + const comments = document.getElementById('comments').value; + //get transfer amount + const quantity = document.getElementById('quantity').value; + //get transfer type + const type = document.getElementById('type').value; + + const transfer = quantity.concat(' ', type); + + //create transfer object + const transf = new Object(); + transf.from = username; + transf.to = recipient; + transf.amount = transfer; + transf.memo = comments; + + //broadcast the transfer + + client.broadcast.transfer(transf, privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('transferResultContainer').style.display = + 'flex'; + document.getElementById('transferResult').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('transferResult').innerHTML = 'Success'; + }, + function(error) { + console.error(error); + document.getElementById('transferResultContainer').style.display = + 'flex'; + document.getElementById('transferResult').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('transferResult').innerHTML = + error.jse_shortmsg; + } + ); +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + const accountI = NetConfig.accounts[1]; + document.getElementById('username').value = account.address; + document.getElementById('privateKey').value = account.privActive; + document.getElementById('recipient').value = accountI.address; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/vote_on_content.md b/_tutorials-javascript/vote_on_content.md index 89eb4a27..e7f7388c 100644 --- a/_tutorials-javascript/vote_on_content.md +++ b/_tutorials-javascript/vote_on_content.md @@ -217,6 +217,145 @@ window.onload = () => { More information on how to use the `broadcast` operation and options surrounding the operation can be found on the [Hive Devportal]({{ '/apidefinitions/#broadcast_ops_vote' | relative_url }}) +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; + +//connect to a hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +const createPrivateKey = function() { + try { + return PrivateKey.fromString( + document.getElementById('postingKey').value + ); + } catch (e) { + const resultEl = document.getElementById('result'); + resultEl.className = 'form-control-plaintext alert alert-danger'; + resultEl.innerHTML = e.message + ' - See console for full error.'; + throw e; + } +}; + +//refer to "10_submit_post" in the tutorials folder for creating a post on hive.blog +window.createPost = async () => { + //get private key + const privateKey = createPrivateKey(); + //get account name + const account = document.getElementById('username').value; + //for content + const time = new Date().getTime(); + //get title + const title = `developers.hive.io - JS-T:17 ${time}`; + //get body + const body = `Go to [developers.hive.io](https://developers.hive.io) for the latest in Hive tutorials! This post was created by someone using the active version of those tutorials at [https://gitlab.syncad.com/hive/devportal/-/tree/develop/tutorials/javascript](https://gitlab.syncad.com/hive/devportal/-/tree/develop/tutorials/javascript) + + ${time}`; + //get tags and convert to array list + const tags = 'blog'; + const taglist = tags.split(' '); + //make simple json metadata including only tags + const json_metadata = JSON.stringify({ tags: taglist }); + //generate random permanent link for post + const permlink = Math.random() + .toString(36) + .substring(2); + + client.broadcast + .comment( + { + author: account, + body: body, + json_metadata: json_metadata, + parent_author: '', + parent_permlink: tags, + permlink: permlink, + title: title, + }, + privateKey + ) + .then( + function(result) { + document.getElementById('permlink').innerHTML = permlink; + document.getElementById( + 'postLink' + ).innerHTML = `Included in block: <a href="http://127.0.0.1:8080/${ + taglist[0] + }/@${account}/${permlink}" target="_blank">${ + result.block_num + }</a>`; + document.getElementById('postResult').style.display = 'flex'; + document.getElementById('permlink').value = permlink; + }, + function(error) { + console.error(error); + } + ); +}; + +//submit vote function executes when you click "Submit Vote" button +window.submitVote = async () => { + //we'll make use of resultEl in multiple child scopes. This is generally good practice. + const resultEl = document.getElementById('result'); + resultEl.innerHTML = 'pending...'; + + //get all values from the UI// + //get account name of voter + const voter = document.getElementById('username').value; + //get private posting key + const privateKey = createPrivateKey(); + //get author of post/comment to vote + const author = document.getElementById('author').value; + //get post permalink to vote + const permlink = document.getElementById('permlink').value; + //get weight of vote + const weight = parseInt( + document.getElementById('currentWeight').innerHTML, + 10 + ); + + //create vote object + const vote = { + voter, + author, + permlink, + weight, //needs to be an integer for the vote function + }; + + //broadcast the vote + client.broadcast.vote(vote, privateKey).then( + function(result) { + console.log('success:', result); + resultEl.className = 'form-control-plaintext alert alert-success'; + resultEl.innerHTML = 'Success! See console for full response.'; + }, + function(error) { + console.log('error:', error); + resultEl.className = 'form-control-plaintext alert alert-danger'; + resultEl.innerHTML = + error.jse_shortmsg + ' - See console for full response.'; + } + ); +}; + +window.onload = async () => { + var voteWeightSlider = document.getElementById('voteWeight'); + var currentWeightDiv = document.getElementById('currentWeight'); + currentWeightDiv.innerHTML = voteWeightSlider.value; + voteWeightSlider.oninput = function() { + currentWeightDiv.innerHTML = this.value; + }; + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('postingKey').value = account.privPosting; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-javascript/witness_listing_and_voting.md b/_tutorials-javascript/witness_listing_and_voting.md index bf9adb0e..cae7fff5 100644 --- a/_tutorials-javascript/witness_listing_and_voting.md +++ b/_tutorials-javascript/witness_listing_and_voting.md @@ -182,6 +182,121 @@ window.submitNo = async () => { The option buttons (continue with voting process or stop) are disabled at the end of the process in order to remove confusion on what to do next or what the option buttons will do. +Final code: + +```javascript +import { Client, PrivateKey } from '@hiveio/dhive'; +import { Testnet as NetConfig } from '../../configuration'; //A Hive Testnet. Replace 'Testnet' with 'Mainnet' to connect to the main Hive blockchain. + +let opts = { ...NetConfig.net }; +//connect to a Hive node, testnet in this case +const client = new Client(NetConfig.url, opts); + +//create witness list function +window.createList = async () => { + //get list limit + const limit = document.getElementById('limit').value; + + const witnessdata = await client.database.getState('witnesses'); + var witnesses = []; + + for (const witness in witnessdata.witnesses) { + console.log('witness : ', witness); + witnesses.push( + `<li><a href="#" onclick="document.getElementById('witness').value = '${witness}';">${witness}</a></li>` + ); + } + document.getElementById('witnessList').innerHTML = witnesses.join(''); + document.getElementById('witnessListContainer').style.display = 'flex'; +}; + +//submit vote function executes when you click "Submit Vote" button +window.submitVote = async () => { + //get all values from the UI + //get account name of voter + const voter = document.getElementById('username').value; + //get private active key + const privateKey = PrivateKey.fromString( + document.getElementById('activeKey').value + ); + //get witness name + const witness = document.getElementById('witness').value; + + //check if witness is already voted for + var _data = await client.database.getAccounts([voter]); + const witnessvotes = _data[0]['witness_votes']; + const approve = witnessvotes.includes(witness); + if (approve) { + var checkresult = + 'Witness has already been voted for, would you like to remove vote?'; + var votecheck = 'Vote removed'; + } else { + var checkresult = + 'Witness has not yet been voted for, would you like to vote?'; + var votecheck = 'Vote added'; + } + + document.getElementById('voteCheckContainer').style.display = 'flex'; + document.getElementById('voteCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('voteCheck').innerHTML = checkresult; + + document.getElementById('submitYesBtn').style.visibility = 'visible'; + document.getElementById('submitNoBtn').style.visibility = 'visible'; + + window.submitYes = async () => { + //create vote object + const vote = [ + 'account_witness_vote', + { account: voter, witness: witness, approve: !approve }, + ]; + + //broadcast the vote + client.broadcast.sendOperations([vote], privateKey).then( + function(result) { + console.log( + 'included in block: ' + result.block_num, + 'expired: ' + result.expired + ); + document.getElementById('voteCheckContainer').style.display = + 'flex'; + document.getElementById('voteCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('voteCheck').innerHTML = votecheck; + }, + function(error) { + console.error(error); + document.getElementById('voteCheckContainer').style.display = + 'flex'; + document.getElementById('voteCheck').className = + 'form-control-plaintext alert alert-danger'; + document.getElementById('voteCheck').innerHTML = + error.jse_shortmsg; + } + ); + document.getElementById('submitYesBtn').style.visibility = 'hidden'; + document.getElementById('submitNoBtn').style.visibility = 'hidden'; + }; + + window.submitNo = async () => { + document.getElementById('voteCheckContainer').style.display = 'flex'; + document.getElementById('voteCheck').className = + 'form-control-plaintext alert alert-success'; + document.getElementById('voteCheck').innerHTML = + 'Vote process has ben cancelled'; + document.getElementById('submitYesBtn').style.visibility = 'hidden'; + document.getElementById('submitNoBtn').style.visibility = 'hidden'; + }; +}; + +window.onload = async () => { + const account = NetConfig.accounts[0]; + document.getElementById('username').value = account.address; + document.getElementById('activeKey').value = account.privActive; +}; + +``` + ### To run this tutorial 1. `git clone https://gitlab.syncad.com/hive/devportal.git` diff --git a/_tutorials-python/account_recovery.md b/_tutorials-python/account_recovery.md index bfc7b3b0..290d7d24 100644 --- a/_tutorials-python/account_recovery.md +++ b/_tutorials-python/account_recovery.md @@ -241,13 +241,153 @@ print('result') print(result) ``` ---- +Final code: + +```python +import getpass +import beembase +from beem.account import Account +from beem import Hive +from beem.transactionbuilder import TransactionBuilder +from beemgraphenebase.account import PasswordKey +from beembase.objects import Permission + +# capture user information +account = input('account to be recovered: ') +old_password = getpass.getpass('recent password for account: ') +new_password = getpass.getpass('new password for account: ') + +recovery_account = input('account owner (recovery account name): ') +recovery_account_private_key = getpass.getpass('account owner private ACTIVE key: ') +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +client = Hive(node_url, keys=[recovery_account_private_key]) +account = Account(account, blockchain_instance=client) +recovery_account = Account(recovery_account, blockchain_instance=client) + +# create new account owner keys +new_account_owner_private_key = PasswordKey(account.name, new_password, role='owner').get_private_key() +new_account_owner_private_key_string = str(new_account_owner_private_key) +new_account_owner_public_key = str(new_account_owner_private_key.pubkey) + +# create old account owner keys +old_account_owner_private_key = PasswordKey(account.name, old_password, role='owner').get_private_key() +old_account_owner_private_key_string = str(old_account_owner_private_key) +old_account_owner_public_key = str(old_account_owner_private_key.pubkey) + +# owner key format +new_owner_authority = { + "key_auths": [ + [new_account_owner_public_key, 1] + ], + "account_auths": [], + "weight_threshold": 1 +} + +# recovery request data object creation +request_op_data = { + 'account_to_recover': account.name, + 'recovery_account': recovery_account.name, + 'new_owner_authority': new_owner_authority, + 'extensions': [] +} + +# recovery request operation creation +request_op = beembase.operations.Request_account_recovery(**request_op_data) + +print('request_op_data') +print(request_op_data) + +# recovery request broadcast +request_result = client.finalizeOp(request_op, recovery_account.name, "active") + +print('request_result') +print(request_result) + +# owner key format +recent_owner_authority = { + "key_auths": [ + [old_account_owner_public_key, 1] + ], + "account_auths": [], + "weight_threshold": 1 +} -#### Try it +# recover account data object +op_recover_account_data = { + 'account_to_recover': account.name, + 'new_owner_authority': new_owner_authority, + 'recent_owner_authority': recent_owner_authority, + 'extensions': [] +} + +# account keys update data object +op_account_update_data = { + "account": account.name, + "active": { + "key_auths": [ + [str(PasswordKey(account.name, new_password, role='active').get_private_key().pubkey), 1] + ], + "account_auths": [], + "weight_threshold": 1 + }, + "posting": { + "key_auths": [ + [str(PasswordKey(account.name, new_password, role='posting').get_private_key().pubkey), 1] + ], + "account_auths": [], + "weight_threshold": 1 + }, + "memo_key": str(PasswordKey(account.name, new_password, role='memo').get_private_key().pubkey), + "json_metadata": "" +} + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# recover account initialisation and transmission +client = Hive(node_url, keys=[recovery_account_private_key]) + +op_recover_account = beembase.operations.Recover_account(**op_recover_account_data) -Click the play button below: +print('op_recover_account') +print(op_recover_account) + +tb = TransactionBuilder(blockchain_instance=client) +tb.appendOps([op_recover_account]) +tb.appendWif(str(old_account_owner_private_key)) +tb.appendWif(str(new_account_owner_private_key)) +tb.sign() + +result = tb.broadcast() +print('result') +print(result) + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# update account keys initialisation and transmission +client = Hive(node_url, keys=[new_account_owner_private_key]) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py35accountrecovery?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +op_account_update = beembase.operations.Account_update(**op_account_update_data) + +print('op_account_update') +print(op_account_update) + +tb = TransactionBuilder(blockchain_instance=client) +tb.appendOps([op_account_update]) +tb.appendWif(str(new_account_owner_private_key)) +tb.sign() + +result = tb.broadcast() + +print('result') +print(result) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/account_reputation.md b/_tutorials-python/account_reputation.md index bdb16d39..84b6dd3f 100644 --- a/_tutorials-python/account_reputation.md +++ b/_tutorials-python/account_reputation.md @@ -103,13 +103,36 @@ if sign < 0: You can use this to convert from the raw blockchain value. This is now done internally by libraries like beem. ---- +Final code: + +```python +import pprint +from pick import pick + +# initialize Hive class +from beem import Hive +from beem.account import Account -#### Try it +hive = Hive() -Click the play button below: +title = 'Please choose account: ' +options = ["hiveio","ecency","busy.org","demo"] -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py20accountreputation?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# get index and selected filter name +option, index = pick(options, title) + +# option is printed as reference +pprint.pprint("Selected: " + option) + +user = Account(option, blockchain_instance=hive) + +# print specified account's reputation +pprint.pprint(user.get_reputation()) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/claim_rewards.md b/_tutorials-python/claim_rewards.md index b2df2c41..e4d1a983 100644 --- a/_tutorials-python/claim_rewards.md +++ b/_tutorials-python/claim_rewards.md @@ -150,13 +150,91 @@ print('\t' + str(reward_hive) + '\n' + ) ``` ---- +Final code: + +```python +import pprint +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_posting_key = getpass.getpass('Enter private POSTING key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node +client = Hive(node_url, keys=[wif_posting_key]) + +# get account reward balances +account = Account(account, blockchain_instance=client) + +reward_hive = account['reward_hive_balance'] +reward_hbd = account['reward_hbd_balance'] +reward_vests = account['reward_vesting_balance'] + +print('Reward Balances:' + '\n' + + '\t' + str(reward_hive) + '\n' + + '\t' + str(reward_hbd) + '\n' + + '\t' + str(reward_vests) +) + +if reward_hive.amount + reward_hbd.amount + reward_vests.amount == 0: + print('\n' + 'No rewards to claim') + exit() + +input('\n' + 'Press enter to continue to claim selection') + +# choice of claim +title = 'Please choose claim type: ' +options = ['ALL', 'SELECTED', 'CANCEL'] +# get index and selected claim type +option, index = pick(options, title) -#### Try it +if option == 'CANCEL': + print('\n' + 'Operation cancelled') + exit() + +# commit claim based on selection +if option == 'ALL': + account.claim_reward_balance + print('\n' + 'All reward balances have been claimed. New reward balances are:' + '\n') +else: + claim_hive = float(input('\n' + 'Please enter the amount of HIVE to claim: ') or '0') + claim_hbd = float(input('Please enter the amount of HBD to claim: ') or '0') + claim_vests = float(input('Please enter the amount of VESTS to claim: ') or '0') -Click the play button below: + if claim_hive + claim_hbd + claim_vests == 0: + print('\n' + 'Zero values entered, no claim to submit') + exit() + + if claim_hive > reward_hive or claim_hbd > reward_hbd or claim_vests > reward_vests: + print('\n' + 'Requested claim value higher than available rewards') + exit() + + account.claim_reward_balance(reward_hive=claim_hive, reward_hbd=claim_hbd, reward_vests=claim_vests) + print('\n' + 'Claim has been processed. New reward balances are:' + '\n') + +# get updated account reward balances +input("Press enter for new account balances") + +account.refresh() + +reward_hive = account['reward_hive_balance'] +reward_hbd = account['reward_hbd_balance'] +reward_vests = account['reward_vesting_balance'] -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py23claimrewards?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +print('\t' + str(reward_hive) + '\n' + + '\t' + str(reward_hbd) + '\n' + + '\t' + str(reward_vests) +) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/convert_hbd_to_hive.md b/_tutorials-python/convert_hbd_to_hive.md index aae2d4b3..d89cb8a7 100644 --- a/_tutorials-python/convert_hbd_to_hive.md +++ b/_tutorials-python/convert_hbd_to_hive.md @@ -119,13 +119,53 @@ print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_hive) + '\n' + str( The HIVE balance will not yet have been updated as it takes 3.5 days to settle. The HBD will however show the new balance. ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# get account balance for HIVE and HBD +account = Account(account, blockchain_instance=client) +total_hive = account['balance'] +total_hbd = account['hbd_balance'] -#### Try it +print('CURRENT ACCOUNT BALANCE:' + '\n' + str(total_hive) + '\n' + str(total_hbd) + '\n') + +# get recipient name +convert_amount = float(input('Enter the amount of HBD to convert to HIVE: ') or '0') + +if (convert_amount <= 0): + print("Must be greater than zero.") + exit() + +# parameters: amount, request_id +account.convert(convert_amount) -Click the play button below: +print('\n' + format(convert_amount, '.3f') + ' HBD has been converted to HIVE') + +# get remaining account balance for HIVE and HBD +account.refresh() +total_hive = account['balance'] +total_hbd = account['hbd_balance'] -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py32converthbdtohive?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_hive) + '\n' + str(total_hbd)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/convert_hive_to_hbd.md b/_tutorials-python/convert_hive_to_hbd.md index 30124d2e..bd891fe1 100644 --- a/_tutorials-python/convert_hive_to_hbd.md +++ b/_tutorials-python/convert_hive_to_hbd.md @@ -119,13 +119,54 @@ print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_hbd) + '\n' + str(t The HIVE balance will not yet have been fully updated as it takes 3.5 days for the collateral to settle. The HBD will however show the new balance. ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account -#### Try it +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') -Click the play button below: +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py37converthivetohbd?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# get account balance for HIVE and HBD +account = Account(account, blockchain_instance=client) +total_hbd = account['hbd_balance'] +total_hive = account['balance'] + +print('CURRENT ACCOUNT BALANCE:' + '\n' + str(total_hbd) + '\n' + str(total_hive) + '\n') + +# get recipient name +convert_amount = float(input('Enter the amount of HIVE to convert to HBD: ') or '0') + +if (convert_amount <= 0): + print("Must be greater than zero.") + exit() + +# parameters: amount, request_id +account.collateralized_convert(convert_amount) + +print('\n' + format(convert_amount, '.3f') + ' HIVE has been converted to HBD') + +# get remaining account balance for HBD and HIVE +account.refresh() +total_hbd = account['hbd_balance'] +total_hive = account['balance'] + +print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_hbd) + '\n' + str(total_hive)) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/delegate_power.md b/_tutorials-python/delegate_power.md index 927a8e93..0d26476a 100644 --- a/_tutorials-python/delegate_power.md +++ b/_tutorials-python/delegate_power.md @@ -157,13 +157,91 @@ Note that if the user decides to delegate a specific amount, we capture the amou A confirmation of the transaction is displayed on the UI. ---- +Final code: -#### Try it +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account +from beem.amount import Amount -Click the play button below: +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py27delegatepower?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# check valid user +account = Account(account, blockchain_instance=client) + +balance = account['balance'] +symbol = balance.symbol + +# we need high precision because VESTS +denom = 1e6 +delegated_vests = account['delegated_vesting_shares'] +vesting_shares = account['vesting_shares'] +vesting_symbol = vesting_shares.symbol +to_withdraw_vests = float(account['to_withdraw']) / denom +withdrawn_vests = float(account['withdrawn']) / denom + +dgpo = client.get_dynamic_global_properties() +total_vesting_fund_hive = Amount(dgpo['total_vesting_fund_hive']).amount +total_vesting_shares_mvest = Amount(dgpo['total_vesting_shares']).amount / denom +base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest +available_vests = (vesting_shares.amount - delegated_vests.amount - ((to_withdraw_vests - withdrawn_vests))) +available_base = (available_vests / denom) * base_per_mvest + +# display active delegations (refer to tutorial #29_get_delegations_by_user) +delegations = account.get_vesting_delegations() +if len(delegations) == 0: + print('No active delegations') +else: + print('Current delegations:') + for delegation in delegations: + delegated_vests = float(delegation['vesting_shares']['amount']) / denom + delegated_base = (delegated_vests / denom) * base_per_mvest + print('\t' + delegation['delegatee'] + ': ' + format(delegated_base, '.3f') + ' ' + symbol) + +print('\n' + 'Available ' + symbol + ' Power: ' + format(available_base, '.3f') + ' ' + symbol) + +input('Press enter to continue' + '\n') + +# choice of action +title = ('Please choose action') +options = ['DELEGATE POWER', 'UN-DELEGATE POWER', 'CANCEL'] +# get index and selected permission choice +option, index = pick(options, title) + +if (option == 'CANCEL'): + print('operation cancelled') + exit() + +# get account to authorise and check if valid +delegatee = input('Please enter the account name to ADD / REMOVE delegation: ') +delegatee = Account(delegatee, blockchain_instance=client) + +if (option == 'DELEGATE POWER'): + amount = float(input('Please enter the amount of ' + symbol + ' you would like to delegate: ') or '0') + amount_vests = (amount * denom) / base_per_mvest + + print(format(amount, '.3f') + ' ' + symbol + ' (' + format(amount_vests, '.6f') + ' ' + vesting_symbol + ') will be delegated to ' + delegatee.name) +else: + amount_vests = 0 + print('Removing delegated VESTS from ' + delegatee.name) + +account.delegate_vesting_shares(delegatee.name, amount_vests) + +print('Success.') + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/edit_content_patching.md b/_tutorials-python/edit_content_patching.md index 02a45a19..a3539c4d 100644 --- a/_tutorials-python/edit_content_patching.md +++ b/_tutorials-python/edit_content_patching.md @@ -152,13 +152,95 @@ print('\n' + 'Content of the post has been successfully updated: ' + str(broadca A simple confirmation is displayed on the screen for a successful commit. ---- +Final code: + +```python +import beem +import getpass +from beem import Hive +from beem.account import Account +from beem.comment import Comment +from beem.transactionbuilder import TransactionBuilder +from beembase import operations +from diff_match_patch import diff_match_patch + +#capture user information +post_author = input('Please enter the AUTHOR of the post you want to edit: ') + +#connect node +# client = Hive('https://testnet.openhive.network') # Public Testnet +client = Hive('http://127.0.0.1:8090') # Local Testnet + +#check valid post_author +try: + userinfo = Account(post_author, blockchain_instance=client) +except: + print('Oops. Looks like user ' + post_author + ' doesn\'t exist on this chain!') + exit() + +post_permlink = input('Please enter the PERMLINK of the post you want to edit: ') + +#get details of selected post +try: + details = beem.comment.Comment(post_author + '/' + post_permlink, blockchain_instance=client) +except: + print('Oops. Looks like ' + post_author + '/' + post_permlink + ' doesn\'t exist on this chain!') + exit() + +print('\n' + 'Title: ' + details.title) +o_body = details.body +print('Body:' + '\n' + o_body + '\n') + +n_body = input('Please enter new post content:' + '\n') + +#initialise the diff match patch module +dmp = diff_match_patch() -#### Try it +#Check for null input +if (n_body == '') : + print('\n' + 'No new post body supplied. Operation aborted') + exit() +else : + # Check for equality + if (o_body == n_body) : + print('\n' + 'No changes made to post body. Operation aborted') + exit() -Click the play button below: +#check for differences in the text field +diff = dmp.diff_main(o_body, n_body) +#Reduce the number of edits by eliminating semantically trivial equalities. +dmp.diff_cleanupSemantic(diff) +#create patch +patch = dmp.patch_make(o_body, diff) +#create new text based on patch +patch_body = dmp.patch_toText(patch) +#check patch length +if (len(patch_body) < len(o_body)) : + new_body = patch_body +else : + new_body = n_body -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py12editcontentpatching?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +tx = TransactionBuilder(blockchain_instance=client) +tx.appendOps(operations.Comment(**{ + "parent_author": details.parent_author, + "parent_permlink": details.parent_permlink, + "author": details.author, + "permlink": details.permlink, + "title": details.title, + "body": new_body, + "json_metadata": details.json_metadata +})) + +wif_posting_key = getpass.getpass('Posting Key: ') +tx.appendWif(wif_posting_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) + +print('\n' + 'Content of the post has been successfully updated: ' + str(broadcast_tx)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/follow_a_user.md b/_tutorials-python/follow_a_user.md index 7104f17d..93a0254d 100644 --- a/_tutorials-python/follow_a_user.md +++ b/_tutorials-python/follow_a_user.md @@ -155,13 +155,92 @@ print(option + ' ' + author.name + ": " + str(broadcast_tx)) A simple confirmation of the chosen action is printed on the screen. ---- +Final code: + +```python +import getpass +import json +from pick import pick +import beem +from beem.account import Account +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Custom_json + +# capture user information +account = input('Please enter your username: ') + +# capture variables +author = input('Author to follow: ') + +if author == account: + print("Do you follow yourself?") + exit() + +# connect node and private posting key, demo account being used: cdemo, posting key: 5JEZ1EiUjFKfsKP32b15Y7jybjvHQPhnvCYZ9BW62H1LDUnMvHz +# hive = beem.Hive('https://testnet.openhive.network') # Public Testnet +hive = beem.Hive('http://127.0.0.1:8090') # Local Testnet + +author = Account(author, blockchain_instance=hive) +account = Account(account, blockchain_instance=hive) +already_following = False + +if author: + # check current follow status of specified author + following = account.get_following() + + if len(following) > 0 and author.name in following: + title = "Author is already being followed, please choose action" + already_following = True + else: + title = "Author has not yet been followed, please choose action" +else: + print('Author does not exist') + exit() + +# get index and selected action +options = ['Follow', 'Unfollow', 'Exit'] +option, index = pick(options, title) +tx = TransactionBuilder(blockchain_instance=hive) -#### Try it +if option == 'Follow' : + if not already_following: + tx.appendOps(Custom_json(**{ + 'required_auths': [], + 'required_posting_auths': [account.name], + 'id': 'follow', + 'json': json.dumps(['follow', { + 'follower': account.name, + 'following': author.name, + 'what': ['blog'] # set what to follow + }]) + })) +elif option == 'Unfollow' : + if already_following: + tx.appendOps(Custom_json(**{ + 'required_auths': [], + 'required_posting_auths': [account.name], + 'id': 'follow', + 'json': json.dumps(['follow', { + 'follower': account.name, + 'following': author.name, + 'what': [] # clear previous follow + }]) + })) + +if len(tx.ops) == 0: + print('Action Cancelled') + exit() + +wif_posting_key = getpass.getpass('Posting Key: ') +tx.appendWif(wif_posting_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) -Click the play button below: +print(option + ' ' + author.name + ": " + str(broadcast_tx)) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py18followauser?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_account_comments.md b/_tutorials-python/get_account_comments.md index 08381b02..df15a92f 100644 --- a/_tutorials-python/get_account_comments.md +++ b/_tutorials-python/get_account_comments.md @@ -104,13 +104,46 @@ The example of result returned from the service is a `JSON` object with the foll From this result you have access to everything associated to the [comments](https://beem.readthedocs.io/en/latest/beem.comment.html#beem.comment.Comment) of account including content of comment, timestamp, active_votes, etc., so that you can use in further development of your applications with Python. ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions + +h = Hive() +q = Query(limit=2, tag="") +d = Discussions() + +#author list from created post list to randomize account list +posts = d.get_discussions('created', q, limit=2) + +title = 'Please choose account: ' +options = [] +#accounts list +for post in posts: + options.append(post["author"]) + +# get index and selected account name +option, index = pick(options, title) + +# 5 comments from selected author +q = Query(limit=5, start_author=option) + +# get comments of selected account +comments = d.get_discussions('comments', q, limit=5) + +# print comment details for selected account +for comment in comments: + pprint.pprint(comment) +pprint.pprint("Selected: " + option) -#### Try it -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py09getaccountcomments?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/get_account_replies.md b/_tutorials-python/get_account_replies.md index 56d5dd69..9d123ce1 100644 --- a/_tutorials-python/get_account_replies.md +++ b/_tutorials-python/get_account_replies.md @@ -97,13 +97,56 @@ for reply in replies: pprint.pprint(reply.body) ``` ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions +from beem.account import Account + +h = Hive() +q = Query(limit=2, tag="") +d = Discussions() + +#post list for selected query +#we are merely using this to display the most recent posters +#the 'author' can easily be changed to any value within the 'reply_history' function -#### Try it +posts = d.get_discussions('created', q, limit=2) -Click the play button below: +title = 'Please choose author: ' +options = [] +#posts list +for post in posts: + options.append(post["author"]) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py08getaccountreplies?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# get index and selected filter name +option, index = pick(options, title) + +# option is printed as reference +pprint.pprint("Selected: " + option) + +# in this tutorial we are showing usage of reply_history of post where the author is known + +# allocate variables +_author = Account(option) +_limit = 1 + +# get replies for specific author +replies = _author.reply_history(limit=_limit) + +# print specified number of comments + +for reply in replies: + pprint.pprint(reply.body) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_delegations_by_user.md b/_tutorials-python/get_delegations_by_user.md index e1dfffe5..daa13501 100644 --- a/_tutorials-python/get_delegations_by_user.md +++ b/_tutorials-python/get_delegations_by_user.md @@ -105,13 +105,59 @@ For both the queries the starting points were defined in such a way as to includ Note that we output the delegated amounts as HIVE Power, in keeping with the principle of only interacting with the end user in terms of HIVE Power, which is the recommended best practice. ---- +Final code: + +```python +from pick import pick +from beem import Hive +from beem.account import Account +from beem.amount import Amount + +client = Hive() + +# capture username +account = input('Username: ') +account = Account(account) + +balance = account['balance'] +symbol = balance.symbol + +# we need high precision because VESTS +denom = 1e6 +dgpo = client.get_dynamic_global_properties() +total_vesting_fund_hive = Amount(dgpo['total_vesting_fund_hive']).amount +total_vesting_shares_mvest = Amount(dgpo['total_vesting_shares']).amount / denom +base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest + +# capture list limit +limit = input('Max number of vesting delegations to display: ') or '10' -#### Try it +# list type +title = 'Please choose the type of list: ' +options = ['Active Vesting Delegations', 'Expiring Vesting Delegations'] -Click the play button below: +# get index and selected list name +option, index = pick(options, title) +print('\n' + 'List of ' + option + ': ' + '\n') -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py29getdelegationsbyuser?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +if option=='Active Vesting Delegations' : + delegations = account.get_vesting_delegations(limit=limit) +else: + delegations = account.get_expiring_vesting_delegations("2018-01-01T00:00:00", limit=limit) + +if len(delegations) == 0: + print('No ' + option) + exit + +for delegation in delegations: + delegated_vests = float(delegation['vesting_shares']['amount']) / denom + delegated_base = (delegated_vests / denom) * base_per_mvest + print('\t' + delegation['delegatee'] + ': ' + format(delegated_base, '.3f') + ' ' + symbol) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_follower_and_following_list.md b/_tutorials-python/get_follower_and_following_list.md index de3293e1..fa587d1c 100644 --- a/_tutorials-python/get_follower_and_following_list.md +++ b/_tutorials-python/get_follower_and_following_list.md @@ -106,13 +106,53 @@ print(*follows, sep='\n') This is a fairly simple example of how to use these functions but we encourage you to play around with the parameters to gain further understanding of possible results. ---- +Final code: + +```python +from pick import pick +# initialize Hive class +from beem import Hive +from beem.account import Account + +hive = Hive() + +# capture username +account = input("Username: ") +account = Account(account, blockchain_instance=hive) + +# capture list limit +limit = input("Max number of followers(ing) to display: ") +limit = int(limit) + +# list type +title = 'Please choose the type of list: ' +options = ['Follower', 'Following'] + +# get index and selected list name +option, index = pick(options, title) +print("List of " + option) + +# create empty list +follows = [] + +# parameters for get_followers function: +# start_follower, follow_type, limit +if option=="Follower" : + follows = account.get_followers()[:limit] +else: + follows = account.get_following()[:limit] -#### Try it +# check if follower(ing) list is empty +if len(follows) == 0: + print("No " + option + " information available") + exit() + +print(*follows, sep='\n') -Click the play button below: -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py19getfollowerandfollowinglist?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_post_comments.md b/_tutorials-python/get_post_comments.md index 0a8b5ba7..88131ae0 100644 --- a/_tutorials-python/get_post_comments.md +++ b/_tutorials-python/get_post_comments.md @@ -110,13 +110,47 @@ The example of results returned from the service: From this result you have access to everything associated to the replies including content of reply, author, timestamp, etc., so that you can be use in further development of applications with Python. ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions +from beem.comment import Comment + +h = Hive() +q = Query(limit=2, tag="") +d = Discussions() + +#post list for selected query +posts = d.get_discussions('hot', q, limit=2) + +title = 'Please choose post: ' +options = [] -#### Try it +#posts list +for post in posts: + options.append(post["author"]+'/'+post["permlink"]) + +# get index and selected filter name +option, index = pick(options, title) + +details = Comment(option) -Click the play button below: +# get replies for given post +replies = details.get_all_replies() -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py07getpostcomments?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# print post details for selected post +pprint.pprint(replies) +pprint.pprint("Selected: " + option) +pprint.pprint("Number of replies: " + str(len(replies))) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_post_details.md b/_tutorials-python/get_post_details.md index fcc1c16f..b7813d60 100644 --- a/_tutorials-python/get_post_details.md +++ b/_tutorials-python/get_post_details.md @@ -106,13 +106,46 @@ From this result you have access to everything associated to the post including {% include structures/comment.html %} ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions +from beem.comment import Comment + +h = Hive() + +q = Query(limit=2, tag="") +d = Discussions() + +#post list for selected query +posts = d.get_discussions('created', q, limit=2) + +title = 'Please choose post: ' +options = [] + +#posts list +for post in posts: + options.append(post["author"] + '/' + post["permlink"]) + +# get index and selected filter name +option, index = pick(options, title) -#### Try it +details = Comment(option) -Click the play button below: +# print post body for selected post +# Also see: https://beem.readthedocs.io/en/latest/beem.comment.html#beem.comment.Comment +pprint.pprint('Depth: ' + str(details.depth)) +pprint.pprint('Author: ' + details.author) +pprint.pprint('Category: ' + details.category) +pprint.pprint('Body: ' + details.body) + +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py05getpostdetails?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/get_posts.md b/_tutorials-python/get_posts.md index 7d0bcf64..5a3fc712 100644 --- a/_tutorials-python/get_posts.md +++ b/_tutorials-python/get_posts.md @@ -95,13 +95,46 @@ The example of result returned from the service as objects: From this result you have access to everything associated to the posts including additional metadata which is a `JSON` string (that must be decoded to use), `active_votes` info, post title, body, etc. details that can be used in further development of application with Python. ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions + +h = Hive() + +title = 'Please choose filter: ' +#filters list +options = ['trending', 'hot', 'active', 'created', 'promoted'] +# get index and selected filter name +option, index = pick(options, title) + +q = Query(limit=2, tag="") +d = Discussions() +count = 0 + +#post list for selected query +posts = { + 0: d.get_discussions('trending', q, limit=2), + 1: d.get_discussions('hot', q, limit=2), + 2: d.get_discussions('active', q, limit=2), + 3: d.get_discussions('created', q, limit=2), + 4: d.get_discussions('promoted', q, limit=2) +} -#### Try it +# print post list for selected filter +for p in posts[index]: + print(("%d. " % (count + 1)) + str(p)) + count += 1 -Click the play button below: +pprint.pprint("Selected: " + option) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py04getposts?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/get_voters_list_on_post.md b/_tutorials-python/get_voters_list_on_post.md index 7157930c..964a2f6f 100644 --- a/_tutorials-python/get_voters_list_on_post.md +++ b/_tutorials-python/get_voters_list_on_post.md @@ -101,13 +101,43 @@ The example of result returned from the service is a table with the following ou From this result you have access to everything associated to the voter including reputation of voter, timestamp, voter's account name, percent and weight of vote, rshares reward shares values that you can be use in further development of applications with Python. ---- +Final code: + +```python +import pprint +from pick import pick +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions +from beem.vote import ActiveVotes + +h = Hive() +q = {"limit": 5, "tag": "", "before_date": None} +d = Discussions() + +#post list for selected query +posts = d.get_discussions('hot', q, limit=5) + +title = 'Please choose post: ' +options = [] -#### Try it +#posts list +for post in posts: + options.append(post["author"] + '/' + post["permlink"]) -Click the play button below: +# get index and selected filter name +option, index = pick(options, title) + +voters = ActiveVotes(option) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py06getvoterslistonpost?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# print voters list for selected post +voters.printAsTable() +pprint.pprint("Selected: " + option) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/getting_started.md b/_tutorials-python/getting_started.md index ecd34549..52ba7fc4 100644 --- a/_tutorials-python/getting_started.md +++ b/_tutorials-python/getting_started.md @@ -9,10 +9,13 @@ Full, runnable src of [all python tutorials](https://gitlab.syncad.com/hive/devp The library was designed to allow Python developers to easily access the network as well as build utilities and applications. -Currently beem documentation is generated in the standard [pydoc format](https://beem.readthedocs.io/en/latest/). +Currently, beem documentation is generated in the standard [pydoc format](https://beem.readthedocs.io/en/latest/). Repository: [https://github.com/holgern/beem](https://github.com/holgern/beem). +**<a href="{{ '/quickstart/#quickstart-choose-library' | relative_url }}">Alternative Python libraries</a>** + + --- #### Dev requirements diff --git a/_tutorials-python/grant_active_permission.md b/_tutorials-python/grant_active_permission.md index d2052e06..6dee5fb3 100644 --- a/_tutorials-python/grant_active_permission.md +++ b/_tutorials-python/grant_active_permission.md @@ -124,13 +124,66 @@ else: print('active permission for ' + foreign.name + ' has been removed') ``` ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect with active key +client = Hive(node_url, keys=[wif_active_key]) + +# check valid user +account = Account(account, blockchain_instance=client) + +print('Current active authorizations: ' + str(account['active']['account_auths'])) + +# get account to authorise and check if valid +foreign = input('Please enter the account name for ACTIVE authorization: ') +if (foreign == account.name): + print('Cannot allow or disallow active permission to your own account') + exit() + +foreign = Account(foreign, blockchain_instance=client) + +# check if foreign account already has active auth +title = '' + +for auth in account['active']['account_auths']: + if (auth[0] == foreign.name): + title = (foreign.name + ' already has active permission. Please choose option from below list') + options = ['DISALLOW', 'CANCEL'] + break + +if (title == ''): + title = (foreign.name + ' does not yet active permission. Please choose option from below list') + options = ['ALLOW', 'CANCEL'] -#### Try it +option, index = pick(options, title) + +if (option == 'CANCEL'): + print('operation cancelled') + exit() + +if (option == 'ALLOW'): + account.allow(foreign=foreign.name, weight=1, permission='active', threshold=1) + print(foreign.name + ' has been granted active permission') +else: + account.disallow(foreign=foreign.name, permission='active', threshold=1) + print('active permission for ' + foreign.name + ' has been removed') -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py31grantactivepermission?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/grant_posting_permission.md b/_tutorials-python/grant_posting_permission.md index c7843759..2379f794 100644 --- a/_tutorials-python/grant_posting_permission.md +++ b/_tutorials-python/grant_posting_permission.md @@ -116,13 +116,66 @@ else: print('posting permission for ' + foreign.name + ' has been removed') ``` ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect with active key +client = Hive(node_url, keys=[wif_active_key]) + +# check valid user +account = Account(account, blockchain_instance=client) + +print('Current posting authorizations: ' + str(account['posting']['account_auths'])) + +# get account to authorise and check if valid +foreign = input('Please enter the account name for POSTING authorization: ') +if (foreign == account.name): + print('Cannot allow or disallow posting permission to your own account') + exit() + +foreign = Account(foreign, blockchain_instance=client) + +# check if foreign account already has posting auth +title = '' + +for auth in account['posting']['account_auths']: + if (auth[0] == foreign.name): + title = (foreign.name + ' already has posting permission. Please choose option from below list') + options = ['DISALLOW', 'CANCEL'] + break + +if (title == ''): + title = (foreign.name + ' does not yet posting permission. Please choose option from below list') + options = ['ALLOW', 'CANCEL'] -#### Try it +option, index = pick(options, title) + +if (option == 'CANCEL'): + print('operation cancelled') + exit() + +if (option == 'ALLOW'): + account.allow(foreign=foreign.name, weight=1, permission='posting', threshold=1) + print(foreign.name + ' has been granted posting permission') +else: + account.disallow(foreign=foreign.name, permission='posting', threshold=1) + print('posting permission for ' + foreign.name + ' has been removed') -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py30grantpostingpermission?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/password_key_change.md b/_tutorials-python/password_key_change.md index 3a27945b..1101ce80 100644 --- a/_tutorials-python/password_key_change.md +++ b/_tutorials-python/password_key_change.md @@ -139,13 +139,83 @@ Assert Exception:_db.head_block_time() - account_auth.last_owner_update > HIVE_O You will need to wait at least an hour before attempting this again. ---- +Final code: + +```python +import getpass +import json +from beem import Hive +from beem.account import Account +from beemgraphenebase.account import PasswordKey, PrivateKey +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Account_update + +account = input('Account: ') +old_password = getpass.getpass('Current password: ') +new_password = getpass.getpass('New password: ') + +if getpass.getpass('Confirm New password: ') != new_password: + print('New password did not confirm.') + exit() + +wif_old_owner_key = str( + PasswordKey(account, old_password, "owner").get_private_key() +) + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +client = Hive(node_url, keys=[wif_old_owner_key]) + +account = Account(account, blockchain_instance=client) +new_public_keys = {} + +for role in ["owner", "active", "posting", "memo"]: + private_key = PasswordKey(account.name, new_password, role).get_private_key() + new_public_keys[role] = str(private_key.pubkey) + +new_data = { + "account": account.name, + "json_metadata": json.dumps(account.json_metadata), + "owner": { + "key_auths": [ + [new_public_keys["owner"], 1] + ], + "account_auths": account['owner']['account_auths'], + "weight_threshold": 1 + }, + "active": { + "key_auths": [ + [new_public_keys["active"], 1] + ], + "account_auths": account['active']['account_auths'], + "weight_threshold": 1 + }, + "posting": { + "key_auths": [ + [new_public_keys["posting"], 1] + ], + "account_auths": account['posting']['account_auths'], + "weight_threshold": 1 + }, + "memo_key": new_public_keys["memo"] +} + +print("New data:") +print(new_data) + +tx = TransactionBuilder(blockchain_instance=client) +tx.appendOps(Account_update(**new_data)) -#### Try it +tx.appendWif(wif_old_owner_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) -Click the play button below: +print("Account updated successfully: " + str(broadcast_tx)) + +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py34passwordkeychange?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/power_down.md b/_tutorials-python/power_down.md index 738924ad..d3ff4c22 100644 --- a/_tutorials-python/power_down.md +++ b/_tutorials-python/power_down.md @@ -152,13 +152,87 @@ print('Insufficient funds available') The result is displayed on the console/terminal. ---- +Final code: + +```python +import pprint +from pick import pick +import getpass +from beem import Hive +from beem.account import Account +from beem.amount import Amount + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# get account balance for vesting shares +account = Account(account, blockchain_instance=client) +balance = account['balance'] +symbol = balance.symbol + +# we need high precision because VESTS +denom = 1e6 +delegated_vests = account['delegated_vesting_shares'] +vesting_shares = account['vesting_shares'] +vesting_symbol = vesting_shares.symbol +to_withdraw_vests = float(account['to_withdraw']) / denom +withdrawn_vests = float(account['withdrawn']) / denom + +dgpo = client.get_dynamic_global_properties() +total_vesting_fund_hive = Amount(dgpo['total_vesting_fund_hive']).amount +total_vesting_shares_mvest = Amount(dgpo['total_vesting_shares']).amount / denom +base_per_mvest = total_vesting_fund_hive / total_vesting_shares_mvest +available_vests = (vesting_shares.amount - delegated_vests.amount - ((to_withdraw_vests - withdrawn_vests))) +available_base = (available_vests / denom) * base_per_mvest +powering_down = ((to_withdraw_vests - withdrawn_vests) / denom) * base_per_mvest + +print(symbol + ' Power currently powering down: ' + format(powering_down, '.3f') + ' ' + symbol + + '\n' + 'Available ' + symbol + ' Power: ' + format(available_base, '.3f') + ' ' + symbol) + +input('\n' + 'Press enter to continue' + '\n') -#### Try it +# choice of transfer +title = 'Please choose an option: ' +options = ['Power down ALL', 'Power down PORTION', 'Cancel Transaction'] +# get index and selected transfer type +option, index = pick(options, title) -Click the play button below: +# parameters: amount, account +if (option == 'Cancel Transaction'): + print('transaction cancelled') + exit() -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py25powerdown?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +if (option == 'Power down ALL'): + if (available_vests == 0): + print('No change to withdraw amount') + exit() + amount_vests = to_withdraw_vests + available_vests + amount = (amount_vests / denom) * base_per_mvest +else: + amount = float(input('Please enter the amount of ' + symbol + ' you would like to power down: ') or '0') + amount_vests = (amount * denom) / base_per_mvest + +if (amount_vests <= (to_withdraw_vests + available_vests)): + account.withdraw_vesting(amount_vests) + print(format(amount, '.3f') + ' ' + symbol + ' (' + format(amount_vests, '.6f') + ' ' + vesting_symbol + ') now powering down') + exit() + +if (amount_vests == to_withdraw_vests): + print('No change to withdraw amount') + exit() + +print('Insufficient funds available') + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/power_up_hive.md b/_tutorials-python/power_up_hive.md index 56c3e0b6..8daffe6a 100644 --- a/_tutorials-python/power_up_hive.md +++ b/_tutorials-python/power_up_hive.md @@ -131,13 +131,71 @@ balance = account['balance'] print('New balance: ' + str(balance)) ``` ---- +Final code: + +```python +import pprint +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# check valid user and get account balance +account = Account(account, blockchain_instance=client) +balance = account['balance'] +symbol = balance.symbol + +print('Available balance: ' + str(balance) + '\n') + +input('Press any key to continue') + +# choice of account +title = 'Please choose an option for an account to power up: ' +options = ['SELF', 'OTHER'] +# get index and selected transfer type +option, index = pick(options, title) + +if (option == 'OTHER') : + # account to power up to + to_account = input('Please enter the ACCOUNT to where the ' + symbol + ' will be powered up: ') + to_account = Account(to_account, blockchain_instance=client) +else : + print('\n' + 'Power up ' + symbol + ' to own account' + '\n') + to_account = account -#### Try it +# amount to power up +amount = float(input('Please enter the amount of ' + symbol + ' to power up: ') or '0') -Click the play button below: +# parameters: amount, to, account +if (amount == 0) : + print('\n' + 'No ' + symbol + ' entered for powering up') + exit() -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py24poweruphive?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +if (amount > balance) : + print('\n' + 'Insufficient funds available') + exit() + +account.transfer_to_vesting(amount, to_account.name) +print('\n' + str(amount) + ' ' + symbol + ' has been powered up successfully to ' + to_account.name) + +# get new account balance +account.refresh() +balance = account['balance'] +print('New balance: ' + str(balance)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/rcdemo.md b/_tutorials-python/rcdemo.md index ed722489..fdfd9e6e 100644 --- a/_tutorials-python/rcdemo.md +++ b/_tutorials-python/rcdemo.md @@ -130,13 +130,705 @@ convenience of asking `hived` to report these values. As you can see, integrating support for the RC system into a Hive client library involves a number of architectural and technical decisions. ---- - -#### Try it +Final code: + +```python +#!/usr/bin/env python3 + +import collections + +class CountOperationVisitor(object): + + def __init__(self, size_info, exec_info): + self.market_op_count = 0 + self.new_account_op_count = 0 + self.state_bytes_count = 0 + self.execution_time_count = 0 + self.size_info = size_info + self.exec_info = exec_info + + def get_authority_byte_count( self, auth ): + return (self.size_info.authority_base_size + + self.size_info.authority_account_member_size * len(auth["account_auths"]) + + self.size_info.authority_key_member_size * len(auth["key_auths"]) + ) + + def visit_account_create_operation( self, op ): + self.state_bytes_count += ( + self.size_info.account_object_base_size + + self.size_info.account_authority_object_base_size + + self.get_authority_byte_count( op["owner"] ) + + self.get_authority_byte_count( op["active"] ) + + self.get_authority_byte_count( op["posting"] ) + ) + self.execution_time_count += self.exec_info.account_create_operation_exec_time + + def visit_account_create_with_delegation_operation( self, op ): + self.state_bytes_count += ( + self.size_info.account_object_base_size + + self.size_info.account_authority_object_base_size + + self.get_authority_byte_count( op["owner"] ) + + self.get_authority_byte_count( op["active"] ) + + self.get_authority_byte_count( op["posting"] ) + + self.size_info.vesting_delegation_object_base_size + ) + self.execution_time_count += self.exec_info.account_create_with_delegation_operation_exec_time + + def visit_account_witness_vote_operation( self, op ): + self.state_bytes_count += self.size_info.witness_vote_object_base_size + self.execution_time_count += self.exec_info.account_witness_vote_operation_exec_time + + def visit_comment_operation( self, op ): + self.state_bytes_count += ( + self.size_info.comment_object_base_size + + self.size_info.comment_object_permlink_char_size * len(op["permlink"].encode("utf8")) + + self.size_info.comment_object_parent_permlink_char_size * len(op["parent_permlink"].encode("utf8")) + ) + self.execution_time_count += self.exec_info.comment_operation_exec_time + + def visit_comment_payout_beneficiaries( self, bens ): + self.state_bytes_count += self.size_info.comment_object_beneficiaries_member_size * len(bens["beneficiaries"]) + + def visit_comment_options_operation( self, op ): + for e in op["extensions"]: + getattr(self, "visit_"+e["type"])(e["value"]) + self.execution_time_count += self.exec_info.comment_options_operation_exec_time + + def visit_convert_operation( self, op ): + self.state_bytes_count += self.size_info.convert_request_object_base_size + self.execution_time_count += self.exec_info.convert_operation_exec_time + + def visit_create_claimed_account_operation( self, op ): + self.state_bytes_count += ( + self.size_info.account_object_base_size + + self.size_info.account_authority_object_base_size + + self.get_authority_byte_count( op["owner"] ) + + self.get_authority_byte_count( op["active"] ) + + self.get_authority_byte_count( op["posting"] ) + ) + self.execution_time_count += self.exec_info.create_claimed_account_operation_exec_time + + def visit_decline_voting_rights_operation( self, op ): + self.state_bytes_count += self.size_info.decline_voting_rights_request_object_base_size + self.execution_time_count += self.exec_info.decline_voting_rights_operation_exec_time + + def visit_delegate_vesting_shares_operation( self, op ): + self.state_bytes_count += max( + self.size_info.vesting_delegation_object_base_size, + self.size_info.vesting_delegation_expiration_object_base_size + ) + self.execution_time_count += self.exec_info.delegate_vesting_shares_operation_exec_time + + def visit_escrow_transfer_operation( self, op ): + self.state_bytes_count += self.size_info.escrow_object_base_size + self.execution_time_count += self.exec_info.escrow_transfer_operation_exec_time + + def visit_limit_order_create_operation( self, op ): + self.state_bytes_count += 0 if op["fill_or_kill"] else self.size_info.limit_order_object_base_size + self.execution_time_count += self.exec_info.limit_order_create_operation_exec_time + self.market_op_count += 1 + + def visit_limit_order_create2_operation( self, op ): + self.state_bytes_count += 0 if op["fill_or_kill"] else self.size_info.limit_order_object_base_size + self.execution_time_count += self.exec_info.limit_order_create2_operation_exec_time + self.market_op_count += 1 + + def visit_request_account_recovery_operation( self, op ): + self.state_bytes_count += self.size_info.account_recovery_request_object_base_size + self.execution_time_count += self.exec_info.request_account_recovery_operation_exec_time + + def visit_set_withdraw_vesting_route_operation( self, op ): + self.state_bytes_count += self.size_info.withdraw_vesting_route_object_base_size + self.execution_time_count += self.exec_info.set_withdraw_vesting_route_operation_exec_time + + def visit_vote_operation( self, op ): + self.state_bytes_count += self.size_info.comment_vote_object_base_size + self.execution_time_count += self.exec_info.vote_operation_exec_time + + def visit_witness_update_operation( self, op ): + self.state_bytes_count += ( + self.size_info.witness_object_base_size + + self.size_info.witness_object_url_char_size * len(op["url"].encode("utf8")) + ) + self.execution_time_count += self.exec_info.witness_update_operation_exec_time + + def visit_transfer_operation( self, op ): + self.execution_time_count += self.exec_info.transfer_operation_exec_time + self.market_op_count += 1 + + def visit_transfer_to_vesting_operation( self, op ): + self.execution_time_count += self.exec_info.transfer_to_vesting_operation_exec_time + self.market_op_count += 1 + + def visit_transfer_to_savings_operation( self, op ): + self.execution_time_count += self.exec_info.transfer_to_savings_operation_exec_time + + def visit_transfer_from_savings_operation( self, op ): + self.state_bytes_count += self.size_info.savings_withdraw_object_byte_size + self.execution_time_count += self.exec_info.transfer_from_savings_operation_exec_time + + def visit_claim_reward_balance_operation( self, op ): + self.execution_time_count += self.exec_info.claim_reward_balance_operation_exec_time + + def visit_withdraw_vesting_operation( self, op ): + self.execution_time_count += self.exec_info.withdraw_vesting_operation_exec_time + + def visit_account_update_operation( self, op ): + self.execution_time_count += self.exec_info.account_update_operation_exec_time + + def visit_account_witness_proxy_operation( self, op ): + self.execution_time_count += self.exec_info.account_witness_proxy_operation_exec_time + + def visit_cancel_transfer_from_savings_operation( self, op ): + self.execution_time_count += self.exec_info.cancel_transfer_from_savings_operation_exec_time + + def visit_change_recovery_account_operation( self, op ): + self.execution_time_count += self.exec_info.change_recovery_account_operation_exec_time + + def visit_claim_account_operation( self, op ): + self.execution_time_count += self.exec_info.claim_account_operation_exec_time + + if int(op["fee"]["amount"]) == 0: + self.new_account_op_count += 1 + + def visit_custom_operation( self, op ): + self.execution_time_count += self.exec_info.custom_operation_exec_time + + def visit_custom_json_operation( self, op ): + self.execution_time_count += self.exec_info.custom_json_operation_exec_time + + def visit_custom_binary_operation( self, op ): + self.execution_time_count += self.exec_info.custom_binary_operation_exec_time + + def visit_delete_comment_operation( self, op ): + self.execution_time_count += self.exec_info.delete_comment_operation_exec_time + + def visit_escrow_approve_operation( self, op ): + self.execution_time_count += self.exec_info.escrow_approve_operation_exec_time + + def visit_escrow_dispute_operation( self, op ): + self.execution_time_count += self.exec_info.escrow_dispute_operation_exec_time + + def visit_escrow_release_operation( self, op ): + self.execution_time_count += self.exec_info.escrow_release_operation_exec_time + + def visit_feed_publish_operation( self, op ): + self.execution_time_count += self.exec_info.feed_publish_operation_exec_time + + def visit_limit_order_cancel_operation( self, op ): + self.execution_time_count += self.exec_info.limit_order_cancel_operation_exec_time + + def visit_witness_set_properties_operation( self, op ): + self.execution_time_count += self.exec_info.witness_set_properties_operation_exec_time + + def visit_claim_reward_balance2_operation( self, op ): + self.execution_time_count += self.exec_info.claim_reward_balance2_operation_exec_time + + def visit_smt_setup_operation( self, op ): + self.execution_time_count += self.exec_info.smt_setup_operation_exec_time + + def visit_smt_cap_reveal_operation( self, op ): + self.execution_time_count += self.exec_info.smt_cap_reveal_operation_exec_time + + def visit_smt_refund_operation( self, op ): + self.execution_time_count += self.exec_info.smt_refund_operation_exec_time + + def visit_smt_setup_emissions_operation( self, op ): + self.execution_time_count += self.exec_info.smt_setup_emissions_operation_exec_time + + def visit_smt_set_setup_parameters_operation( self, op ): + self.execution_time_count += self.exec_info.smt_set_setup_parameters_operation_exec_time + + def visit_smt_set_runtime_parameters_operation( self, op ): + self.execution_time_count += self.exec_info.smt_set_runtime_parameters_operation_exec_time + + def visit_smt_create_operation( self, op ): + self.execution_time_count += self.exec_info.smt_create_operation_exec_time + + def visit_allowed_vote_assets( self, op ): + pass + + def visit_recover_account_operation( self, op ): pass + def visit_pow_operation( self, op ): pass + def visit_pow2_operation( self, op ): pass + def visit_report_over_production_operation( self, op ): pass + def visit_reset_account_operation( self, op ): pass + def visit_set_reset_account_operation( self, op ): pass + + # Virtual ops + def visit_fill_convert_request_operation( self, op ): pass + def visit_author_reward_operation( self, op ): pass + def visit_curation_reward_operation( self, op ): pass + def visit_comment_reward_operation( self, op ): pass + def visit_liquidity_reward_operation( self, op ): pass + def visit_interest_operation( self, op ): pass + def visit_fill_vesting_withdraw_operation( self, op ): pass + def visit_fill_order_operation( self, op ): pass + def visit_shutdown_witness_operation( self, op ): pass + def visit_fill_transfer_from_savings_operation( self, op ): pass + def visit_hardfork_operation( self, op ): pass + def visit_comment_payout_update_operation( self, op ): pass + def visit_return_vesting_delegation_operation( self, op ): pass + def visit_comment_benefactor_reward_operation( self, op ): pass + def visit_producer_reward_operation( self, op ): pass + def visit_clear_null_account_balance_operation( self, op ): pass + +class SizeInfo(object): + pass + +class ExecInfo(object): + pass + +class ResourceCounter(object): + def __init__(self, resource_params): + self.resource_params = resource_params + self.resource_name_to_index = {} + self._size_info = None + self._exec_info = None + + self.resource_names = self.resource_params["resource_names"] + self.STEEM_NUM_RESOURCE_TYPES = len(self.resource_names) + for i, resource_name in enumerate(self.resource_names): + self.resource_name_to_index[ resource_name ] = i + self._size_info = SizeInfo() + for k, v in self.resource_params["size_info"]["resource_state_bytes"].items(): + setattr(self._size_info, k, v) + self._exec_info = ExecInfo() + for k, v in self.resource_params["size_info"]["resource_execution_time"].items(): + setattr(self._exec_info, k, v) + return + + def __call__( self, tx=None, tx_size=-1 ): + if tx_size < 0: + ser = Serializer() + ser.signed_transaction(tx) + tx_size = len(ser.flush()) + result = collections.OrderedDict( + (("resource_count", collections.OrderedDict(( + ("resource_history_bytes", 0), + ("resource_new_accounts", 0), + ("resource_market_bytes", 0), + ("resource_state_bytes", 0), + ("resource_execution_time", 0), + ))),) + ) + + resource_count = result["resource_count"] + resource_count["resource_history_bytes"] += tx_size + + vtor = CountOperationVisitor(self._size_info, self._exec_info) + for op in tx["operations"]: + getattr(vtor, "visit_"+op["type"])(op["value"]) + resource_count["resource_new_accounts"] += vtor.new_account_op_count + + if vtor.market_op_count > 0: + resource_count["resource_market_bytes"] += tx_size + + resource_count["resource_state_bytes"] += ( + self._size_info.transaction_object_base_size + + self._size_info.transaction_object_byte_size * tx_size + + vtor.state_bytes_count ) + + # resource_count["resource_execution_time"] += vtor.execution_time_count + return result + +def compute_rc_cost_of_resource( curve_params=None, current_pool=0, resource_count=0, rc_regen=0 ): + if resource_count <= 0: + if resource_count < 0: + return -compute_rc_cost_of_resource( curve_params, current_pool, -resource_count, rc_regen ) + return 0 + num = rc_regen + num *= int(curve_params["coeff_a"]) + num >>= int(curve_params["shift"]) + num += 1 + num *= resource_count + + denom = int(curve_params["coeff_b"]) + denom += max(current_pool, 0) + + num_denom = num // denom + return num_denom+1 + +def rd_compute_pool_decay( + decay_params, + current_pool, + dt, + ): + if current_pool < 0: + return -rd_compute_pool_decay( decay_params, -current_pool, dt ) + decay_amount = int(decay_params["decay_per_time_unit"]) * dt + decay_amount *= current_pool + decay_amount >>= int(decay_params["decay_per_time_unit_denom_shift"]) + result = decay_amount + return min(result, current_pool) + +class RCModel(object): + def __init__(self, resource_params=None, resource_pool=None, rc_regen=0 ): + self.resource_params = resource_params + self.resource_pool = resource_pool + self.rc_regen = rc_regen + self.count_resources = ResourceCounter(resource_params) + self.resource_names = self.resource_params["resource_names"] + + def get_transaction_rc_cost(self, tx=None, tx_size=-1): + usage = self.count_resources( tx, tx_size ) + + total_cost = 0 + + cost = collections.OrderedDict() + + for resource_name in self.resource_params["resource_names"]: + params = self.resource_params["resource_params"][resource_name] + pool = int(self.resource_pool[resource_name]["pool"]) + + usage["resource_count"][resource_name] *= params["resource_dynamics_params"]["resource_unit"] + cost[resource_name] = compute_rc_cost_of_resource( params["price_curve_params"], pool, usage["resource_count"][resource_name], self.rc_regen) + total_cost += cost[resource_name] + # TODO: Port get_resource_user() + return collections.OrderedDict( (("usage", usage), ("cost", cost)) ) + + def apply_rc_pool_dynamics(self, count): + block_info = collections.OrderedDict(( + ("dt", collections.OrderedDict()), + ("decay", collections.OrderedDict()), + ("budget", collections.OrderedDict()), + ("usage", collections.OrderedDict()), + ("adjustment", collections.OrderedDict()), + ("pool", collections.OrderedDict()), + ("new_pool", collections.OrderedDict()), + )) + + for resource_name in self.resource_params["resource_names"]: + params = self.resource_params["resource_params"][resource_name]["resource_dynamics_params"] + pool = int(self.resource_pool[resource_name]["pool"]) + dt = 1 + + block_info["pool"][resource_name] = pool + block_info["dt"][resource_name] = dt + block_info["budget"][resource_name] = int(params["budget_per_time_unit"]) * dt + block_info["usage"][resource_name] = count[resource_name] * params["resource_unit"] + block_info["decay"][resource_name] = rd_compute_pool_decay( params["decay_params"], pool - block_info["usage"][resource_name], dt ) + + block_info["new_pool"][resource_name] = pool - block_info["decay"][resource_name] + block_info["budget"][resource_name] - block_info["usage"][resource_name] + return block_info + +# These are constants #define in the code +STEEM_RC_REGEN_TIME = 60*60*24*5 +STEEM_BLOCK_INTERVAL = 3 + +# This is the result of rc_api.get_resource_params() +resource_params = { + "resource_names": [ + "resource_history_bytes", + "resource_new_accounts", + "resource_market_bytes", + "resource_state_bytes", + "resource_execution_time" + ], + "resource_params": { + "resource_history_bytes": { + "resource_dynamics_params": { + "resource_unit": 1, + "budget_per_time_unit": 347222, + "pool_eq": "216404314004", + "max_pool_size": "432808628007", + "decay_params": { + "decay_per_time_unit": 3613026481, + "decay_per_time_unit_denom_shift": 51 + }, + "min_decay": 0 + }, + "price_curve_params": { + "coeff_a": "12981647055416481792", + "coeff_b": 1690658703, + "shift": 49 + } + }, + "resource_new_accounts": { + "resource_dynamics_params": { + "resource_unit": 10000, + "budget_per_time_unit": 797, + "pool_eq": 157691079, + "max_pool_size": 157691079, + "decay_params": { + "decay_per_time_unit": 347321, + "decay_per_time_unit_denom_shift": 36 + }, + "min_decay": 0 + }, + "price_curve_params": { + "coeff_a": "16484671763857882971", + "coeff_b": 1231961, + "shift": 51 + } + }, + "resource_market_bytes": { + "resource_dynamics_params": { + "resource_unit": 10, + "budget_per_time_unit": 578704, + "pool_eq": "16030041350", + "max_pool_size": "32060082699", + "decay_params": { + "decay_per_time_unit": 2540365427, + "decay_per_time_unit_denom_shift": 46 + }, + "min_decay": 0 + }, + "price_curve_params": { + "coeff_a": "9231393461629499392", + "coeff_b": 125234698, + "shift": 53 + } + }, + "resource_state_bytes": { + "resource_dynamics_params": { + "resource_unit": 1, + "budget_per_time_unit": 231481481, + "pool_eq": "144269542669147", + "max_pool_size": "288539085338293", + "decay_params": { + "decay_per_time_unit": 3613026481, + "decay_per_time_unit_denom_shift": 51 + }, + "min_decay": 0 + }, + "price_curve_params": { + "coeff_a": "12981647055416481792", + "coeff_b": "1127105802103", + "shift": 49 + } + }, + "resource_execution_time": { + "resource_dynamics_params": { + "resource_unit": 1, + "budget_per_time_unit": 82191781, + "pool_eq": "51225569123068", + "max_pool_size": "102451138246135", + "decay_params": { + "decay_per_time_unit": 3613026481, + "decay_per_time_unit_denom_shift": 51 + }, + "min_decay": 0 + }, + "price_curve_params": { + "coeff_a": "12981647055416481792", + "coeff_b": "400199758774", + "shift": 49 + } + } + }, + "size_info": { + "resource_state_bytes": { + "authority_base_size": 40000, + "authority_account_member_size": 180000, + "authority_key_member_size": 350000, + "account_object_base_size": 4800000, + "account_authority_object_base_size": 400000, + "account_recovery_request_object_base_size": 320000, + "comment_object_base_size": 2010000, + "comment_object_permlink_char_size": 10000, + "comment_object_parent_permlink_char_size": 20000, + "comment_object_beneficiaries_member_size": 180000, + "comment_vote_object_base_size": 470000, + "convert_request_object_base_size": 480000, + "decline_voting_rights_request_object_base_size": 280000, + "escrow_object_base_size": 1190000, + "limit_order_object_base_size": 147440, + "savings_withdraw_object_byte_size": 14656, + "transaction_object_base_size": 6090, + "transaction_object_byte_size": 174, + "vesting_delegation_object_base_size": 600000, + "vesting_delegation_expiration_object_base_size": 440000, + "withdraw_vesting_route_object_base_size": 430000, + "witness_object_base_size": 2660000, + "witness_object_url_char_size": 10000, + "witness_vote_object_base_size": 400000, + "STATE_BYTES_SCALE": 10000 + }, + "resource_execution_time": { + "account_create_operation_exec_time": 57700, + "account_create_with_delegation_operation_exec_time": 57700, + "account_update_operation_exec_time": 14000, + "account_witness_proxy_operation_exec_time": 117000, + "account_witness_vote_operation_exec_time": 23000, + "cancel_transfer_from_savings_operation_exec_time": 11500, + "change_recovery_account_operation_exec_time": 12000, + "claim_account_operation_exec_time": 10000, + "claim_reward_balance_operation_exec_time": 50300, + "comment_operation_exec_time": 114100, + "comment_options_operation_exec_time": 13200, + "convert_operation_exec_time": 15700, + "create_claimed_account_operation_exec_time": 57700, + "custom_operation_exec_time": 228000, + "custom_json_operation_exec_time": 228000, + "custom_binary_operation_exec_time": 228000, + "decline_voting_rights_operation_exec_time": 5300, + "delegate_vesting_shares_operation_exec_time": 19900, + "delete_comment_operation_exec_time": 51100, + "escrow_approve_operation_exec_time": 9900, + "escrow_dispute_operation_exec_time": 11500, + "escrow_release_operation_exec_time": 17200, + "escrow_transfer_operation_exec_time": 19100, + "feed_publish_operation_exec_time": 6200, + "limit_order_cancel_operation_exec_time": 9600, + "limit_order_create_operation_exec_time": 31700, + "limit_order_create2_operation_exec_time": 31700, + "request_account_recovery_operation_exec_time": 54400, + "set_withdraw_vesting_route_operation_exec_time": 17900, + "transfer_from_savings_operation_exec_time": 17500, + "transfer_operation_exec_time": 9600, + "transfer_to_savings_operation_exec_time": 6400, + "transfer_to_vesting_operation_exec_time": 44400, + "vote_operation_exec_time": 26500, + "withdraw_vesting_operation_exec_time": 10400, + "witness_set_properties_operation_exec_time": 9500, + "witness_update_operation_exec_time": 9500 + } + } +} + +# This is the result of get_resource_pool +resource_pool = { + "resource_history_bytes": { + "pool": "199290410749" + }, + "resource_new_accounts": { + "pool": 24573481 + }, + "resource_market_bytes": { + "pool": "15970580402" + }, + "resource_state_bytes": { + "pool": "132161364601521" + }, + "resource_execution_time": { + "pool": "47263115029450" + } +} + +# The value of total_vesting_shares is available from get_dynamic_global_properties() +total_vesting_shares = 397114288290855167 +total_vesting_fund_hive = 196576920519 + +example_transactions = { + "vote" : {"tx" : { + "ref_block_num": 12345, + "ref_block_prefix": 31415926, + "expiration": "2018-09-28T01:02:03", + "operations": [ + { + "type": "vote_operation", + "value": { + "voter": "alice1234567890", + "author": "bobob9876543210", + "permlink": "hello-world-its-bob", + "weight": 10000 + } + } + ], + "extensions": [], + "signatures": [ + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40" + ] + }, "tx_size" : 133}, + + "transfer" : {"tx" : { + "ref_block_num": 12345, + "ref_block_prefix": 31415926, + "expiration": "2018-09-28T01:02:03", + "operations": [ + { + "type": "transfer_operation", + "value": { + "from": "alice1234567890", + "to": "bobob9876543210", + "amount" : {"amount":"50000111","precision":3,"nai":"@@000000013"}, + "memo" : "#"+152*"x", + "permlink": "hello-world-its-bob", + "weight": 10000 + } + } + ], + "extensions": [], + "signatures": [ + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f40" + ] + }, "tx_size" : 282}, + + "long_post" : {"tx" : { + "ref_block_num": 12345, + "ref_block_prefix": 31415926, + "expiration": "2018-09-28T01:02:03", + "operations":[{"type":"comment_operation","value":{ + "parent_author":"alice1234567890", + "parent_permlink":"itsover9000", + "author":"bobob9876543210", + "permlink":40*"p", + "title":40*"t", + "body":7000*"x", + "json_metadata":2000*"m" + }}, + {"type":"comment_options_operation", + "value":{"author":"bobob9876543210", + "permlink":40*"p", + "max_accepted_payout":{"amount":"1000000000","precision":3,"nai":"@@000000013"}, + "percent_hive_dollars":10000, + "allow_votes":True, + "allow_curation_rewards":True, + "extensions":[{"type":"comment_payout_beneficiaries","value":{"beneficiaries":[{"account":"coolui1997","weight":1000}]}}] + }}], + "extensions":[], + "signatures":["1f3de3651752238dcaa8ecfbc3a5c49bca50769b0f1af7d01def32578cf33184eb3258572754eefd036cb62adf797d6e3950fb943b5301fc6d6add64adcbe85f94"] + }, "tx_size" : 9303}, + + "short_post" : {"tx":{ + "ref_block_num": 12345, + "ref_block_prefix": 31415926, + "expiration": "2018-09-28T01:02:03", + "operations":[{"type":"comment_operation","value":{ + "parent_author":"alice1234567890", + "parent_permlink":10*"p", + "author":"bobob9876543210", + "permlink":40*"p", + "title":40*"t", + "body":500*"x", + "json_metadata":150*"m" + }}, + {"type":"comment_options_operation", + "value":{"author":"bobob9876543210", + "permlink":40*"p", + "max_accepted_payout":{"amount":"1000000000","precision":3,"nai":"@@000000013"}, + "percent_hive_dollars":10000, + "allow_votes":True, + "allow_curation_rewards":True, + "extensions":[{"type":"comment_payout_beneficiaries","value":{"beneficiaries":[{"account":"coolui1997","weight":1000}]}}] + }}], + "extensions":[], + "signatures":["1f3de3651752238dcaa8ecfbc3a5c49bca50769b0f1af7d01def32578cf33184eb3258572754eefd036cb62adf797d6e3950fb943b5301fc6d6add64adcbe85f94"]}, + "tx_size" : 952} + } + +vote_tx = example_transactions["vote"]["tx"] +vote_tx_size = example_transactions["vote"]["tx_size"] + +import json + +count_resources = ResourceCounter(resource_params) + +rc_regen = total_vesting_shares // (STEEM_RC_REGEN_TIME // STEEM_BLOCK_INTERVAL) +model = RCModel( resource_params=resource_params, resource_pool=resource_pool, rc_regen=rc_regen ) + +if __name__ == "__main__": + for example_name, etx in sorted(example_transactions.items()): + tx = etx["tx"] + tx_size = etx["tx_size"] + tx_cost = model.get_transaction_rc_cost(tx, tx_size) + total_cost = sum(tx_cost["cost"].values()) + print("{:20} {:6.3f}".format(example_name, total_cost * total_vesting_fund_hive / (1000.0 * total_vesting_shares))) -Click the play button below: +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py36rcdemo?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/reblogging_post.md b/_tutorials-python/reblogging_post.md index bf7e9854..483c34fd 100644 --- a/_tutorials-python/reblogging_post.md +++ b/_tutorials-python/reblogging_post.md @@ -99,13 +99,64 @@ print("Reblogged successfully: " + str(broadcast_tx)) If transaction is successful you shouldn't see any error messages, otherwise you will be notified. ---- +Final code: + +```python +import pprint +from pick import pick +import getpass +import json +# initialize Hive class +from beem import Hive +from beem.discussions import Query, Discussions +from beem.comment import Comment +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Custom_json + +# hive = Hive(['https://testnet.openhive.network']) # Public Testnet +hive = Hive(['http://127.0.0.1:8090']) # Local Testnet +q = Query(limit=5, tag="") +d = Discussions(blockchain_instance=hive) -#### Try it +#author list from hot post list +posts = d.get_discussions('hot', q, limit=5) -Click the play button below: +title = 'Please choose post to reblog: ' +options = [] +# post list +for post in posts: + options.append('@' + post["author"] + '/' + post["permlink"]) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py14rebloggingpost?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# get index and selected post +option, index = pick(options, title) +pprint.pprint("You selected: " + option) + +comment = Comment(option, blockchain_instance=hive) + +account = input("Enter your username? ") + +tx = TransactionBuilder(blockchain_instance=hive) +tx.appendOps(Custom_json(**{ + 'required_auths': [], + 'required_posting_auths': [account], + 'id': 'reblog', + 'json': json.dumps(['reblog', { + 'account': account, + 'author': comment.author, + 'permlink': comment.permlink + }]) +})) + +wif_posting_key = getpass.getpass('Posting Key: ') +tx.appendWif(wif_posting_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) + +print("Reblogged successfully: " + str(broadcast_tx)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/search_accounts.md b/_tutorials-python/search_accounts.md index e1a85a57..7802f8ee 100644 --- a/_tutorials-python/search_accounts.md +++ b/_tutorials-python/search_accounts.md @@ -96,13 +96,50 @@ else: The query returns an array of objects. We use the `for` loop to build a list of only the tag `names` from that array and then display the list on the UI with line separators. This creates an easy to read list of tags. ---- +Final code: -#### Try it +```python +from beem import Hive +from pick import pick +from beem.blockchain import Blockchain +from beem.discussions import Query, Trending_tags -Click the play button below: +# initialize Hive class + +h = Hive() + +# choose list type +title = 'Please select type of list:' +options = ['Active Account names', 'Trending tags'] + +# get index and selected list name +option, index = pick(options, title) + +if option == 'Active Account names': + context = Blockchain(blockchain_instance=h) + # capture starting account + account = input("Enter account name to start search from: ") + # input list limit + limit = input("Enter max number of accounts to display: ") + print('\n' + "List of " + option + '\n') + accounts = [] + for a in context.get_all_accounts(start=account, limit=int(limit)): + print(a) +else: + # capture starting tag + aftertag = input("Enter tag name to start search from: ") + # capture list limit + limit = input("Enter max number of tags to display: ") + print('\n' + "List of " + option + '\n') + q = Query(limit=int(limit), start_tag=aftertag) + for t in Trending_tags(q): + print(t['name']) + + +``` + +--- -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py15searchaccounts?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> ### To Run the tutorial diff --git a/_tutorials-python/search_tags.md b/_tutorials-python/search_tags.md index a3d75e06..5a7f1b5d 100644 --- a/_tutorials-python/search_tags.md +++ b/_tutorials-python/search_tags.md @@ -9,4 +9,46 @@ Full, runnable src of [Search Tags](https://gitlab.syncad.com/hive/devportal/-/t Please refer to [15_search_accounts](search_accounts.html) which includes a tutorial for `trending tags` as well. +Final code: + +```python +from beem import Hive +from pick import pick +from beem.blockchain import Blockchain +from beem.discussions import Query, Trending_tags + +# initialize Hive class + +h = Hive() + +# choose list type +title = 'Please select type of list:' +options = ['Active Account names', 'Trending tags'] + +# get index and selected list name +option, index = pick(options, title) + +if option == 'Active Account names': + context = Blockchain(blockchain_instance=h) + # capture starting account + account = input("Enter account name to start search from: ") + # input list limit + limit = input("Enter max number of accounts to display: ") + print('\n' + "List of " + option + '\n') + accounts = [] + for a in context.get_all_accounts(start=account, limit=int(limit)): + print(a) +else: + # capture starting tag + aftertag = input("Enter tag name to start search from: ") + # capture list limit + limit = input("Enter max number of tags to display: ") + print('\n' + "List of " + option + '\n') + q = Query(limit=int(limit), start_tag=aftertag) + for t in Trending_tags(q): + print(t['name']) + + +``` + --- diff --git a/_tutorials-python/stream_blockchain_transactions.md b/_tutorials-python/stream_blockchain_transactions.md index 6d1e4677..51ed3574 100644 --- a/_tutorials-python/stream_blockchain_transactions.md +++ b/_tutorials-python/stream_blockchain_transactions.md @@ -74,13 +74,27 @@ walterprofe authored a post: LÃmites 01 Introducción poshbot replied to prydefoltz ``` ---- +Final code: -#### Try it +```python +from beem.blockchain import Blockchain +from beem import Hive -Click the play button below: +h = Hive() +blockchain = Blockchain(blockchain_instance=h) +stream = blockchain.stream() -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py13streamblockchaintransactions?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +for op in stream: + if op["type"] == 'comment': + if len(op["parent_author"]) == 0: + print(op["author"] + " authored a post: " + op["title"]) + else: + print(op["author"] + " replied to " + op["parent_author"]) + + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/submit_comment_reply.md b/_tutorials-python/submit_comment_reply.md index e118c8a7..9accf10c 100644 --- a/_tutorials-python/submit_comment_reply.md +++ b/_tutorials-python/submit_comment_reply.md @@ -119,13 +119,48 @@ A simple confirmation is printed on the screen if the post is committed successf You can also check on your local testnet using [database_api.find_comments]({{ '/apidefinitions/#database_api.find_comments' | relative_url }}) for the post. ---- +Final code: + +```python +import random +import string +import getpass +from beem import Hive +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Comment -#### Try it +#capture variables +parent_author = input('Parent author: ') +parent_permlink = input('Parent permlink: ') +author = input('Username: ') +title = input('Post Title: ') +body = input('Post Body: ') -Click the play button below: +#random generator to create post permlink +permlink = ''.join(random.choices(string.digits, k=10)) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py11submitcommentreply?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# client = Hive('https://testnet.openhive.network') # Public Testnet +client = Hive('http://127.0.0.1:8090') # Local Testnet +tx = TransactionBuilder(blockchain_instance=client) +tx.appendOps(Comment(**{ + "parent_author": parent_author, + "parent_permlink": parent_permlink, + "author": author, + "permlink": permlink, + "title": title, + "body": body +})) + +wif_posting_key = getpass.getpass('Posting Key: ') +tx.appendWif(wif_posting_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) + +print("Comment created successfully: " + str(broadcast_tx)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/submit_post.md b/_tutorials-python/submit_post.md index 6ee2329a..98fc8d78 100644 --- a/_tutorials-python/submit_post.md +++ b/_tutorials-python/submit_post.md @@ -114,13 +114,56 @@ A simple confirmation is printed on the screen if the post is committed successf You can also check on your local testnet using [database_api.find_comments]({{ '/apidefinitions/#database_api.find_comments' | relative_url }}) for the post. ---- +Final code: + +```python +import random +import string +import getpass +import json +from beem import Hive +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Comment + +#capture variables +author = input('Username: ') +title = input('Post Title: ') +body = input('Post Body: ') -#### Try it +#capture list of tags and separate by " " +taglimit = 2 #number of tags 1 - 5 +taglist = [] +for i in range(1, taglimit+1): + print(i) + tag = input(' Tag : ') + taglist.append(tag) -Click the play button below: +#random generator to create post permlink +permlink = ''.join(random.choices(string.digits, k=10)) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py10submitpost?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# client = Hive('https://testnet.openhive.network') # Public Testnet +client = Hive('http://127.0.0.1:8090') # Local Testnet +tx = TransactionBuilder(blockchain_instance=client) +tx.appendOps(Comment(**{ + "parent_author": '', + "parent_permlink": taglist[0], # we use the first tag as the category + "author": author, + "permlink": permlink, + "title": title, + "body": body, + "json_metadata": json.dumps({"tags": taglist}) +})) + +wif_posting_key = getpass.getpass('Posting Key: ') +tx.appendWif(wif_posting_key) +signed_tx = tx.sign() +broadcast_tx = tx.broadcast(trx_id=True) + +print("Post created successfully: " + str(broadcast_tx)) + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/transfer_hive_and_hbd.md b/_tutorials-python/transfer_hive_and_hbd.md index f84fc255..3a135521 100644 --- a/_tutorials-python/transfer_hive_and_hbd.md +++ b/_tutorials-python/transfer_hive_and_hbd.md @@ -153,13 +153,80 @@ total_debt = account['hbd_balance'] print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str(total_debt) + '\n') ``` ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Active Key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# get account balance for HIVE and HBD +account = Account(account, blockchain_instance=client) +total_base = account['balance'] +total_debt = account['hbd_balance'] +base_symbol = total_base.symbol +debt_symbol = total_debt.symbol + +print('CURRENT ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str(total_debt) + '\n') + +# get recipient name +recipient = input('Enter the user you wish to transfer funds to: ') -#### Try it +# check for valid recipient name +recipient = Account(recipient, blockchain_instance=client) -Click the play button below: +if recipient: + # choice of transfer + title = 'Please choose transfer type: ' + options = [base_symbol, debt_symbol, 'Cancel Transfer'] + # get index and selected transfer type + option, index = pick(options, title) +else: + print('Invalid recipient for funds transfer') + exit() + +if option == 'Cancel Transfer': + print('Transaction cancelled') + exit() + +if option == base_symbol: + # get HIVE transfer amount + amount = input('Enter amount of ' + base_symbol + ' to transfer to ' + recipient.name + ': ') + amount = float(amount) + symbol = base_symbol +else: + # get HBD transfer amount + amount = input('Enter amount of ' + debt_symbol + ' to transfer to ' + recipient.name + ': ') + amount = float(amount) + symbol = debt_symbol + +account.transfer(recipient.name, amount, symbol) + +print('\n' + str(amount) + ' ' + symbol + ' has been transferred to ' + recipient.name) + +# get remaining account balance for HIVE and HBD +account = Account(account.name, blockchain_instance=client) +total_base = account['balance'] +total_debt = account['hbd_balance'] + +print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str(total_debt) + '\n') + +``` + + +--- -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py21transferhiveandhbd?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> ### To Run the tutorial diff --git a/_tutorials-python/transfer_hive_and_hbd_to_savings_balance.md b/_tutorials-python/transfer_hive_and_hbd_to_savings_balance.md index ee52214f..d845bbb7 100644 --- a/_tutorials-python/transfer_hive_and_hbd_to_savings_balance.md +++ b/_tutorials-python/transfer_hive_and_hbd_to_savings_balance.md @@ -148,13 +148,86 @@ print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str( print('CURRENT SAVINGS BALANCE:' + '\n' + str(savings_base) + '\n' + str(savings_debt) + '\n') ``` ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account +import random + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Enter private ACTIVE key: ') -#### Try it +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet -Click the play button below: +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py33transferhiveandhbdtosavingsbalance?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +# check for valid account and get account balance for HIVE and HBD +account = Account(account, blockchain_instance=client) + +total_base = account['balance'] +total_debt = account['hbd_balance'] +savings_base = account['savings_balance'] +savings_debt = account['savings_hbd_balance'] + +symbol_base = total_base.symbol +symbol_debt = total_debt.symbol + +print('CURRENT ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str(total_debt) + '\n') +print('CURRENT SAVINGS BALANCE:' + '\n' + str(savings_base) + '\n' + str(savings_debt) + '\n') + +input('Press enter to continue with the transfer' + '\n') + +# choice of transfer/withdrawal +title1 = 'Please choose transfer type: ' +options1 = ['Transfer', 'Withdrawal', 'Cancel'] +# get index and selected transfer type +transfer_type, index = pick(options1, title1) + +if transfer_type == 'Cancel': + print('Transaction cancelled') + exit() + +# choice of currency +title2 = 'Please choose currency: ' +options2 = [symbol_base, symbol_debt] +# get index and selected currency +asset, index = pick(options2, title2) + +if asset == symbol_base: + # get HIVE transfer amount + amount = float(input('Enter amount of ' + symbol_base + ' to transfer: ') or '0') +else: + # get HBD transfer amount + amount = float(input('Enter amount of ' + symbol_debt + ' to transfer: ') or '0') + +if transfer_type == 'Transfer': + account.transfer_to_savings(amount, asset, '') + print('\n' + 'Transfer to savings balance successful') +else: + # create request ID random integer + request_id = random.randint(1,1000000) + account.transfer_from_savings(amount, asset, '', request_id=request_id) + print('\n' + 'Withdrawal from savings successful, transaction ID: ' + str(request_id)) + +# get remaining account balance for HIVE and HBD +account.refresh() +total_base = account['balance'] +total_debt = account['hbd_balance'] +savings_base = account['savings_balance'] +savings_debt = account['savings_hbd_balance'] + +print('\n' + 'REMAINING ACCOUNT BALANCE:' + '\n' + str(total_base) + '\n' + str(total_debt) + '\n') +print('CURRENT SAVINGS BALANCE:' + '\n' + str(savings_base) + '\n' + str(savings_debt) + '\n') + +``` + +--- ### To Run the tutorial diff --git a/_tutorials-python/using_keys_securely.md b/_tutorials-python/using_keys_securely.md index 10d57dd4..fbd8a161 100644 --- a/_tutorials-python/using_keys_securely.md +++ b/_tutorials-python/using_keys_securely.md @@ -86,6 +86,28 @@ would sing and broadcast vote operation, etc. That's it! +Final code: + +```python +# initialize Hive class +from beem import Hive +from beem.account import Account + +# defining private keys inside source code is not secure way but possible +h = Hive(keys=['<private_posting_key>', '<private_active_key>']) +a = Account('demo', blockchain_instance=h) + +# above will allow accessing Commit methods such as +# demo account sending 0.001 HIVE to demo1 account + +a.transfer('demo1', '0.001', 'HIVE', memo='memo text') + +# if private keys are not defined +# accessing Wallet methods are also possible and secure way +h.wallet.getActiveKeyForAccount('demo') + +``` + ### To Run the tutorial 1. [review dev requirements](getting_started.html) diff --git a/_tutorials-python/vote_on_content.md b/_tutorials-python/vote_on_content.md index 28324e0f..e7ed9320 100644 --- a/_tutorials-python/vote_on_content.md +++ b/_tutorials-python/vote_on_content.md @@ -140,13 +140,77 @@ When the function is executed the selected vote weight overrides any value previ A simple confirmation of the chosen action is printed on the screen. ---- +Final code: + +```python +from pick import pick +import getpass +from beem import Hive +from beem.account import Account +from beem.vote import ActiveVotes +from beem.transactionbuilder import TransactionBuilder +from beembase.operations import Vote + +# capture user information +voter = input('Please enter your username (voter): ') + +# connect node +# If using mainnet, try with demo account: cdemo, posting key: 5JEZ1EiUjFKfsKP32b15Y7jybjvHQPhnvCYZ9BW62H1LDUnMvHz +# client = Hive('https://testnet.openhive.network') # Public Testnet +client = Hive('http://127.0.0.1:8090') # Local Testnet + +# capture variables +author = input('Author of post/comment that you wish to vote for: ') +permlink = input('Permlink of the post/comment you wish to vote for: ') + +# check vote status +# noinspection PyInterpreter +print('checking vote status - getting current post votes') +identifier = ('@' + author + '/' + permlink) +author_account = Account(author, blockchain_instance=client) +result = ActiveVotes(identifier, blockchain_instance=client) +print(len(result), ' votes retrieved') + +if result: + for vote in result : + if vote['voter'] == voter: + title = "This post/comment has already been voted for" + break + else: + title = "No vote for this post/comment has been submitted" +else: + title = "No vote for this post/comment has been submitted" + +# option to continue +options = ['Add/Change vote', 'Cancel without voting'] +option, index = pick(options, title) + +if option == 'Add/Change vote': + weight = input('\n' + 'Please advise weight of vote between -100.0 and 100 (zero removes previous vote): ') + try: + tx = TransactionBuilder(blockchain_instance=client) + tx.appendOps(Vote(**{ + "voter": voter, + "author": author, + "permlink": permlink, + "weight": int(float(weight) * 100) + })) -#### Try it + wif_posting_key = getpass.getpass('Posting Key: ') + tx.appendWif(wif_posting_key) + signed_tx = tx.sign() + broadcast_tx = tx.broadcast(trx_id=True) -Click the play button below: + print("Vote cast successfully: " + str(broadcast_tx)) + except Exception as e: + print('\n' + str(e) + '\nException encountered. Unable to vote') + +else: + print('Voting has been cancelled') + +``` -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py17voteoncontent?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-python/witness_listing_and_voting.md b/_tutorials-python/witness_listing_and_voting.md index 1dd4a017..a6bb1aea 100644 --- a/_tutorials-python/witness_listing_and_voting.md +++ b/_tutorials-python/witness_listing_and_voting.md @@ -111,13 +111,69 @@ else : A confirmation of the transaction to the blockchain is displayed on the UI. ---- +Final code: + +```python +import pprint +from pick import pick +import getpass +from beem import Hive +from beem.account import Account +from beem.witness import Witness, WitnessesVotedByAccount + +# capture user information +account = input('Enter username: ') +wif_active_key = getpass.getpass('Active Key: ') + +# node_url = 'https://testnet.openhive.network' # Public Testnet +node_url = 'http://127.0.0.1:8090' # Local Testnet + +# connect node and private active key +client = Hive(node_url, keys=[wif_active_key]) + +# check valid user +account = Account(account, blockchain_instance=client) + +# print list of currently voted for witnesses +print('\n' + 'WITNESSES CURRENTLY VOTED FOR') +vote_list = WitnessesVotedByAccount(account.name, blockchain_instance=client) +for witness in vote_list: + pprint.pprint(witness.account.name) + +input('Press enter to continue') -#### Try it +# choice of action +title = ('Please choose action') +options = ['VOTE', 'UNVOTE', 'CANCEL'] +# get index and selected permission choice +option, index = pick(options, title) + +if (option == 'CANCEL') : + print('\n' + 'operation cancelled') + exit() + +if (option == 'VOTE') : + # vote process + witness_vote = input('Please enter the witness name you wish to vote for: ') + witness = Witness(witness_vote, blockchain_instance=client) + if witness_vote in vote_list : + print('\n' + witness_vote + ' cannot be voted for more than once') + exit() + account.approvewitness(witness_vote) + print('\n' + witness_vote + ' has been successfully voted for') +else : + # unvote process + witness_unvote = input('Please enter the witness name you wish to remove the vote from: ') + if witness_unvote not in vote_list : + print('\n' + witness_unvote + ' is not in your voted for list') + exit() + account.disapprovewitness(witness_unvote) + print('\n' + witness_unvote + ' has been removed from your voted for list') + +``` -Click the play button below: -<iframe height="400px" width="100%" src="https://replit.com/@inertia186/py22witnesslistingandvoting?embed=1&output=1" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe> +--- ### To Run the tutorial diff --git a/_tutorials-ruby/blog_feed.md b/_tutorials-ruby/blog_feed.md index 6e38eb7a..02be6e39 100644 --- a/_tutorials-ruby/blog_feed.md +++ b/_tutorials-ruby/blog_feed.md @@ -22,6 +22,44 @@ It also counts the words in the content body by splitting the text into an array Finally, it creates the canonical URL by combining `parent_permlink`, `author`, and `permlink`. + +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +account_name = ARGV[0] +api = Radiator::Api.new +query = {tag: account_name, limit: 5} +created = nil + +api.get_discussions_by_blog(query) do |posts| + posts.each do |post| + words = post.body.split(/\s/) + author = post.author + type = author == account_name ? 'Post' : 'Reblog' + uri = [] + + uri << post.parent_permlink + uri << "@#{author}" + uri << post.permlink + + if created != post.created + puts created = Time.parse(post.created + 'Z') + end + + puts " #{type}: #{post.title}" + puts " By: #{author}" + puts " Words: #{words.size}" + puts " https://hive.blog/#{uri.join('/')}" + end +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/convert_hbd_to_hive.md b/_tutorials-ruby/convert_hbd_to_hive.md index 28e2a56b..fb16405d 100644 --- a/_tutorials-ruby/convert_hbd_to_hive.md +++ b/_tutorials-ruby/convert_hbd_to_hive.md @@ -130,6 +130,38 @@ Broadcasting a `convert` operation will require the following fields: * `requestid` - conversion request identifier * `amount` - amount of HBD to convert +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +options = { + url: 'https://testnet.openhive.network', + wif: '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +} +tx = Radiator::Transaction.new(options) + +tx.operations << { + type: :convert, + owner: 'social', + requestid: 1234, + amount: '10.000 TBD' # <- Testnet: TBD; Mainnet: HBD +} + +response = tx.process(true) + +if !!response.error + puts response.error.message +else + puts JSON.pretty_generate response +end + + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository) with the following arguments: diff --git a/_tutorials-ruby/edit_content_patching.md b/_tutorials-ruby/edit_content_patching.md index f4be243c..bb222cb9 100644 --- a/_tutorials-ruby/edit_content_patching.md +++ b/_tutorials-ruby/edit_content_patching.md @@ -29,6 +29,62 @@ As stated earlier, you will need to change `broadcast` to `true`. You can also * `title` - Title of the post. * `permlink` - Leave this if the `permlink` is derived from the title or set it to the original `permlink` if you want to modify the title independently from the `permlink`. +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +# change to true if you want to broadcast this example +broadcast = false +url = 'https://testnet.openhive.network' +wif = '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +author = 'social' +title = 'title of my post' +permlink = title.gsub(' ', '-').downcase +api = Radiator::Api.new(url: url) +content = api.get_content(author, permlink).result +metadata = {tags: %w(tag), app: 'devportal/1.0'} +new_body = "#{content.body}\nAppended content." +dmp = DiffMatchPatch.new +patches = dmp.patch_make content.body, new_body +diff_body = dmp.patch_toText(patches) + +new_body = diff_body if diff_body < content.body + +puts "Changes:" +puts new_body + +post = { + type: :comment, + parent_author: '', + parent_permlink: metadata[:tags][0], + author: author, + permlink: permlink, + json_metadata: metadata.to_json, + title: title, + body: new_body +} + +tx = Radiator::Transaction.new(url: url, wif: wif) + +tx.operations << post +response = tx.process(broadcast) + +if broadcast + if !!response.error + puts response.error.message + else + puts JSON.pretty_generate response + end +else + puts 'Not broadcasted.' +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/follow_another_user.md b/_tutorials-ruby/follow_another_user.md index 71a37758..1a47c1a0 100644 --- a/_tutorials-ruby/follow_another_user.md +++ b/_tutorials-ruby/follow_another_user.md @@ -59,6 +59,79 @@ The API method we're using here is `condenser.get_following`. We pass the name We also specify `blog` to tell the API method that we're looking for followed, not muted (to locate muted accounts, use `ignore` instead of `blog`). +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +options = { + url: 'https://testnet.openhive.network', + wif: '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +} +tx = Radiator::Transaction.new(options) +what = 'blog' # set this to empty string to unfollow + +tx.operations << { + type: :custom_json, + id: 'follow', + required_auths: [], + required_posting_auths: ['social'], + json: [:follow, { + follower: 'social', + following: 'alice', + what: [what] + }].to_json +} + +response = tx.process(true) + +if !!response.error + puts response.error.message +else + puts JSON.pretty_generate response +end + +``` + +check_follow.rb + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +api = Radiator::Api.new +account_name = 'social' +follow_name = 'alice' +what = 'blog' # use `blog` to find follows, `ignore` to find mutes +follows = [] +following = false +limit = 10 # how many follows to read per api call (limit 1000) +count = 0 + +loop do + follows += api.get_following(account_name, follows.last, what, limit) do |follows| + follows.map(&:following) + end + + follows = follows.uniq + + break unless count < follows.size + count = follows.size +end + +if follows.include? follow_name + puts "#{account_name} is following #{follow_name}" +else + puts "#{account_name} is *not* following #{follow_name}" +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_account_comments.md b/_tutorials-ruby/get_account_comments.md index 7c4071e1..5652b317 100644 --- a/_tutorials-ruby/get_account_comments.md +++ b/_tutorials-ruby/get_account_comments.md @@ -117,6 +117,67 @@ Comments in the results of `get_account_history` will only return the following In our example script, we want more detail than this, so for every `comment`, we call `get_content` to retrieve more detail. For a full explanation of the results provided by `get_content`, please refer to the tutorial: [Get Post Details]({{ '/tutorials-ruby/get_post_details.html' | relative_url }}) +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +account_name = ARGV[0] +api = Radiator::Api.new + +options = [] +options << account_name +options << -1 # start +options << 1000 # limit + +# This is optional, we can mask out all operations other than comment_operation. +operation_mask = 0x02 # comment_operation +options << (operation_mask & 0xFFFFFFFF) # operation_filter_low +options << ((operation_mask & 0xFFFFFFFF00000000) >> 32) # operation_filter_high + +api.get_account_history(*options) do |history| + history.each do |index, item| + type, op = item.op + + next unless type == 'comment' + next if op.parent_author.empty? # skip posts + next if op.parent_author == account_name # skip replies to account + + url = "https://hive.blog/@#{op.author}/#{op.permlink}" + api.get_content(op.author, op.permlink) do |reply| + puts "Reply to @#{op.parent_author} in discussion: \"#{reply.root_title}\"" + + puts "\tbody_length: #{reply.body.size} (#{reply.body.split(/\W+/).size} words)" + + # The date and time this reply was created. + print "\treplied at: #{reply.created}" + + if reply.last_update != reply.created + # The date and time of the last update to this reply. + print ", updated at: #{reply.last_update}" + end + + if reply.last_update != reply.created + # The last time this reply was "touched" by voting or reply. + print ", active at: #{reply.active}" + end + + print "\n" + + # Net positive votes + puts "\tnet_votes: #{reply.net_votes}" + + # Link directly to reply. + puts "\t#{url}" + end + end +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_account_replies.md b/_tutorials-ruby/get_account_replies.md index 37741a68..d65bccb6 100644 --- a/_tutorials-ruby/get_account_replies.md +++ b/_tutorials-ruby/get_account_replies.md @@ -107,6 +107,67 @@ Replies in the results of `get_account_history` will only return the following f In our example script, we want more detail than this, so for every `comment`, we call `get_content` to retrieve more detail. For a full explanation of the results provided by `get_content`, please refer to the tutorial: [Get Post Details]({{ '/tutorials-ruby/get_post_details.html' | relative_url }}) +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +account_name = ARGV[0] +api = Radiator::Api.new + +options = [] +options << account_name +options << -1 # start +options << 1000 # limit + +# This is optional, we can mask out all operations other than comment_operation. +operation_mask = 0x02 # comment_operation +options << (operation_mask & 0xFFFFFFFF) # operation_filter_low +options << ((operation_mask & 0xFFFFFFFF00000000) >> 32) # operation_filter_high + +api.get_account_history(*options) do |history| + history.each do |index, item| + type, op = item.op + + next unless type == 'comment' + next if op.parent_author.empty? # skip posts + next unless op.parent_author == account_name # skip comments by account + + url = "https://hive.blog/@#{op.author}/#{op.permlink}" + api.get_content(op.author, op.permlink) do |reply| + puts "Reply by @#{op.author} in discussion: \"#{reply.root_title}\"" + + puts "\tbody_length: #{reply.body.size} (#{reply.body.split(/\W+/).size} words)" + + # The date and time this reply was created. + print "\treplied at: #{reply.created}" + + if reply.last_update != reply.created + # The date and time of the last update to this reply. + print ", updated at: #{reply.last_update}" + end + + if reply.last_update != reply.created + # The last time this reply was "touched" by voting or reply. + print ", active at: #{reply.active}" + end + + print "\n" + + # Net positive votes + puts "\tnet_votes: #{reply.net_votes}" + + # Link directly to reply. + puts "\t#{url}" + end + end +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_follower_and_following_list.md b/_tutorials-ruby/get_follower_and_following_list.md index 8702fe7b..a4a13d07 100644 --- a/_tutorials-ruby/get_follower_and_following_list.md +++ b/_tutorials-ruby/get_follower_and_following_list.md @@ -89,6 +89,45 @@ until count >= result.size end ``` +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +api = Radiator::Api.new + +if ARGV.size < 1 + puts "Usage:" + puts "ruby #{__FILE__} <account> [following|followers] [limit]" + exit +end + +type = 'blog' # use 'ignore' to get mutes +account = ARGV[0] +what = ARGV[1] || 'following' +limit = (ARGV[2] || '-1').to_i +result = [] +count = -1 + +method = "get_#{what}" +elem = what.sub(/s/, '').to_sym + +until count >= result.size + count = result.size + response = api.send(method, account, result.last, type, [limit, 1000].max) + abort response.error.message if !!response.error + result += response.result.map(&elem) + result = result.uniq +end + +puts result[0..limit] +puts "#{account} #{what}: #{result.size}" + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_post_comments.md b/_tutorials-ruby/get_post_comments.md index 9bc9eb6f..27157cf3 100644 --- a/_tutorials-ruby/get_post_comments.md +++ b/_tutorials-ruby/get_post_comments.md @@ -70,6 +70,28 @@ Replies by: Total replies: 522 ``` +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +url = ARGV[0] +slug = url.split('@').last +author, permlink = slug.split('/') +api = Radiator::Api.new + +api.get_content_replies(author, permlink) do |replies| + reply_authors = replies.map{|reply| reply.author} + reply_authors = reply_authors.uniq.join("\n\t") + puts "Replies by:\n\t#{reply_authors}" + puts "Total replies: #{replies.size}" +end + +``` + --- ### To Run diff --git a/_tutorials-ruby/get_post_details.md b/_tutorials-ruby/get_post_details.md index a638022f..9592acab 100644 --- a/_tutorials-ruby/get_post_details.md +++ b/_tutorials-ruby/get_post_details.md @@ -204,6 +204,171 @@ Note, we're using `rescue` in case the `json_metadata` string contains invalid J {% include structures/comment.html %} +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +url = ARGV[0] +slug = url.split('@').last +author, permlink = slug.split('/') +api = Radiator::Api.new + +api.get_content(author, permlink) do |content| + if content.author.empty? + puts "Could not find content with url: #{url}" + exit + end + + if content.parent_author.empty? + puts "Post by #{content.author}" + else + print "Reply by #{content.author} to #{content.parent_author}/#{content.parent_permlink}" + + if content.parent_author == content.root_author && content.parent_permlink == content.root_permlink + # This is a reply direcly to the root post, no need to specify. + print "\n" + else + # This is a reply to a reply, so we can specify the root post info. + puts " in #{content.root_author}/#{content.root_permlink} (#{content.root_title})" + end + + # Used to track max nested depth of replies. + puts "\tdepth: #{content.depth}" + end + + %w(title permlink category).each do |key| + puts "\t#{key}: #{content[key]}" + end + + puts "\tbody_length: #{content.body.size} (#{content.body.split(/\W+/).size} words)" + + # The date and time this content was created. + print "\tposted at: #{content.created}" + + if content.last_update == content.created + # The date and time of the last update to this content. + print ", updated at: #{content.last_update}" + end + + # The last time this content was "touched" by voting or reply. + puts ", active at: #{content.active}" + + # Used to track the total number of children, grandchildren, etc. ... + puts "\tchildren: #{content.children}" + + # Reward is proportional to liniar rshares, this is the sum of all votes + # (positive and negative reward sum) + puts "\tnet_rshares: #{content.net_rshares}" + + # Total positive rshares from all votes. Used to calculate delta weights. + # Needed to handle vote changing and removal. + puts "\tvote_rshares: #{content.vote_rshares}" + + puts "\tpayout:" + + # Value of the maximum payout this content will receive. + puts "\t\tmax_accepted_payout: #{content.max_accepted_payout}" + + # The percent of Hive Dollars to keep, unkept amounts will be received as + # HIVE Power. + puts "\t\tpercent_hbd: #{'%.2f %%' % (content.percent_hbd / 100.0)}" + + # 7 days from the created date. + if (cashout = Time.parse(content.cashout_time + 'Z') - Time.now.utc) > 0 + cashout = cashout / 86400 # convert from seconds to days + puts "\t\tpays in: #{('%.1f' % (cashout))} days" + + # Pending payout amount if 7 days has not yet elapsed. + puts "\t\tpending_payout_value: #{content.pending_payout_value}" + + # Total pending payout amount if 7 days has not yet elapsed. + puts "\t\ttotal_pending_payout_value: #{content.total_pending_payout_value}" + else + # The date and time of the last update to this content. + print "\t\tpayout at: #{content.last_payout}" + + payout_elapsed = Time.now.utc - Time.parse(content.last_payout + 'Z') + payout_elapsed = payout_elapsed / 86400 # convert from seconds to days + puts " (#{('%.1f' % payout_elapsed)} days ago)" + + # Tracks the author payout this content has received over time, measured in + # the debt asset. + puts "\t\tauthor_rewards: #{('%.3f HBD' % (content.author_rewards / 1000.0))}" + + # Tracks the curator payout this content has received over time, measured in + # the debt asset. + puts "\t\tcurator_payout_value: #{content.curator_payout_value}" + + # Tracks the total payout this content has received over time, measured in + # the debt asset. + puts "\t\ttotal_payout_value: #{content.total_payout_value}" + end + + # If post is promoted, how much has been spent on promotion. + puts "\tpromoted: #{content.promoted}" + + # The list of up to 8 beneficiary accounts for this content as well as the + # percentage of the author reward they will receive in HIVE Power. + if content.beneficiaries.any? + puts "\tbeneficiaries:" + + content.beneficiaries.each do |beneficiary| + puts "\t\t#{beneficiary.account}: #{'%.2f %%' % (beneficiary.weight / 100.0)}" + end + end + + # The total weight of voting rewards, used to calculate pro-rata share of + # curation payouts. + puts "\ttotal_vote_weight: #{content.total_vote_weight}" + + # Weight/percent of reward. + puts "\treward_weight: #{'%.2f %%' % (content.reward_weight / 100.0)}" + + # Net positive votes + print "\tnet_votes: #{content.net_votes}" + + # The entire voting list array, including upvotes, downvotes, and unvotes; + # used to calculate net_votes. + votes = content.active_votes + upvotes = votes.select { |v| v.percent > 0 }.size + downvotes = votes.select { |v| v.percent < 0 }.size + unvotes = votes.select { |v| v.percent == 0 }.size + top_voter = votes.sort_by { |v| v.rshares.to_i }.last.voter + + print ", upvotes: #{upvotes}" + print ", downvotes: #{downvotes}" + print ", unvotes: #{unvotes}" + print ", total: #{votes.size}" + puts ", top voter: #{top_voter}" + + # Allows content to disable replies. + puts "\tallow_replies: #{content.allow_replies}" + + # Allows content to receive votes. + puts "\tallow_votes: #{content.allow_votes}" + + # Allows curators of this content receive rewards. + puts "\tallow_curation_rewards: #{content.allow_curation_rewards}" + + # Author's reputation. + puts "\tauthor_reputation: #{content.author_reputation}" + + # JSON metadata that holds extra information about the content. Note: The + # format for this field is not guaranteed to be valid JSON, so we use rescue + # here to deal with this possibility. + metadata = JSON[content.json_metadata || '{}'] rescue {} + tags = metadata['tags'] || [] + app = metadata['app'] + puts "\ttags: #{tags.join(', ')}" if tags.any? + puts "\tapp: #{app}" if !!app +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_posts.md b/_tutorials-ruby/get_posts.md index b5f205a6..113213cf 100644 --- a/_tutorials-ruby/get_posts.md +++ b/_tutorials-ruby/get_posts.md @@ -37,6 +37,69 @@ For each post we retrieve, we are going to build up a summary to display the int * Number of words in the body * Canonical URL + +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +CATEGORIES = %i(trending hot active created votes promoted children) + +if ARGV.size < 1 + puts "Usage:" + puts "ruby #{__FILE__} <#{CATEGORIES.join('|')}> [limit] [tag]" + exit +end + +category = ARGV[0].downcase.to_sym + +unless CATEGORIES.include? category + puts "Unknown category: #{category}" + puts "Expecting one of: #{CATEGORIES.join(', ')}" + exit +end + +limit = (ARGV[1] || '10').to_i +tag = ARGV[2] || '' +api = Radiator::Api.new + +options = { + tag: tag, + limit: limit +} + +api.send("get_discussions_by_#{category}", options) do |posts, error| + if !!error + puts error.message + exit + end + + posts.each do |post| + words = post.body.split(/\s/) + author = post.author + promoted = post.promoted + uri = [] + + uri << post.parent_permlink + uri << "@#{author}" + uri << post.permlink + + puts created = Time.parse(post.created + 'Z') + puts " Post: #{post.title}" + puts " By: #{author}" + puts " Votes: #{post.net_votes}" + puts " Replies: #{post.children}" + puts " Promoted: #{promoted}" + puts " Words: #{words.size}" + puts " https://hive.blog/#{uri.join('/')}" + end +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/get_voters_list_on_post.md b/_tutorials-ruby/get_voters_list_on_post.md index 78cc32c6..3d8c54b2 100644 --- a/_tutorials-ruby/get_voters_list_on_post.md +++ b/_tutorials-ruby/get_voters_list_on_post.md @@ -20,6 +20,34 @@ First, we ask the blockchain for the active votes on a post or comment. Then, w Then, we sort the votes by `rshares` to find the top voter. +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +url = ARGV[0] +slug = url.split('@').last +author, permlink = slug.split('/') +api = Radiator::Api.new + +api.get_active_votes(author, permlink) do |votes| + upvotes = votes.select { |v| v.percent > 0 }.size + downvotes = votes.select { |v| v.percent < 0 }.size + unvotes = votes.select { |v| v.percent == 0 }.size + top_voter = votes.sort_by { |v| v.rshares.to_i }.last.voter + + puts "Upvotes: #{upvotes}" + puts "Downvotes: #{downvotes}" + puts "Unvotes: #{unvotes}" + puts "Total: #{votes.size}" + puts "Top Voter: #{top_voter}" +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/reblogging_post.md b/_tutorials-ruby/reblogging_post.md index c8911114..aa549c4e 100644 --- a/_tutorials-ruby/reblogging_post.md +++ b/_tutorials-ruby/reblogging_post.md @@ -282,6 +282,47 @@ Broadcasting a `custom_json` operation will require the following fields: * `author` - author of the post being reblogged * `permlink` - permlink of the post being reblogged +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +url = ARGV[0] +slug = url.split('@').last +author = slug.split('/')[0] +permlink = slug.split('/')[1..-1].join('/') +reblogger = 'social' +posting_wif = '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +options = { + url: 'https://testnet.openhive.network', + wif: posting_wif +} + +tx = Radiator::Transaction.new(options) + +data = [ + :reblog, { + account: reblogger, + author: author, + permlink: permlink + } +] + +tx.operations << { + type: :custom_json, + id: 'follow', + required_auths: [], + required_posting_auths: [reblogger], + json: data.to_json +} + +puts JSON.pretty_generate tx.process(true) + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/search_accounts.md b/_tutorials-ruby/search_accounts.md index b3efdbf1..c81439da 100644 --- a/_tutorials-ruby/search_accounts.md +++ b/_tutorials-ruby/search_accounts.md @@ -76,6 +76,24 @@ From the example we get the following output from our script: bob ``` +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +api = Radiator::Api.new +lower_bound_name, limit = ARGV +limit = (limit || '10').to_i + +api.lookup_accounts(lower_bound_name, limit) do |accounts| + puts accounts.join(' ') +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/search_tags.md b/_tutorials-ruby/search_tags.md index fa1b5986..aab5bed0 100644 --- a/_tutorials-ruby/search_tags.md +++ b/_tutorials-ruby/search_tags.md @@ -79,6 +79,41 @@ Tags in the results of `get_trending_tags` returns the following fields: * `top_posts` - Top votes in this tag. * `comments` - Number of comments in this tag. +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +api = Radiator::Api.new +limit = (ARGV[0] || '10').to_i +all_tags = [] + +until all_tags.size >= limit + last_tag = if all_tags.any? + all_tags.last.name + else + nil + end + + api.get_trending_tags(last_tag, [limit, 51].min) do |tags| + all_tags += tags + end + + all_tags = all_tags.uniq +end + +all_tags.each do |tag| + print "tag: #{tag.name.empty? ? '<empty>' : tag.name}," + print " total_payouts: #{tag.total_payouts}," + print " top_posts: #{tag.top_posts}," + print " comments: #{tag.comments}\n" +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/stream_blockchain_transactions.md b/_tutorials-ruby/stream_blockchain_transactions.md index 559d1a1b..add7af59 100644 --- a/_tutorials-ruby/stream_blockchain_transactions.md +++ b/_tutorials-ruby/stream_blockchain_transactions.md @@ -82,6 +82,46 @@ end The `type` variable can be `nil` or the type of ops we're looking for whereas `args` contains the `start` (`block_num` to start from) and `mode` (`head` or `irreversible`). +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +mode = (ARGV[0] || 'irreversible').to_sym +what = (ARGV[1] || 'ops').to_sym +type = (ARGV[2..-1] || ['vote']).map(&:to_sym) +stream = Radiator::Stream.new + +# Set to a block number you would like to begin streaming from, or leave nil +# to stream from the latest block. +start = nil +args = [start, mode] + +case what +when :blocks + stream.blocks(*args) do |block| + block_num = block.block_id[0..7].hex + print "block_num: #{block_num}" + puts "; block_id: #{block.block_id}" + print "\ttransactions: #{block.transactions.size}" + print "; witness: #{block.witness}" + puts "; timestamp: #{block.timestamp}" + end +when :transactions + stream.transactions(*args) do |trx| + puts JSON.pretty_generate trx + end +when :ops + stream.operations(type, *args) do |op| + puts op.to_json + end +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/submit_comment_reply.md b/_tutorials-ruby/submit_comment_reply.md index a19403e2..65fde45f 100644 --- a/_tutorials-ruby/submit_comment_reply.md +++ b/_tutorials-ruby/submit_comment_reply.md @@ -30,6 +30,46 @@ You should change `wif` to the posting key that matches your `author`. This scr * `body` - The actual content of the post. * `json_metadata` - JSON containing the `parent_permlink` of the root post as a tags array. +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +options = { + url: 'https://testnet.openhive.network', + wif: '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +} +tx = Radiator::Transaction.new(options) + +tags = %w(tag1) +metadata = { + tags: tags +} + +tx.operations << { + type: :comment, + author: 'social', + permlink: 'test-post-reply', + parent_author: 'social', + parent_permlink: 'test-post', + title: '', + body: 'Reply', + json_metadata: metadata.to_json +} + +response = tx.process(true) + +if !!response.error + puts response.error.message +else + puts JSON.pretty_generate response +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/submit_post.md b/_tutorials-ruby/submit_post.md index f8a7559c..e0b83173 100644 --- a/_tutorials-ruby/submit_post.md +++ b/_tutorials-ruby/submit_post.md @@ -26,6 +26,46 @@ You should change `wif` to the posting key that matches your `author`. This scr * `body` - The actual content of the post. * `json_metadata` - JSON containing all of the tags. +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +options = { + url: 'https://testnet.openhive.network', + wif: '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +} +tx = Radiator::Transaction.new(options) + +tags = %w(tag1 tag2 tag3) +metadata = { + tags: tags +} + +tx.operations << { + type: :comment, + author: 'social', + permlink: 'test-post', + parent_author: '', + parent_permlink: tags[0], + title: 'Test Post', + body: 'Body', + json_metadata: metadata.to_json +} + +response = tx.process(true) + +if !!response.error + puts response.error.message +else + puts JSON.pretty_generate response +end + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository): diff --git a/_tutorials-ruby/vote_on_content.md b/_tutorials-ruby/vote_on_content.md index 486b5c65..7b4ab91f 100644 --- a/_tutorials-ruby/vote_on_content.md +++ b/_tutorials-ruby/vote_on_content.md @@ -199,6 +199,40 @@ Broadcasting a `vote` operation will require the following fields: * `permlink` - permlink of the post being voted for * `weight` - percentage of one vote being cast, expressed as an integer (e.g.: `100.0 %` = `10000`) +Final code: + +```ruby +require 'rubygems' +require 'bundler/setup' + +Bundler.require + +url, weight = ARGV +slug = url.split('@').last +author = slug.split('/')[0] +permlink = slug.split('/')[1..-1].join('/') +voter = 'social' +posting_wif = '5JrvPrQeBBvCRdjv29iDvkwn3EQYZ9jqfAHzrCyUvfbEbRkrYFC' +weight = ((weight || '100.0').to_f * 100).to_i +options = { + url: 'https://testnet.openhive.network', + wif: posting_wif +} + +tx = Radiator::Transaction.new(options) + +tx.operations << { + type: :vote, + voter: voter, + author: author, + permlink: permlink, + weight: weight +} + +puts JSON.pretty_generate tx.process(true) + +``` + ### To Run First, set up your workstation using the steps provided in [Getting Started]({{ '/tutorials-ruby/getting_started.html' | relative_url }}). Then you can create and execute the script (or clone from this repository) with the following arguments: -- GitLab