From abb11b11914552d48dab926ab2f7aca63d7d2060 Mon Sep 17 00:00:00 2001 From: Anthony Martin <github@martin-studio.com> Date: Fri, 22 Jun 2018 08:39:39 -0700 Subject: [PATCH] added option to use condenser_api for broadcast, defaults appbase --- lib/steem/broadcast.rb | 81 +++++++++++------ lib/steem/transaction_builder.rb | 146 ++++++++++++++++++++++--------- lib/steem/type/amount.rb | 56 ++++++++++-- 3 files changed, 206 insertions(+), 77 deletions(-) diff --git a/lib/steem/broadcast.rb b/lib/steem/broadcast.rb index fca4184..da1748b 100644 --- a/lib/steem/broadcast.rb +++ b/lib/steem/broadcast.rb @@ -32,7 +32,7 @@ module Steem class Broadcast extend Retriable - DEFAULT_MAX_ACCEPTED_PAYOUT = Type::Amount.new(["1000000000", 3, "@@000000013"]) + DEFAULT_MAX_ACCEPTED_PAYOUT = Type::Amount.new(amount: '1000000000', precision: 3, nai: '@@000000013') # This operation is used to cast a vote on a post/comment. # @@ -174,9 +174,9 @@ module Steem }]] max_accepted_payout = if params.keys.include? :max_accepted_payout - Type::Amount.to_nia(params[:max_accepted_payout]) + normalize_amount(options.merge amount: params[:max_accepted_payout]) else - DEFAULT_MAX_ACCEPTED_PAYOUT.to_nia + normalize_amount(options.merge amount: DEFAULT_MAX_ACCEPTED_PAYOUT) end allow_votes = if params.keys.include? :allow_votes @@ -274,7 +274,7 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:amount] = Type::Amount.to_nia(params[:amount]) + params[:amount] = normalize_amount(options.merge amount: params[:amount]) ops = [[:transfer, params]] @@ -310,7 +310,7 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:amount] = Type::Amount.to_nia(params[:amount]) + params[:amount] = normalize_amount(options.merge amount: params[:amount]) ops = [[:transfer_to_vesting, params]] @@ -336,7 +336,7 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:vesting_shares] = Type::Amount.to_nia(params[:vesting_shares]) + params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares]) ops = [[:withdraw_vesting, params]] @@ -363,8 +363,8 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:amount_to_sell] = Type::Amount.to_nia(params[:amount_to_sell]) - params[:min_to_receive] = Type::Amount.to_nia(params[:min_to_receive]) + params[:amount_to_sell] = normalize_amount(options.merge amount: params[:amount_to_sell]) + params[:min_to_receive] = normalize_amount(options.merge amount: params[:min_to_receive]) if !!params[:expiration] params[:expiration] = Time.parse(params[:expiration].to_s) @@ -414,8 +414,8 @@ module Steem exchange_rate = params[:exchange_rate] rescue nil || {} base = exchange_rate[:base] quote = exchange_rate[:quote] - params[:exchange_rate][:base] = Type::Amount.to_nia(base) - params[:exchange_rate][:quote] = Type::Amount.to_nia(quote) + params[:exchange_rate][:base] = normalize_amount(options.merge amount: base) + params[:exchange_rate][:quote] = normalize_amount(options.merge amount: quote) ops = [[:feed_publish, params]] @@ -438,7 +438,7 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:amount] = Type::Amount.to_nia(params[:amount]) + params[:amount] = normalize_amount(options.merge amount: params[:amount]) ops = [[:convert, params]] @@ -502,7 +502,7 @@ module Steem check_required_fields(params, *required_fields) - params[:fee] = Type::Amount.to_nia(params[:fee]) + params[:fee] = normalize_amount(options.merge amount: params[:fee]) ops = [[:account_create, params]] @@ -603,8 +603,8 @@ module Steem check_required_fields(params, *required_fields) account_creation_fee = params[:props][:account_creation_fee] rescue nil - params[:props][:account_creation_fee] = Type::Amount.to_nia(account_creation_fee) - params[:fee] = Type::Amount.to_nia(params[:fee]) + params[:props][:account_creation_fee] = normalize_amount(options.merge amount: account_creation_fee) + params[:fee] = normalize_amount(options.merge amount: params[:fee]) ops = [[:witness_update, params]] @@ -844,9 +844,9 @@ module Steem check_required_fields(params, *required_fields) - params[:sbd_amount] = Type::Amount.to_nia(params[:sbd_amount]) - params[:steem_amount] = Type::Amount.to_nia(params[:steem_amount]) - params[:fee] = Type::Amount.to_nia(params[:fee]) + params[:sbd_amount] = normalize_amount(options.merge amount: params[:sbd_amount]) + params[:steem_amount] = normalize_amount(options.merge amount: params[:steem_amount]) + params[:fee] = normalize_amount(options.merge amount: params[:fee]) params[:ratification_deadline] = Time.parse(params[:ratification_deadline].to_s) params[:ratification_deadline] = params[:ratification_deadline].strftime('%Y-%m-%dT%H:%M:%S') @@ -905,8 +905,8 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:sbd_amount] = Type::Amount.to_nia(params[:sbd_amount]) - params[:steem_amount] = Type::Amount.to_nia(params[:steem_amount]) + params[:sbd_amount] = normalize_amount(options.merge amount: params[:sbd_amount]) + params[:steem_amount] = normalize_amount(options.merge amount: params[:steem_amount]) ops = [[:escrow_release, params]] @@ -954,7 +954,7 @@ module Steem check_required_fields(params, *required_fields) params[:memo] ||= '' - params[:amount] = Type::Amount.to_nia(params[:amount]) + params[:amount] = normalize_amount(options.merge amount: params[:amount]) ops = [[:transfer_to_savings, params]] @@ -977,7 +977,7 @@ module Steem check_required_fields(params, *required_fields) params[:memo] ||= '' - params[:amount] = Type::Amount.to_nia(params[:amount]) + params[:amount] = normalize_amount(options.merge amount: params[:amount]) ops = [[:transfer_from_savings, params]] @@ -1039,7 +1039,7 @@ module Steem params = options[:params] check_required_fields(params, *required_fields) - params[:vesting_shares] = Type::Amount.to_nia(params[:vesting_shares]) + params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares]) ops = [[:delegate_vesting_shares, params]] process(options.merge(ops: ops), &block) @@ -1075,8 +1075,8 @@ module Steem check_required_fields(params, *required_fields) - params[:fee] = Type::Amount.to_nia(params[:fee]) - params[:delegation] = Type::Amount.to_nia(params[:delegation]) + params[:fee] = normalize_amount(options.merge amount: params[:fee]) + params[:delegation] = normalize_amount(options.merge amount: params[:delegation]) params[:extensions] ||= [] ops = [[:account_create_with_delegation, params]] @@ -1097,9 +1097,17 @@ module Steem trx = tx.transaction response = if !!options[:pretend] - database_api(options).verify_authority(trx: trx) + if !!options[:app_base] || !!options[:app_base] + database_api(options).verify_authority(trx: trx) + else + database_api(options).verify_authority(trx) + end else - network_broadcast_api(options).broadcast_transaction_synchronous(trx: trx) + if !!options[:app_base] || !!options[:app_base] + network_broadcast_api(options).broadcast_transaction(trx: trx) + else + network_broadcast_api(options).broadcast_transaction_synchronous(trx) + end end break @@ -1120,13 +1128,30 @@ module Steem end private # @private + def self.normalize_amount(options) + if options[:app_base].nil? || !!options[:app_base] + Type::Amount.to_h(options[:amount]) + else + Type::Amount.to_s(options[:amount]) + end + end + + # @privats def self.database_api(options) - options[:database_api] ||= Steem::DatabaseApi.new(options) + options[:database_api] ||= if options[:app_base].nil? || !!options[:app_base] + Steem::DatabaseApi.new(options) + else + Steem::CondenserApi.new(options) + end end # @private def self.network_broadcast_api(options) - options[:network_broadcast_api] ||= Steem::NetworkBroadcastApi.new(options) + options[:network_broadcast_api] ||= if options[:app_base].nil? || !!options[:app_base] + Steem::NetworkBroadcaseApi.new(options) + else + Steem::CondenserApi.new(options) + end end # @private diff --git a/lib/steem/transaction_builder.rb b/lib/steem/transaction_builder.rb index c6c1125..1938270 100644 --- a/lib/steem/transaction_builder.rb +++ b/lib/steem/transaction_builder.rb @@ -26,13 +26,25 @@ module Steem include ChainConfig include Utils - attr_accessor :database_api, :block_api, :expiration, :operations + attr_accessor :app_base, :database_api, :block_api, :expiration, :operations attr_writer :wif attr_reader :signed + alias app_base? app_base + def initialize(options = {}) - @database_api = options[:database_api] || Steem::DatabaseApi.new(options) - @block_api = options[:block_api] || Steem::BlockApi.new(options) + @app_base = options[:app_base].nil? || !!options[:app_base] + @database_api = options[:database_api] + @block_api = options[:block_api] + + if app_base? + @database_api ||= Steem::DatabaseApi.new(options) + @block_api ||= Steem::BlockApi.new(options) + else + @database_api ||= Steem::CondenserApi.new(options) + @block_api ||= Steem::CondenserApi.new(options) + end + @wif = [options[:wif]].flatten @signed = false @@ -114,9 +126,18 @@ module Steem catch :prepare_header do; begin @database_api.get_dynamic_global_properties do |properties| block_number = properties.last_irreversible_block_num + block_header_args = if app_base? + {block_num: block_number} + else + block_number + end - @block_api.get_block_header(block_num: block_number) do |result| - header = result.header + @block_api.get_block_header(block_header_args) do |result| + header = if app_base? + result.header + else + result + end @ref_block_num = (block_number - 1) & 0xFFFF @ref_block_prefix = unhexlify(header.previous[8..-1]).unpack('V*')[0] @@ -138,7 +159,7 @@ module Steem # Sets operations all at once, then prepares. def operations=(operations) - @operations = operations + @operations = operations.map{ |op| normalize_operation(op) } prepare @operations end @@ -167,34 +188,8 @@ module Steem # @return {TransactionBuilder} def put(type, op = nil) @expiration = nil - - ## Saving this for later. This block, or something like it, might replace - ## API broadcast operation structure. - # case type - # when Symbol, String - # type_value = "#{type}_operation" - # @operations << {type: type_value, value: op} - # when Hash - # type_value = "#{type.keys.first}_operation" - # @operations << {type: type_value, value: type.values.first} - # when Array - # type_value = "#{type[0]}_operation" - # @operations << {type: type_value, value: type[1]} - # else - # # don't know what to do with it, skipped - # end - - case type - when Symbol then @operations << [type, op] - when String then @operations << [type.to_sym, op] - when Hash then @operations << [type.keys.first.to_sym, type.values.first] - when Array then @operations << type - else - # don't know what to do with it, skipped - end - + @operations << normalize_operation(type, op) prepare - self end @@ -240,8 +235,20 @@ module Steem unless @signed catch :serialize do; begin - @database_api.get_transaction_hex(trx: trx) do |result| - hex = @chain_id + result.hex[0..-4] # Why do we have to chop the last two bytes? + transaction_hex_args = if app_base? + {trx: trx} + else + trx + end + + @database_api.get_transaction_hex(transaction_hex_args) do |result| + hex = if app_base? + result.hex + else + result + end + + hex = @chain_id + hex[0..-4] # Why do we have to chop the last two bytes? digest = unhexlify(hex) digest_hex = Digest::SHA256.digest(digest) private_keys = @wif.map{ |wif| Bitcoin::Key.from_base58 wif } @@ -283,8 +290,18 @@ module Steem # @return [Array] All public keys that could possibly sign for a given transaction. def potential_signatures - @database_api.get_potential_signatures(trx: transaction) do |result| - result[:keys] + potential_signatures_args = if app_base? + {trx: transaction} + else + transaction + end + + @database_api.get_potential_signatures(potential_signatures_args) do |result| + if app_base? + result[:keys] + else + result + end end end @@ -294,15 +311,35 @@ module Steem # # @return [Array] The minimal subset of public keys that should add signatures to the transaction. def required_signatures - @database_api.get_required_signatures(trx: transaction) do |result| - result[:keys] + required_signatures_args = if app_base? + {trx: transaction} + else + [transaction, []] + end + + @database_api.get_required_signatures(*required_signatures_args) do |result| + if app_base? + result[:keys] + else + result + end end end # @return [Boolean] True if the transaction has all of the required signatures. def valid? - @database_api.verify_authority(trx: transaction) do |result| - result.valid + verify_authority_args = if app_base? + {trx: transaction} + else + transaction + end + + @database_api.verify_authority(verify_authority_args) do |result| + if app_base? + result.valid + else + result + end end end private @@ -318,5 +355,32 @@ module Steem ((sig[33] & 0x80 ) != 0) ) end + + def normalize_operation(type, op = nil) + if app_base? + case type + when Symbol, String + type_value = "#{type}_operation" + {type: type_value, value: op} + when Hash + type_value = "#{type.keys.first}_operation" + {type: type_value, value: type.values.first} + when Array + type_value = "#{type[0]}_operation" + {type: type_value, value: type[1]} + else + raise Steem::ArgumentError, "Don't know what to do with operation type #{type.class}: #{type} (#{op})" + end + else + case type + when Symbol then [type, op] + when String then [type.to_sym, op] + when Hash then [type.keys.first.to_sym, type.values.first] + when Array then type + else + raise Steem::ArgumentError, "Don't know what to do with operation type #{type.class}: #{type} (#{op})" + end + end + end end end diff --git a/lib/steem/type/amount.rb b/lib/steem/type/amount.rb index 11ef376..3caf2be 100644 --- a/lib/steem/type/amount.rb +++ b/lib/steem/type/amount.rb @@ -3,8 +3,10 @@ module Steem # See: https://github.com/xeroc/piston-lib/blob/34a7525cee119ec9b24a99577ede2d54466fca0e/steembase/operations.py class Amount < BaseType - def self.to_nia(amount) - new(amount).to_nia + attr_reader :amount, :precision, :nai, :asset + + def self.to_h(amount) + new(amount).to_h end def self.to_s(amount) @@ -16,15 +18,33 @@ module Steem case value when Array - a, p, t = value - @asset = case t + @amount, @precision, @nai = value + @asset = case @nai when '@@000000013' then 'SBD' when '@@000000021' then 'STEEM' when '@@000000037' then 'VESTS' - else; raise TypeError, "Asset #{@asset} unknown." + else; raise TypeError, "Asset #{@nai} unknown." + end + + @amount = "%.#{@precision}f" % (@amount.to_f / 10 ** @precision) + when Hash + @amount, @precision, @nai = value.map do |k, v| + v if %i(amount precision nai).include? k.to_sym + end.compact + + @asset = case @nai + when '@@000000013' then 'SBD' + when '@@000000021' then 'STEEM' + when '@@000000037' then 'VESTS' + else; raise TypeError, "Asset #{@nai} unknown." end - @precision = p - @amount = "%.#{p}f" % (a.to_f / 10 ** p) + + @amount = "%.#{@precision}f" % (@amount.to_f / 10 ** @precision) + when Amount + @precision = value.precision + @nai = value.nai + @asset = value.asset + @amount = value.amount else @amount, @asset = value.strip.split(' ') rescue ['', ''] @precision = case @asset @@ -45,7 +65,7 @@ module Steem asset end - def to_nia + def to_a case @asset when 'STEEM' then [(@amount.to_f * 1000).to_i.to_s, 3, '@@000000021'] when 'VESTS' then [(@amount.to_f * 1000000).to_i.to_s, 6, '@@000000037'] @@ -53,6 +73,26 @@ module Steem end end + def to_h + case @asset + when 'STEEM' then { + amount: (@amount.to_f * 1000).to_i.to_s, + precision: 3, + nai: '@@000000021' + } + when 'VESTS' then { + amount: (@amount.to_f * 1000000).to_i.to_s, + precision: 6, + nai: '@@000000037' + } + when 'SBD' then { + amount: (@amount.to_f * 1000).to_i.to_s, + precision: 3, + nai: '@@000000013' + } + end + end + def to_s "#{@amount} #{@asset}" end -- GitLab