diff --git a/_data/apidefinitions/database_api.yml b/_data/apidefinitions/database_api.yml index 30b3bf09b6530f4d5862d825cc158ceacbd49425..b38baff0e34a1afdaa438d1df08dd40b7ee738d0 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 baf0a80f3026cea2a19eccbc364fc6a58880c543..f40101e99285e00e7b84d2e515f50f60f0b4bf7a 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 2065c8a689128effe1890dd37ac5ec8f12005dd4..b11a03141c0d3bb48e3f286ee1bc2595287e0a8f 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 4d0b7591c2b09be68dd1173d3040acdd42b31173..b3d8bff2073e1a3570f5429108f87d613fa9d617 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 01ff9f633652c0a2ed31109b6e9e4dc098561469..ee8b8da9df6e9dcfbae9fac39d31d38461f00026 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 acddfe9f201c8d9d29981ce1b1cd162f23c130be..df8c4eb049a867cfbf195766956b3a33c8e2a705 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 958628f1e565a7319c404b428387de301be930e6..d610ae6f7445dc5555f9b241645080d6b6c895ed 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 08877c1a0f395a64031bb848848eb5b703add15b..7b3107576f9ccec8c7a0dba4292004507e61fc4e 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 cc49730b87fc55ea206b411705b89b09ac74f16c..6ec0a0b0d0b6c69b436f8ea9622ef6c6bcd1474d 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 54de17bdeb41beb9262e1b4de564a540407f7a70..7b7f8eae38688d8a6de419d400d2929fc3343157 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 73abd9f98b46cfb65750fd41846c6a7c46c4cf96..0000000000000000000000000000000000000000 --- 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 8ab351a451fdd0638bae6832f83b04d262886b5a..71b908f888c39ddbef169738dcf25a0249960c0e 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 5ac39666d052403b4bb3ce6ccbdd6ba0f8d9c804..cf34d1f8c6027bfd7f9bc4140dd650e0d4364794 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 09933e2751489c0760405a12452c5f76d8c76e04..e4fe598449c0048f0cc48d30005742df1b3625b2 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 4c0e26ee7422347c62b569458f64dea866bc7312..41936e3249a11985236964a6c864e6434350a4e5 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 5f5cad4e03fef0b47257ead91367a489985cbf01..d563c1a5e334333ff24267fe58d660d7beecd681 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 d11ae6544b20d0abb4440e6db9e16f6ab4531dd9..1d3209c86fba0e5abed3f4c8d39e2da403ab21eb 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 c652108d1ccd6288504fcd0e4fac36f080c622df..31c3cdf0477b1a83c3539942caf783ae25047191 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 114c1fbbe2b102c68c12ae836d42dd8a7ab20b2b..f0f27f4a27ac6834116085a513157d9de50d2d0c 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 0db6509e576b71fe794bf1a9e08f3792b8f15054..6615ee5342df0f8267544558caa0a77e9a8fd4b2 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 04d82dc7a201fd449c9e6170f14a425db864074d..cc53fa27359ca852a7cd3b4690173a7f1ccd08d0 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 4650cf7a14e4a0f69d213c283703f617f0d451a9..a3025439eafe4ddefce3a993a188c2f10185ec37 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 9981615dc8458dc0692ca9784dd0d2eca60df2ca..adbd0cbc9e64fffcbcf4f821b67c46a1f0e2afea 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 7904a0b110b942c1f55f152933ee5ec133a263a6..3842a74482171d4bb500feb196511aef4ad75875 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 d2a399b56afb6f90977a6b9ed4ca309d65149c46..81210ab9d8d621db46334cf01460730c19dfcd7f 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 99842fa83bb6689f3ee1ac2a6090e94efcb54c9e..c23c7afd9d17c4fb7fb416038a052334b2dc4510 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 daa1c0dbd091e9a4216f7152daabbf187eaa1d75..7e088d39ee1199d4ba7b1ecc3dece13c03f623f8 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 ce2868842e419001aff852478b4670c4e557ea5a..68555b05e0459a776138b6c72610a08f0d14eb79 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 49a2b410bda6b9da6b1351dc525f04e2a3cb98e7..1b67bb302687b8042b38f1c41b93e3a23819bd36 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 020eac95d21f2d2f181f1c75fab1ea86d1f71002..a68b47b0593355d7d6bd55b2909ce51c263b6124 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 4d7ad86b1577d8ca69826e0b26594d8d3b870818..4cb37d073289a2e76f920f3e3f305f721fb938cb 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 77a3f72c30c870c26098ac42a19b448867371da5..39dfbb57a7b8438d18a7de56ff381eb4e6bdb2ed 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 21909c706bbafa9ccfd46f18eec34eca9de5c33f..1bc069f95fb9a0dec3c161983e3b0113c58f25c8 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 a82cf0c74980330b98847a425b708817efb3747f..f95f6999f8d1e3d6b67b8d0ac8cf552bffdb73ec 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 c5c44f489f12c64aa2e6a84fa21f239f80fbd6ac..0fe1bbcac3634772ad2493843e753100f1b8bb11 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 19dde55eaea88f9adf104692f570959cff2b0203..9ef6fd04423ba189587b843796818812d7d48b47 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 92dc093a1e70f8e9612304ab67d711c00356b064..4a4bd36235cb344207867bde050ef1de288e793c 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 a81f6039b8eba7ea8bc33ab76152a4d634568b92..117110149834603faddde89dfbbebd02897868c7 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 89eb4a27f3997f04ccd65198552cabf2c12c4731..e7f7388cb7c16bbafb30678d67fcc82edda10786 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 bf9adb0ed532cb95ecad2d886d215a7d6a8d48d3..cae7fff539a81bdebd380cc8e17bb45f4ca02b7f 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 bfc7b3b0873d52f28bc8ac2e487bc6ff14b24697..290d7d24ebbcdabd1b40028d4b54e74092b2d803 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 bdb16d39a6e401fadca873ffa649f474634f2a23..84b6dd3faf45e4a3403e0da59ce918a1c1e2ff50 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 b2df2c41901285ffba60f0d87c17647c94c63c17..e4d1a983558b11714bb46129b374a33d6ae75751 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 aae2d4b3625cb7e8c5760f9678e0fa045bcab031..d89cb8a76311c9b565d99a9445d0db14c24be0cf 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 30124d2e2a171fb661393d24d7d918eafe569a31..bd891fe1e98365e54101c5b9ab3de664f1e349ba 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 927a8e93c4f4d4772a9fb2826eed31e9c0d39b13..0d26476a9740457f14f95335b48dabf36ce44164 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 02a45a19dc99839770f42513bcfbecb9230fc152..a3539c4d043e1257a2a25e7ddb1f2aaa4af2abbb 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 7104f17df859c537707507107c24163090facdde..93a0254dbfd159e9d9c0b1dda838fdb74c88c709 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 08381b02dde486585bd9905a645011c9cfe7041f..df15a92fd48d2d8da8e42cc4ec7645c35d41d421 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 56d5dd693f9dc8fabc232373e41a58c4a685944e..9d123ce15040251b2f0021a4819db62bd7ff786a 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 e1dfffe589f86238f13d409f50e4b4a1ef1b3e6f..daa13501c6207d3eca496f208e9ee4d237475f0f 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 de3293e1c8c05e2fcfbfb38743ba5d325ffbe65f..fa587d1c0781fa0452bd80962e766dd274e9a174 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 0a8b5ba75d1f479cd37e33052a34c79e47221e7c..88131ae0a008bea0bed53b1afb3837a2bbfc9ebe 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 fcc1c16f4a4d09e3a7b350a50e6c7ece82ee1e32..b7813d601ea5ab4facf116174271efd0f4f7da9c 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 7d0bcf64d88af9c61248f38a1a5b44f7e1d85efb..5a3fc71272c4dc562e9ad548e9136ad95a61aba4 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 7157930c68f9b8dad4095fcfaa310a8fe28a752e..964a2f6fa20e348ed1961e85bd1da8b619bc6615 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 ecd34549d990aa50d485cec2a67c1cf67452fe46..52ba7fc4f2051c6e6d26cc50d5ae2d50e3a95f07 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 d2052e0610423b315230bfd695774afc3e7eddb4..6dee5fb3f537b56baa45af0000ca9ad039245bfe 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 c7843759483eb9415e58fb5a7cf458f95bb81ac7..2379f794bc7b515129d896e1c3802ab5abd88092 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 3a27945beaae5febe004f6835c7b1887558f389a..1101ce80503c486d2ef92ce0a74c35992d6169eb 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 738924ad447a06049c97f04ce06cd0e826661e73..d3ff4c2220efa08bd764c2336c4f7d2916512dbc 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 56c3e0b6d94065fe7a183b02dfd6189b1f7dc9de..8daffe6a3501a004ff8682062bff0634c6d9ee1f 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 ed722489abb6ad448da7c32e3b77a1763a3077a3..fdfd9e6e7939a4967d3b199c8df9e1d8392c01aa 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 bf7e98543a57eb28996cb416d7bd36e4e832c033..483c34fda5e0e1e6c10de3e16c6f45afb9d8ce90 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 e1a85a57ee6f0ecc6e7514e94743d9eb14a5ae27..7802f8ee7d1ae602efa7c43ead36b5bcee0b255a 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 a3d75e0631ec8a648349386da51012eae49f4cb7..5a7f1b5d4277bc4ad9bc7eaa5f80d400e61e84fe 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 6d1e467713b255966cf58133050fb0d775e03045..51ed3574c15e4a523281a9c3adcd3c41d2e739e1 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 e118c8a711d79b6859bd2f21c1271bd2abad7346..9accf10c46debc4f195eb90af4d0fabe3d914d0c 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 6ee2329a86f5cb1fb054285425ab275a3d904e03..98fc8d78cc2bad4fdcf80c6bf992405d61828417 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 f84fc255ffdd2fbbd56eb82332de70112b61ff3c..3a1355210936155c9a29c12409e7a3058c67582c 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 ee52214f7c32a1dfcb291ca645c926ebb4c3a1af..d845bbb72160b3fbad37f3b0b8d9096665b073a3 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 10d57dd46c7476bc7e318699bb17276e444e7543..fbd8a161a9b04d91347997d11da13b5413a7286d 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 28324e0fcbec14cd52d7acbbf7d06d1837077952..e7ed932097371353acbfd1623257bc25b55863f4 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 1dd4a01743dcdfa80702d2dfd17952c30c1fb42c..a6bb1aeacf4df8a4dacbb880ea486a4de70edece 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 6e38eb7a1beb2c5a4365a90573271ac21f0eabc4..02be6e39e3b6dfd87834c17c5eab8c657b24f02b 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 28e2a56b1b4ed3041c3a3d63a2f98db834305ffb..fb16405dadadbab254ba8d7b5ec49c76c7d90851 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 f4be243cde908ad4fee29171059bb064601e42ce..bb222cb9d6e6899a3d6b5a9920ecb640c888bee1 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 71a3775898b0e23f4618b32179d7fe9bbb09c670..1a47c1a0f179e977ed6acec2ac933d0494c9355b 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 7c4071e128c91862f2d9d89c2ddf6342a2575b97..5652b3171a8f78ac5310598670c15253a9925bf4 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 37741a68a2721f8ba67980f5f752db1daa6305e3..d65bccb61b77bc12ab01b105656b301f42085352 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 8702fe7bef4b4d0bc126dbfb118f4c873249d8db..a4a13d07466cca9b2f6d6edbb8ba47c0730f0d0d 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 9bc9eb6f23ca10e6832a806688ea0274e8930e8f..27157cf374e6b9c18e3c463bdc9bfe5522f567c9 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 a638022f0593537ae9fb41307b48d20509fb0f2e..9592acabc289e6441653f11d5e45c4220fc7b018 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 b5f205a6566282d72b97f037772b788734a9cb37..113213cfef8a3e4e0ab7a56a3822c5a6f21dd158 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 78cc32c630637085c39e25b2a9bba0c3bfaacafb..3d8c54b2caaf5c9294ad797956ef12a319a361d6 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 c891111422c03865c56f1647c82885e3a75f2d6c..aa549c4eaf6eae24053dc0a5c8406dade31bad34 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 b3efdbf1e47bf055c6e07a0f58177fde4dd93864..c81439da0ebe13f3461109e058b204b87f57618d 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 fa1b5986640bc6da5b693e8292da19ac34172331..aab5bed0f7eefbc5d0a4fb64560b0610bd157c2d 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 559d1a1b080fc69e6cf01ff35d0103769c7dd8e7..add7af59e9c9e769c00d0dc4c0a927e3917dcae5 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 a19403e2cb6a90658f2b8588cae7df0fc47409af..65fde45f67a1d207c0159c486846d90ce0510479 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 f8a7559c422735e8c03aee08d350b18b57d7d35a..e0b831734b3b25ef23688dcc66cb99667d7a41e8 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 486b5c651ad6a94a107cb8bbba0b75c210f57482..7b4ab91fdb2445be0c2a060381dbb43c9d2f24df 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: