rubybear 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +77 -0
  4. data/LICENSE +41 -0
  5. data/README.md +559 -0
  6. data/Rakefile +140 -0
  7. data/gource.sh +8 -0
  8. data/images/Anthony Martin.png +0 -0
  9. data/images/Marvin Hofmann.jpg +0 -0
  10. data/images/Marvin Hofmann.png +0 -0
  11. data/lib/bears.rb +17 -0
  12. data/lib/rubybear.rb +45 -0
  13. data/lib/rubybear/account_by_key_api.rb +7 -0
  14. data/lib/rubybear/account_history_api.rb +15 -0
  15. data/lib/rubybear/api.rb +907 -0
  16. data/lib/rubybear/base_error.rb +23 -0
  17. data/lib/rubybear/block_api.rb +14 -0
  18. data/lib/rubybear/broadcast_operations.json +500 -0
  19. data/lib/rubybear/chain.rb +299 -0
  20. data/lib/rubybear/chain_config.rb +22 -0
  21. data/lib/rubybear/chain_stats_api.rb +15 -0
  22. data/lib/rubybear/condenser_api.rb +99 -0
  23. data/lib/rubybear/database_api.rb +5 -0
  24. data/lib/rubybear/error_parser.rb +228 -0
  25. data/lib/rubybear/follow_api.rb +7 -0
  26. data/lib/rubybear/logger.rb +20 -0
  27. data/lib/rubybear/market_history_api.rb +19 -0
  28. data/lib/rubybear/methods.json +498 -0
  29. data/lib/rubybear/mixins/acts_as_poster.rb +124 -0
  30. data/lib/rubybear/mixins/acts_as_voter.rb +50 -0
  31. data/lib/rubybear/mixins/acts_as_wallet.rb +67 -0
  32. data/lib/rubybear/network_broadcast_api.rb +7 -0
  33. data/lib/rubybear/operation.rb +101 -0
  34. data/lib/rubybear/operation_ids.rb +98 -0
  35. data/lib/rubybear/operation_types.rb +139 -0
  36. data/lib/rubybear/stream.rb +527 -0
  37. data/lib/rubybear/tag_api.rb +33 -0
  38. data/lib/rubybear/transaction.rb +306 -0
  39. data/lib/rubybear/type/amount.rb +57 -0
  40. data/lib/rubybear/type/array.rb +17 -0
  41. data/lib/rubybear/type/beneficiaries.rb +29 -0
  42. data/lib/rubybear/type/future.rb +18 -0
  43. data/lib/rubybear/type/hash.rb +17 -0
  44. data/lib/rubybear/type/permission.rb +19 -0
  45. data/lib/rubybear/type/point_in_time.rb +19 -0
  46. data/lib/rubybear/type/price.rb +25 -0
  47. data/lib/rubybear/type/public_key.rb +18 -0
  48. data/lib/rubybear/type/serializer.rb +12 -0
  49. data/lib/rubybear/type/u_int16.rb +19 -0
  50. data/lib/rubybear/type/u_int32.rb +19 -0
  51. data/lib/rubybear/utils.rb +170 -0
  52. data/lib/rubybear/version.rb +4 -0
  53. data/rubybear.gemspec +40 -0
  54. metadata +412 -0
@@ -0,0 +1,124 @@
1
+ module Rubybear
2
+ module Mixins
3
+ module ActsAsPoster
4
+ # Creates a post operation.
5
+ #
6
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
7
+ # options = {
8
+ # title: 'This is my fancy post title.',
9
+ # body: 'This is my fancy post body.',
10
+ # tags: %w(thess are my fancy tags)
11
+ # }
12
+ # bears.post(options)
13
+ # bears.broadcast!
14
+ #
15
+ # @param options [::Hash] options
16
+ # @option options [String] :title Title of the post.
17
+ # @option options [String] :body Body of the post.
18
+ # @option options [::Array<String>] :tags Tags of the post.
19
+ # @option options [String] :permlink (automatic) Permlink of the post, defaults to formatted title.
20
+ # @option options [String] :parent_permlink (automatic) Parent permlink of the post, defaults to first tag.
21
+ # @option options [String] :parent_author (optional) Parent author of the post (only used if reply).
22
+ # @option options [String] :max_accepted_payout (1000000.000 BSD) Maximum accepted payout, set to '0.000 BSD' to deline payout
23
+ # @option options [Integer] :percent_bears_dollars (5000) Percent BEARS Dollars is used to set 50/50 or 100% BEARS Power
24
+ # @option options [Integer] :allow_votes (true) Allow votes for this post.
25
+ # @option options [Integer] :allow_curation_rewards (true) Allow curation rewards for this post.
26
+ def post(options = {})
27
+ tags = [options[:tags] || []].flatten
28
+ title = options[:title].to_s
29
+ permlink = options[:permlink] || title.downcase.gsub(/[^a-z0-9\-]+/, '-')
30
+ parent_permlink = options[:parent_permlink] || tags[0]
31
+
32
+ raise ChainError, 'At least one tag is required or set the parent_permlink directy.' if parent_permlink.nil?
33
+
34
+ body = options[:body]
35
+ parent_author = options[:parent_author] || ''
36
+ max_accepted_payout = options[:max_accepted_payout] || default_max_acepted_payout
37
+ percent_bears_dollars = options[:percent_bears_dollars]
38
+ allow_votes = options[:allow_votes] || true
39
+ allow_curation_rewards = options[:allow_curation_rewards] || true
40
+ self_vote = options[:self_vote]
41
+
42
+ tags.insert(0, parent_permlink)
43
+ tags = tags.compact.uniq
44
+
45
+ metadata = {
46
+ app: Rubybear::AGENT_ID
47
+ }
48
+ metadata[:tags] = tags if tags.any?
49
+
50
+ @operations << {
51
+ type: :comment,
52
+ parent_permlink: parent_permlink,
53
+ author: account_name,
54
+ permlink: permlink,
55
+ title: title,
56
+ body: body,
57
+ json_metadata: metadata.to_json,
58
+ parent_author: parent_author
59
+ }
60
+
61
+ if (!!max_accepted_payout &&
62
+ max_accepted_payout != default_max_acepted_payout
63
+ ) || !!percent_bears_dollars || !allow_votes || !allow_curation_rewards
64
+ @operations << {
65
+ type: :comment_options,
66
+ author: account_name,
67
+ permlink: permlink,
68
+ max_accepted_payout: max_accepted_payout,
69
+ percent_bears_dollars: percent_bears_dollars,
70
+ allow_votes: allow_votes,
71
+ allow_curation_rewards: allow_curation_rewards,
72
+ extensions: []
73
+ }
74
+ end
75
+
76
+ vote(self_vote, account_name, permlink) if !!self_vote
77
+
78
+ self
79
+ end
80
+
81
+ # Create a vote operation and broadcasts it right away.
82
+ #
83
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
84
+ # options = {
85
+ # title: 'This is my fancy post title.',
86
+ # body: 'This is my fancy post body.',
87
+ # tags: %w(thess are my fancy tags)
88
+ # }
89
+ # bears.post!(options)
90
+ #
91
+ # @see post
92
+ def post!(options = {}); post(options).broadcast!(true); end
93
+
94
+ # Create a delete_comment operation.
95
+ #
96
+ # Examples:
97
+ #
98
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
99
+ # bears.delete_comment('permlink')
100
+ # bears.broadcast!
101
+ #
102
+ # @param permlink
103
+ def delete_comment(permlink)
104
+ @operations << {
105
+ type: :delete_comment,
106
+ author: account_name,
107
+ permlink: permlink
108
+ }
109
+
110
+ self
111
+ end
112
+
113
+ # Create a delete_comment operation and broadcasts it right away.
114
+ #
115
+ # Examples:
116
+ #
117
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
118
+ # bears.delete_comment!('permlink')
119
+ #
120
+ # @see delete_comment
121
+ def delete_comment!(permlink); delete_comment(permlink).broadcast!(true); end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,50 @@
1
+ module Rubybear
2
+ module Mixins
3
+ module ActsAsVoter
4
+ # Create a vote operation.
5
+ #
6
+ # Examples:
7
+ #
8
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
9
+ # bears.vote(10000, 'author', 'permlink')
10
+ # bears.broadcast!
11
+ #
12
+ # ... or ...
13
+ #
14
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
15
+ # bears.vote(10000, '@author/permlink')
16
+ # bears.broadcast!
17
+ #
18
+ # @param weight [Integer] value between -10000 and 10000.
19
+ # @param args [author, permlink || slug] pass either `author` and `permlink` or string containing both like `@author/permlink`.
20
+ def vote(weight, *args)
21
+ author, permlink = normalize_author_permlink(args)
22
+
23
+ @operations << {
24
+ type: :vote,
25
+ voter: account_name,
26
+ author: author,
27
+ permlink: permlink,
28
+ weight: weight
29
+ }
30
+
31
+ self
32
+ end
33
+
34
+ # Create a vote operation and broadcasts it right away.
35
+ #
36
+ # Examples:
37
+ #
38
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
39
+ # bears.vote!(10000, 'author', 'permlink')
40
+ #
41
+ # ... or ...
42
+ #
43
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
44
+ # bears.vote!(10000, '@author/permlink')
45
+ #
46
+ # @see vote
47
+ def vote!(weight, *args); vote(weight, *args).broadcast!(true); end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,67 @@
1
+ module Rubybear
2
+ module Mixins
3
+ module ActsAsWallet
4
+ # Create a claim_reward_balance operation.
5
+ #
6
+ # Examples:
7
+ #
8
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
9
+ # bears.claim_reward_balance(reward_bsd: '100.000 BSD')
10
+ # bears.broadcast!
11
+ #
12
+ # @param options [::Hash] options
13
+ # @option options [String] :reward_bears The amount of BEARS to claim, like: `100.000 BEARS`
14
+ # @option options [String] :reward_bsd The amount of BSD to claim, like: `100.000 BSD`
15
+ # @option options [String] :reward_coins The amount of COINS to claim, like: `100.000000 COINS`
16
+ def claim_reward_balance(options)
17
+ reward_bears = options[:reward_bears] || '0.000 BEARS'
18
+ reward_bsd = options[:reward_bsd] || '0.000 BSD'
19
+ reward_coins = options[:reward_coins] || '0.000000 COINS'
20
+
21
+ @operations << {
22
+ type: :claim_reward_balance,
23
+ account: account_name,
24
+ reward_bears: reward_bears,
25
+ reward_bsd: reward_bsd,
26
+ reward_coins: reward_coins
27
+ }
28
+
29
+ self
30
+ end
31
+
32
+ # Create a claim_reward_balance operation and broadcasts it right away.
33
+ #
34
+ # Examples:
35
+ #
36
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
37
+ # bears.claim_reward_balance!(reward_bsd: '100.000 BSD')
38
+ #
39
+ # @see claim_reward_balance
40
+ def claim_reward_balance!(permlink); claim_reward_balance(permlink).broadcast!(true); end
41
+
42
+ # Create a transfer operation.
43
+ #
44
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your active wif')
45
+ # bears.transfer(amount: '1.000 BSD', to: 'account name', memo: 'this is a memo')
46
+ # bears.broadcast!
47
+ #
48
+ # @param options [::Hash] options
49
+ # @option options [String] :amount The amount to transfer, like: `100.000 BEARS`
50
+ # @option options [String] :to The account receiving the transfer.
51
+ # @option options [String] :memo ('') The memo for the transfer.
52
+ def transfer(options = {})
53
+ @operations << options.merge(type: :transfer, from: account_name)
54
+
55
+ self
56
+ end
57
+
58
+ # Create a transfer operation and broadcasts it right away.
59
+ #
60
+ # bears = Rubybear::Chain.new(chain: :bears, account_name: 'your account name', wif: 'your wif')
61
+ # bears.transfer!(amount: '1.000 BSD', to: 'account name', memo: 'this is a memo')
62
+ #
63
+ # @see transfer
64
+ def transfer!(options = {}); transfer(options).broadcast!(true); end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,7 @@
1
+ module Rubybear
2
+ class NetworkBroadcastApi < Api
3
+ def api_name
4
+ :network_broadcast_api
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,101 @@
1
+ module Rubybear
2
+ class Operation
3
+ include OperationIds
4
+ include OperationTypes
5
+ include Utils
6
+
7
+ def initialize(options = {})
8
+ opt = options.dup
9
+ @type = opt.delete(:type)
10
+
11
+ opt.each do |k, v|
12
+ instance_variable_set("@#{k}", type(@type, k, v))
13
+ end
14
+
15
+ @use_condenser_namespace = if options.keys.include? :use_condenser_namespace
16
+ options.delete(:use_condenser_namespace)
17
+ else
18
+ true
19
+ end
20
+
21
+ unless Operation::known_operation_names.include? @type
22
+ raise OperationError, "Unsupported operation type: #{@type}"
23
+ end
24
+ end
25
+
26
+ def to_bytes
27
+ bytes = [id(@type.to_sym)].pack('C')
28
+
29
+ Operation::param_names(@type.to_sym).each do |p|
30
+ next unless defined? p
31
+
32
+ v = instance_variable_get("@#{p}")
33
+ bytes += v.to_bytes and next if v.respond_to? :to_bytes
34
+
35
+ bytes += case v
36
+ when Symbol then pakStr(v.to_s)
37
+ when String then pakStr(v)
38
+ when Integer then paks(v)
39
+ when TrueClass then pakC(1)
40
+ when FalseClass then pakC(0)
41
+ when ::Array then pakArr(v)
42
+ when ::Hash then pakHash(v)
43
+ when NilClass then next
44
+ else
45
+ raise OperationError, "Unsupported type: #{v.class}"
46
+ end
47
+ end
48
+
49
+ bytes
50
+ end
51
+
52
+ def payload
53
+ params = {}
54
+
55
+ Operation::param_names(@type.to_sym).each do |p|
56
+ next unless defined? p
57
+
58
+ v = instance_variable_get("@#{p}")
59
+ next if v.nil?
60
+ next if v.class == Rubybear::Type::Future
61
+
62
+ params[p] = case v
63
+ when Rubybear::Type::Beneficiaries then [[0, v.to_h]]
64
+ when Rubybear::Type::Amount
65
+ if use_condenser_namespace?
66
+ v.to_s
67
+ else
68
+ v.to_a
69
+ end
70
+ else; v
71
+ end
72
+ end
73
+
74
+ [@type, params]
75
+ end
76
+ private
77
+ def self.broadcast_operations_json_path
78
+ @broadcast_operations_json_path ||= "#{File.dirname(__FILE__)}/broadcast_operations.json"
79
+ end
80
+
81
+ def self.broadcast_operations
82
+ @broadcast_operations ||= JSON[File.read broadcast_operations_json_path]
83
+ end
84
+
85
+ def self.known_operation_names
86
+ broadcast_operations.map { |op| op["operation"].to_sym }
87
+ end
88
+
89
+ def self.param_names(type)
90
+ broadcast_operations.each do |op|
91
+ if op['operation'].to_sym == type.to_sym
92
+ return op['params'].map(&:to_sym)
93
+ end
94
+ end
95
+ end
96
+
97
+ def use_condenser_namespace?
98
+ @use_condenser_namespace
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,98 @@
1
+ module Rubybear
2
+ module OperationIds
3
+ # These IDS are derrived from:
4
+ # https://github.com/bearshares/bears/blob/127a441fbac2f06804359968bda83b66e602c891/libraries/protocol/include/bears/protocol/operations.hpp
5
+
6
+ IDS = [
7
+ :vote_operation,
8
+ :comment_operation,
9
+
10
+ :transfer_operation,
11
+ :transfer_to_coining_operation,
12
+ :withdraw_coining_operation,
13
+
14
+ :limit_order_create_operation,
15
+ :limit_order_cancel_operation,
16
+
17
+ :feed_publish_operation,
18
+ :convert_operation,
19
+
20
+ :account_create_operation,
21
+ :account_update_operation,
22
+
23
+ :witness_update_operation,
24
+ :account_witness_vote_operation,
25
+ :account_witness_proxy_operation,
26
+
27
+ :pow_operation,
28
+
29
+ :custom_operation,
30
+
31
+ :report_over_production_operation,
32
+
33
+ :delete_comment_operation,
34
+ :custom_json_operation,
35
+ :comment_options_operation,
36
+ :set_withdraw_coining_route_operation,
37
+ :limit_order_create2_operation,
38
+ :claim_account_operation,
39
+ :create_claimed_account_operation,
40
+ :request_account_recovery_operation,
41
+ :recover_account_operation,
42
+ :change_recovery_account_operation,
43
+ :escrow_transfer_operation,
44
+ :escrow_dispute_operation,
45
+ :escrow_release_operation,
46
+ :pow2_operation,
47
+ :escrow_approve_operation,
48
+ :transfer_to_savings_operation,
49
+ :transfer_from_savings_operation,
50
+ :cancel_transfer_from_savings_operation,
51
+ :custom_binary_operation,
52
+ :decline_voting_rights_operation,
53
+ :reset_account_operation,
54
+ :set_reset_account_operation,
55
+ :claim_reward_balance_operation,
56
+ :delegate_coining_shares_operation,
57
+ :account_create_with_delegation_operation,
58
+ :witness_set_properties_operation,
59
+
60
+ # SMT operations
61
+ :claim_reward_balance2_operation,
62
+
63
+ :smt_setup_operation,
64
+ :smt_cap_reveal_operation,
65
+ :smt_refund_operation,
66
+ :smt_setup_emissions_operation,
67
+ :smt_set_setup_parameters_operation,
68
+ :smt_set_runtime_parameters_operation,
69
+ :smt_create_operation,
70
+
71
+ # virtual operations below this point
72
+ :fill_convert_request_operation,
73
+ :author_reward_operation,
74
+ :curation_reward_operation,
75
+ :comment_reward_operation,
76
+ :liquidity_reward_operation,
77
+ :interest_operation,
78
+ :fill_coining_withdraw_operation,
79
+ :fill_order_operation,
80
+ :shutdown_witness_operation,
81
+ :fill_transfer_from_savings_operation,
82
+ :hardfork_operation,
83
+ :comment_payout_update_operation,
84
+ :return_coining_delegation_operation,
85
+ :comment_benefactor_reward_operation,
86
+ :producer_reward_operation,
87
+ :clear_null_account_balance_operation
88
+ ]
89
+
90
+ def id(op)
91
+ if op.to_s =~ /_operation$/
92
+ IDS.find_index op
93
+ else
94
+ IDS.find_index "#{op}_operation".to_sym
95
+ end
96
+ end
97
+ end
98
+ end