diff --git a/lib/hive.rb b/lib/hive.rb index ccae1be4d033ade7710097e4cdea9a00247b0e46..c90e41b58badc20a8e33d8cb25d222ce6b5444d5 100644 --- a/lib/hive.rb +++ b/lib/hive.rb @@ -16,6 +16,7 @@ require 'hive/operation' require 'hive/operation/account_create.rb' require 'hive/operation/account_create_with_delegation.rb' require 'hive/operation/account_update.rb' +require 'hive/operation/account_update2.rb' require 'hive/operation/account_witness_proxy.rb' require 'hive/operation/account_witness_vote.rb' require 'hive/operation/cancel_transfer_from_savings.rb' @@ -27,6 +28,7 @@ require 'hive/operation/comment.rb' require 'hive/operation/comment_options.rb' require 'hive/operation/convert.rb' require 'hive/operation/create_claimed_account.rb' +require 'hive/operation/create_proposal.rb' require 'hive/operation/custom.rb' require 'hive/operation/custom_binary.rb' require 'hive/operation/custom_json.rb' @@ -43,6 +45,7 @@ require 'hive/operation/limit_order_create.rb' require 'hive/operation/limit_order_create2.rb' require 'hive/operation/prove_authority.rb' require 'hive/operation/recover_account.rb' +require 'hive/operation/remove_proposal.rb' require 'hive/operation/report_over_production.rb' require 'hive/operation/request_account_recovery.rb' require 'hive/operation/reset_account.rb' @@ -52,6 +55,7 @@ require 'hive/operation/transfer.rb' require 'hive/operation/transfer_from_savings.rb' require 'hive/operation/transfer_to_savings.rb' require 'hive/operation/transfer_to_vesting.rb' +require 'hive/operation/update_proposal_votes.rb' require 'hive/operation/vote.rb' require 'hive/operation/withdraw_vesting.rb' require 'hive/operation/witness_update.rb' diff --git a/lib/hive/broadcast.rb b/lib/hive/broadcast.rb index d9a8af7ea1a8da7a8adb4a2047003278f0dc8f47..b5f85da8adb25b5dfd9471837330b43e59400439 100644 --- a/lib/hive/broadcast.rb +++ b/lib/hive/broadcast.rb @@ -1237,7 +1237,124 @@ module Hive process(options.merge(ops: ops), &block) end - + + # @param options [Hash] options + # @option options [String] :wif Posting wif + # @option options [Hash] :params + # * :account (String) Account claiming rewards. + # * :reward_steem (Amount) Amount of HIVE to claim. + # * :reward_sbd (Amount) Amount of HBD to claim. + # * :reward_vests (Amount) Amount of VESTS to claim. + # @option options [Boolean] :pretend Just validate, do not broadcast. + # @see https://developers.hive.io/apidefinitions/broadcast-ops.html#broadcast_ops_claim_reward_balance + def self.claim_reward_balance(options, &block) + required_fields = %i(account) + params = options[:params] + + check_required_fields(params, *required_fields) + + params[:reward_steem] = normalize_amount(options.merge amount: params[:reward_steem]) + params[:reward_sbd] = normalize_amount(options.merge amount: params[:reward_sbd]) + params[:reward_vests] = normalize_amount(options.merge amount: params[:reward_vests]) + + ops = [[:claim_reward_balance, params]] + + process(options.merge(ops: ops), &block) + end + + # @param options [Hash] options + # @option options [String] :wif Active wif + # @option options [Hash] :params + # * :account (String) Account being updated. + # * :metadata (Hash) Metadata of the account, becomes `json_metadata`. + # * :json_metadata (String) String version of `metadata` (use one or the other). + # @option options [Boolean] :pretend Just validate, do not broadcast. + # @see https://developers.hive.io/apidefinitions/broadcast-ops.html#broadcast_ops_account_update2 + def self.account_update2(options, &block) + required_fields = %i(account) + params = options[:params] + + check_required_fields(params, *required_fields) + + if !!params[:metadata] && !!params[:json_metadata] + raise Hive::ArgumentError, 'Assign either metadata or json_metadata, not both.' + end + + metadata = params.delete(:metadata) || {} + metadata ||= (JSON[params[:json_metadata]] || nil) || {} + params[:json_metadata] = metadata.to_json + + ops = [[:account_update2, params]] + + process(options.merge(ops: ops), &block) + end + + # @param options [Hash] options + # @option options [String] :wif Active wif + # @option options [Hash] :params + # * :creator (String) Creator of the new proposal. + # * :receiver (String) Reciever of `daily_pay` (or creator if empty) + # * :start_date (String) When the proposal starts. + # * :end_date (String) When the proposal ends. + # * :daily_pay (String) Daily pay in HBD starting on the `start_date` and ending on the `end_date`. + # * :subject (String) Subject of the proposal. + # * :permlink (String) Proposal permlink must point to the article posted by creator or receiver. + # @option options [Boolean] :pretend Just validate, do not broadcast. + # @see https://developers.hive.io/apidefinitions/broadcast-ops.html#broadcast_ops_create_proposal + def self.create_proposal(options, &block) + required_fields = %i(creator start_date end_date daily_pay subject permlink) + params = options[:params] + + check_required_fields(params, *required_fields) + + params[:start_date] = Time.parse(params[:start_date].to_s) + params[:start_date] = params[:start_date].strftime('%Y-%m-%dT%H:%M:%S') + params[:end_date] = Time.parse(params[:end_date].to_s) + params[:end_date] = params[:end_date].strftime('%Y-%m-%dT%H:%M:%S') + params[:daily_pay] = normalize_amount(options.merge amount: params[:daily_pay]) + + ops = [[:create_proposal, params]] + + process(options.merge(ops: ops), &block) + end + + # @param options [Hash] options + # @option options [String] :wif Active wif + # @option options [Hash] :params + # * :voter (String) Account doing approval (or removing approval). + # * :proposal_ids (Array<Integer>) Proposals to approve (or remove approval) for. + # * :approve (Boolean) Approve or unapprove. + # @option options [Boolean] :pretend Just validate, do not broadcast. + # @see https://developers.hive.io/apidefinitions/broadcast-ops.html#broadcast_ops_update_proposal_votes + def self.update_proposal_votes(options, &block) + required_fields = %i(voter proposal_ids approve) + params = options[:params] + + check_required_fields(params, *required_fields) + + ops = [[:update_proposal_votes, params]] + + process(options.merge(ops: ops), &block) + end + + # @param options [Hash] options + # @option options [String] :wif Active wif + # @option options [Hash] :params + # * :proposal_owner (String) Creator of the proposal. + # * :proposal_ids (Array<Integer>) Proposals to remove. + # @option options [Boolean] :pretend Just validate, do not broadcast. + # @see https://developers.hive.io/apidefinitions/broadcast-ops.html#broadcast_ops_update_proposal_votes + def self.remove_proposal(options, &block) + required_fields = %i(proposal_owner proposal_ids) + params = options[:params] + + check_required_fields(params, *required_fields) + + ops = [[:remove_proposal, params]] + + process(options.merge(ops: ops), &block) + end + # @param options [Hash] options # @option options [Array<Array<Hash>] :ops Operations to process. # @option options [Boolean] :pretend Just validate, do not broadcast. diff --git a/lib/hive/operation.rb b/lib/hive/operation.rb index 4f7b8510900dbb726b2e20c9f791255fcf450750..5719546b9923a34097d9eaa7c436761136db047b 100644 --- a/lib/hive/operation.rb +++ b/lib/hive/operation.rb @@ -5,7 +5,7 @@ module Hive include Utils # IDs derrived from: - # https://github.com/openhive-network/hive/blob/127a441fbac2f06804359968bda83b66e602c891/libraries/protocol/include/steem/protocol/operations.hpp + # https://gitlab.syncad.com/hive/hive/-/blob/master/libraries/protocol/include/steem/protocol/operations.hpp IDS = [ :vote_operation, @@ -60,6 +60,10 @@ module Hive :delegate_vesting_shares_operation, :account_create_with_delegation_operation, :witness_set_properties_operation, + :account_update2_operation, + :create_proposal_operation, + :update_proposal_votes_operation, + :remove_proposal_operation, # SMT operations :claim_reward_balance2_operation, diff --git a/lib/hive/operation/account_update2.rb b/lib/hive/operation/account_update2.rb new file mode 100644 index 0000000000000000000000000000000000000000..d6538c571bb5c8894ab02686ddfd0ab21d969211 --- /dev/null +++ b/lib/hive/operation/account_update2.rb @@ -0,0 +1,4 @@ +class Hive::Operation::AccountUpdate2 < Hive::Operation + def_attr account: :string + def_attr json_metadata: :string +end diff --git a/lib/hive/operation/create_proposal.rb b/lib/hive/operation/create_proposal.rb new file mode 100644 index 0000000000000000000000000000000000000000..171e71f35d735faaa206df25922f63a0b6c3bdbb --- /dev/null +++ b/lib/hive/operation/create_proposal.rb @@ -0,0 +1,9 @@ +class Hive::Operation::CreateProposal < Hive::Operation + def_attr creator: :string + def_attr receiver: :string + def_attr start_date: :point_in_time + def_attr end_date: :point_in_time + def_attr daily_pay: :amount + def_attr subject: :string + def_attr permlink: :string +end diff --git a/lib/hive/operation/remove_proposal.rb b/lib/hive/operation/remove_proposal.rb new file mode 100644 index 0000000000000000000000000000000000000000..4abd441e0e0aa8ddc7c4619414d5263c2e992dc1 --- /dev/null +++ b/lib/hive/operation/remove_proposal.rb @@ -0,0 +1,4 @@ +class Hive::Operation::RemoveProposal < Hive::Operation + def_attr proposal_owner: :string + def_attr proposal_ids: :uint64_array +end diff --git a/lib/hive/operation/update_proposal_votes.rb b/lib/hive/operation/update_proposal_votes.rb new file mode 100644 index 0000000000000000000000000000000000000000..ed9885e47a3ec0ac6dff561f52e8bc9e618d8660 --- /dev/null +++ b/lib/hive/operation/update_proposal_votes.rb @@ -0,0 +1,5 @@ +class Hive::Operation::UpdateProposalVotes < Hive::Operation + def_attr voter: :string + def_attr proposal_ids: :uint64_array + def_attr approve: :boolean +end diff --git a/test/hive/broadcast_test.rb b/test/hive/broadcast_test.rb index 08af1fa0671d2c17012b25c61d7900b3929e6330..de0b59ab957f92185e3933bddb7b19b1f0828caf 100644 --- a/test/hive/broadcast_test.rb +++ b/test/hive/broadcast_test.rb @@ -9,7 +9,8 @@ module Hive feed_publish limit_order_cancel limit_order_create recover_account request_account_recovery set_withdraw_vesting_route transfer transfer_to_vesting vote withdraw_vesting witness_update - witness_set_properties create_claimed_account claim_account) + witness_set_properties create_claimed_account claim_account + claim_reward_balance) def setup app_base = false # todo: randomly set true or false to test differences. @@ -648,7 +649,7 @@ module Hive props: { account_creation_fee: "0.000 #{@core_symbol}", maximum_block_size: 131072, - sbd_interest_rate:1000 + sbd_interest_rate: 1000 }, fee: "0.000 #{@core_symbol}" } @@ -761,7 +762,7 @@ module Hive id: 777, data: '0a627974656d617374657207737465656d697402a3d13897d82114466ad87a74b73a53292d8331d1bd1d3082da6bfbcff19ed097029db013797711c88cccca3692407f9ff9b9ce7221aaa2d797f1692be2215d0a5f6d2a8cab6832050078bc5729201e3ea24ea9f7873e6dbdc65a6bd9899053b9acda876dc69f11a13df9ca8b26b6' }, - force_serialize: true # FIXME + force_serialize: @force_serialize } vcr_cassette('broadcast_custom') do @@ -777,7 +778,7 @@ module Hive id: 777, data: '0a627974656d617374657207737465656d697402a3d13897d82114466ad87a74b73a53292d8331d1bd1d3082da6bfbcff19ed097029db013797711c88cccca3692407f9ff9b9ce7221aaa2d797f1692be2215d0a5f6d2a8cab6832050078bc5729201e3ea24ea9f7873e6dbdc65a6bd9899053b9acda876dc69f11a13df9ca8b26b6' }, - force_serialize: true # FIXME + force_serialize: @force_serialize } vcr_cassette('broadcast_custom_binary') do @@ -1157,6 +1158,127 @@ module Hive end end + def test_claim_reward_balance + options = { + params: { + account: @account_name, + reward_steem: "0.000 #{@core_symbol}", + reward_sbd: "0.000 #{@debt_symbol}", + reward_vests: "0.000000 #{@vest_symbol}" + } + } + + vcr_cassette('broadcast_claim_reward_balance') do + assert Broadcast.claim_reward_balance(@broadcast_options.merge(options)) + end + end + + def test_account_update2 + options = { + params: { + account: @account_name, + json_metadata: '{}' + } + } + + vcr_cassette('broadcast_account_update2') do + assert_raises MissingActiveAuthorityError do + Broadcast.account_update2(@broadcast_options.merge(options)) + end + end + end + + def test_account_update2_both_metadata + options = { + params: { + metadata: {}, + json_metadata: '{}' + } + } + + assert_raises Hive::ArgumentError do + Broadcast.account_update2(@broadcast_options.merge(options)) + end + end + + def test_account_update2_empty + options = { + params: { + account: @account_name, + json_metadata: '{}' + } + } + + vcr_cassette('broadcast_account_update_empty') do + assert_raises MissingActiveAuthorityError do + Broadcast.account_update2(@broadcast_options.merge(options)) + end + end + end + + def test_create_proposal + options = { + params: { + creator: @account_name, + receiver: '', + start_date: (Time.now.utc + 300), + end_date: (Time.now.utc + 900), + daily_pay: "0.000 #{@debt_symbol}", + subject: 'subject', + permlink: 'permlink' + } + } + + vcr_cassette('broadcast_create_proposal') do + assert_raises MissingActiveAuthorityError do + Broadcast.create_proposal(@broadcast_options.merge(options)) + end + end + end + + def test_update_proposal_votes + options = { + params: { + voter: @account_name, + proposal_ids: ['1'], + approve: true + } + } + + vcr_cassette('broadcast_update_proposal_votes') do + assert_raises MissingActiveAuthorityError do + Broadcast.update_proposal_votes(@broadcast_options.merge(options)) + end + end + end + + def test_remove_proposal + options = { + params: { + proposal_owner: @account_name, + proposal_ids: ['1'] + } + } + + vcr_cassette('broadcast_remove_proposal') do + assert_raises MissingActiveAuthorityError do + Broadcast.remove_proposal(@broadcast_options.merge(options)) + end + end + end + + def test_fake_op + options = { + ops: [[:bogus, {}]] + } + + vcr_cassette('broadcast_fake_op') do + assert_raises UnknownOperationError do + Hive::Broadcast.process(@broadcast_options.merge(options)) + end + end + end + # This test picks a random op to try. def test_random_op fields = %i(account account_to_recover active agent allow_curation_rewards