radiator 0.3.15 → 0.4.0pre1

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.
@@ -0,0 +1,50 @@
1
+ module Radiator
2
+ module Mixins
3
+ module ActsAsVoter
4
+ # Create a vote operation.
5
+ #
6
+ # Examples:
7
+ #
8
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
9
+ # steem.vote(10000, 'author', 'permlink')
10
+ # steem.broadcast!
11
+ #
12
+ # ... or ...
13
+ #
14
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
15
+ # steem.vote(10000, '@author/permlink')
16
+ # steem.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
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
39
+ # steem.vote!(10000, 'author', 'permlink')
40
+ #
41
+ # ... or ...
42
+ #
43
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
44
+ # steem.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 Radiator
2
+ module Mixins
3
+ module ActsAsWallet
4
+ # Create a claim_reward_balance operation.
5
+ #
6
+ # Examples:
7
+ #
8
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
9
+ # steem.claim_reward_balance(reward_sbd: '100.000 SBD')
10
+ # steem.broadcast!
11
+ #
12
+ # @param options [Hash] options
13
+ # @option options [String] :reward_steem The amount of STEEM to claim, like: `100.000 STEEM`
14
+ # @option options [String] :reward_sbd The amount of SBD to claim, like: `100.000 SBD`
15
+ # @option options [String] :reward_vests The amount of VESTS to claim, like: `100.000000 VESTS`
16
+ def claim_reward_balance(options)
17
+ reward_steem = options[:reward_steem] || '0.000 STEEM'
18
+ reward_sbd = options[:reward_sbd] || '0.000 SBD'
19
+ reward_vests = options[:reward_vests] || '0.000000 VESTS'
20
+
21
+ @operations << {
22
+ type: :claim_reward_balance,
23
+ account: account_name,
24
+ reward_steem: reward_steem,
25
+ reward_sbd: reward_sbd,
26
+ reward_vests: reward_vests
27
+ }
28
+
29
+ self
30
+ end
31
+
32
+ # Create a claim_reward_balance operation and broadcasts it right away.
33
+ #
34
+ # Examples:
35
+ #
36
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
37
+ # steem.claim_reward_balance!(reward_sbd: '100.000 SBD')
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
+ # steem = Steem.new(account_name: 'your account name', wif: 'your active wif')
45
+ # steem.transfer(amount: '1.000 SBD', to: 'account name', memo: 'this is a memo')
46
+ # steem.broadcast!
47
+ #
48
+ # @param options [Hash] options
49
+ # @option options [String] :amount The amount to transfer, like: `100.000 STEEM`
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
+ # steem = Steem.new(account_name: 'your account name', wif: 'your wif')
61
+ # steem.transfer!(amount: '1.000 SBD', 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
@@ -8,13 +8,13 @@ module Radiator
8
8
  class Transaction
9
9
  include ChainConfig
10
10
  include Utils
11
-
11
+
12
12
  VALID_OPTIONS = %w(
13
13
  wif private_key ref_block_num ref_block_prefix expiration
14
14
  chain
15
15
  ).map(&:to_sym)
16
16
  VALID_OPTIONS.each { |option| attr_accessor option }
17
-
17
+
18
18
  def initialize(options = {})
19
19
  options = options.dup
20
20
  options.each do |k, v|
@@ -24,29 +24,31 @@ module Radiator
24
24
  send("#{k}=", v)
25
25
  end
26
26
  end
27
-
27
+
28
28
  @logger = options[:logger] || Radiator.logger
29
29
  @chain ||= :steem
30
30
  @chain = @chain.to_sym
31
31
  @chain_id = chain_id options[:chain_id]
32
32
  @url = options[:url] || url
33
33
  @operations = options[:operations] || []
34
-
34
+
35
35
  unless NETWORK_CHAIN_IDS.include? @chain_id
36
36
  warning "Unknown chain id: #{@chain_id}"
37
37
  end
38
-
38
+
39
39
  if !!wif && !!private_key
40
40
  raise TransactionError, "Do not pass both wif and private_key. That's confusing."
41
41
  end
42
-
42
+
43
43
  if !!wif
44
44
  @private_key = Bitcoin::Key.from_base58 wif
45
45
  end
46
-
46
+
47
+ @ref_block_num ||= nil
48
+ @ref_block_prefix ||= nil
47
49
  @expiration ||= nil
48
50
  @immutable_expiration = !!@expiration
49
-
51
+
50
52
  options = options.merge(
51
53
  url: @url,
52
54
  chain: @chain,
@@ -54,23 +56,23 @@ module Radiator
54
56
  persist: false,
55
57
  reuse_ssl_sessions: false
56
58
  )
57
-
59
+
58
60
  @api = Api.new(options)
59
61
  @network_broadcast_api = NetworkBroadcastApi.new(options)
60
-
62
+
61
63
  ObjectSpace.define_finalizer(self, self.class.finalize(@api, @network_broadcast_api, @logger))
62
64
  end
63
-
65
+
64
66
  def chain_id(chain_id = nil)
65
67
  return chain_id if !!chain_id
66
-
68
+
67
69
  case chain.to_s.downcase.to_sym
68
70
  when :steem then NETWORKS_STEEM_CHAIN_ID
69
71
  when :golos then NETWORKS_GOLOS_CHAIN_ID
70
72
  when :test then NETWORKS_TEST_CHAIN_ID
71
73
  end
72
74
  end
73
-
75
+
74
76
  def url
75
77
  case chain.to_s.downcase.to_sym
76
78
  when :steem then NETWORKS_STEEM_DEFAULT_NODE
@@ -78,24 +80,24 @@ module Radiator
78
80
  when :test then NETWORKS_TEST_DEFAULT_NODE
79
81
  end
80
82
  end
81
-
83
+
82
84
  def process(broadcast = false)
83
85
  prepare
84
-
86
+
85
87
  if broadcast
86
88
  loop do
87
89
  response = @network_broadcast_api.broadcast_transaction_synchronous(payload)
88
-
90
+
89
91
  if !!response.error
90
92
  parser = ErrorParser.new(response)
91
-
93
+
92
94
  if parser.can_reprepare?
93
95
  debug "Error code: #{parser}, repreparing transaction ..."
94
96
  prepare
95
- redo
97
+ redo
96
98
  end
97
99
  end
98
-
100
+
99
101
  return response
100
102
  end
101
103
  else
@@ -104,7 +106,7 @@ module Radiator
104
106
  ensure
105
107
  shutdown
106
108
  end
107
-
109
+
108
110
  def operations
109
111
  @operations = @operations.map do |op|
110
112
  case op
@@ -113,14 +115,20 @@ module Radiator
113
115
  end
114
116
  end
115
117
  end
116
-
118
+
117
119
  def operations=(operations)
118
120
  @operations = operations
119
121
  end
120
-
122
+
121
123
  def shutdown
122
124
  @api.shutdown if !!@api
123
125
  @network_broadcast_api.shutdown if !!@network_broadcast_api
126
+
127
+ if !!@logger && defined?(@logger.close)
128
+ if defined?(@logger.closed?)
129
+ @logger.close unless @logger.closed?
130
+ end
131
+ end
124
132
  end
125
133
  private
126
134
  def payload
@@ -133,35 +141,35 @@ module Radiator
133
141
  signatures: [hexlify(signature)]
134
142
  }
135
143
  end
136
-
144
+
137
145
  def prepare
138
146
  raise TransactionError, "No wif or private key." unless !!@wif || !!@private_key
139
-
147
+
140
148
  @payload = nil
141
-
149
+
142
150
  while @expiration.nil? && @ref_block_num.nil? && @ref_block_prefix.nil?
143
151
  @api.get_dynamic_global_properties do |properties, error|
144
152
  if !!error
145
153
  raise TransactionError, "Unable to prepare transaction.", error
146
154
  end
147
-
155
+
148
156
  @properties = properties
149
157
  end
150
-
158
+
151
159
  # You can actually go back as far as the TaPoS buffer will allow, which
152
160
  # is something like 50,000 blocks.
153
-
161
+
154
162
  block_number = @properties.last_irreversible_block_num
155
-
163
+
156
164
  @api.get_block(block_number) do |block, error|
157
165
  if !!error
158
166
  raise TransactionError, "Unable to prepare transaction.", error
159
167
  end
160
-
168
+
161
169
  if !!block && !!block.previous
162
170
  @ref_block_num = (block_number - 1) & 0xFFFF
163
171
  @ref_block_prefix = unhexlify(block.previous[8..-1]).unpack('V*')[0]
164
-
172
+
165
173
  # The expiration allows for transactions to expire if they are not
166
174
  # included into a block by that time. Always update it to the current
167
175
  # time + EXPIRE_IN_SECS.
@@ -169,50 +177,50 @@ module Radiator
169
177
  # Note, as of #1215, expiration exactly 'now' will be rejected:
170
178
  # https://github.com/steemit/steem/blob/57451b80d2cf480dcce9b399e48e56aa7af1d818/libraries/chain/database.cpp#L2870
171
179
  # https://github.com/steemit/steem/issues/1215
172
-
180
+
173
181
  block_time = Time.parse(@properties.time + 'Z')
174
182
  @expiration ||= block_time + EXPIRE_IN_SECS
175
183
  else
176
184
  # Suspect this happens when there are microforks, but it should be
177
185
  # rare, especially since we're asking for the last irreversible
178
186
  # block.
179
-
187
+
180
188
  if block.nil?
181
189
  warning "Block missing while trying to prepare transaction, retrying ..."
182
190
  else
183
191
  debug block if %w(DEBUG TRACE).include? ENV['LOG']
184
-
192
+
185
193
  warning "Block structure while trying to prepare transaction, retrying ..."
186
194
  end
187
-
195
+
188
196
  @expiration = nil unless @immutable_expiration
189
197
  end
190
198
  end
191
199
  end
192
-
200
+
193
201
  self
194
202
  end
195
-
203
+
196
204
  def to_bytes
197
205
  bytes = unhexlify(@chain_id)
198
206
  bytes << pakS(@ref_block_num)
199
207
  bytes << pakI(@ref_block_prefix)
200
208
  bytes << pakI(@expiration.to_i)
201
209
  bytes << pakC(operations.size)
202
-
210
+
203
211
  operations.each do |op|
204
212
  bytes << op.to_bytes
205
213
  end
206
-
214
+
207
215
  bytes << 0x00 # extensions
208
-
216
+
209
217
  bytes
210
218
  end
211
-
219
+
212
220
  def digest
213
221
  Digest::SHA256.digest(to_bytes)
214
222
  end
215
-
223
+
216
224
  # May not find all non-canonicals, see: https://github.com/lian/bitcoin-ruby/issues/196
217
225
  def signature
218
226
  public_key_hex = @private_key.pub
@@ -224,16 +232,17 @@ module Radiator
224
232
  count += 1
225
233
  debug "#{count} attempts to find canonical signature" if count % 40 == 0
226
234
  sig = ec.sign_compact(digest_hex, @private_key.priv, public_key_hex, false)
227
-
235
+
228
236
  next if public_key_hex != ec.recover_compact(digest_hex, sig)
229
-
237
+
230
238
  return sig if canonical? sig
231
239
  end
232
240
  end
233
241
 
242
+ # See: https://github.com/steemit/steem/issues/1944
234
243
  def canonical?(sig)
235
244
  sig = sig.unpack('C*')
236
-
245
+
237
246
  !(
238
247
  ((sig[0] & 0x80 ) != 0) || ( sig[0] == 0 ) ||
239
248
  ((sig[1] & 0x80 ) != 0) ||
@@ -241,7 +250,7 @@ module Radiator
241
250
  ((sig[33] & 0x80 ) != 0)
242
251
  )
243
252
  end
244
-
253
+
245
254
  def self.finalize(api, network_broadcast_api, logger)
246
255
  proc {
247
256
  if !!api && !api.stopped?
@@ -249,16 +258,20 @@ module Radiator
249
258
  api.shutdown
250
259
  api = nil
251
260
  end
252
-
261
+
253
262
  if !!network_broadcast_api && !network_broadcast_api.stopped?
254
263
  puts "DESTROY: #{network_broadcast_api.inspect}" if ENV['LOG'] == 'TRACE'
255
264
  network_broadcast_api.shutdown
256
265
  network_broadcast_api = nil
257
266
  end
258
-
259
- if !!logger && defined?(logger.close) && !logger.closed?
260
- logger.close
261
- end
267
+
268
+ begin
269
+ if !!logger && defined?(logger.close)
270
+ if defined?(logger.closed?)
271
+ logger.close unless logger.closed?
272
+ end
273
+ end
274
+ rescue IOError, NoMethodError => _; end
262
275
  }
263
276
  end
264
277
  end
@@ -5,13 +5,14 @@ module Radiator
5
5
  class Permission < Serializer
6
6
  def initialize(value)
7
7
  super(:permission, value)
8
- raise NotImplementedError, 'stub'
9
8
  end
10
9
 
11
10
  def to_bytes
11
+ pakHash(@value)
12
12
  end
13
13
 
14
14
  def to_s
15
+ @value.to_json
15
16
  end
16
17
  end
17
18
  end
@@ -37,18 +37,10 @@ module Radiator
37
37
  puts "#{level}: #{log_message}"
38
38
  end
39
39
  else
40
- if defined? @logger.ap
41
- if !!prefix
42
- @logger.ap log_level: level, prefix => obj
43
- else
44
- @logger.ap obj, level
45
- end
40
+ if !!prefix
41
+ @logger.ap log_level: level, prefix => obj
46
42
  else
47
- if !!prefix
48
- @logger.send level, ({prefix => obj}).inspect
49
- else
50
- @logger.send level, obj.inspect
51
- end
43
+ @logger.ap obj, level
52
44
  end
53
45
  end
54
46
 
@@ -1,4 +1,4 @@
1
1
  module Radiator
2
- VERSION = '0.3.15'
2
+ VERSION = '0.4.0pre1'
3
3
  AGENT_ID = "radiator/#{VERSION}"
4
4
  end
data/lib/radiator.rb CHANGED
@@ -1,6 +1,5 @@
1
1
  require 'radiator/version'
2
2
  require 'json'
3
- require 'awesome_print' if ENV['USE_AWESOME_PRINT'] == 'true'
4
3
 
5
4
  module Radiator
6
5
  require 'radiator/utils'
@@ -33,6 +32,9 @@ module Radiator
33
32
  require 'radiator/transaction'
34
33
  require 'radiator/base_error'
35
34
  require 'radiator/error_parser'
35
+ require 'radiator/mixins/acts_as_poster'
36
+ require 'radiator/mixins/acts_as_voter'
37
+ require 'radiator/mixins/acts_as_wallet'
36
38
  require 'radiator/chain'
37
39
  require 'steem'
38
40
  require 'golos'
data/lib/steem.rb CHANGED
@@ -5,4 +5,7 @@ class Steem < Radiator::Chain
5
5
  def initialize(options = {})
6
6
  super(options.merge(chain: :steem))
7
7
  end
8
+
9
+ alias steem_per_mvest base_per_mvest
10
+ alias steem_per_usd base_per_debt
8
11
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: radiator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.15
4
+ version: 0.4.0pre1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anthony Martin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-30 00:00:00.000000000 Z
11
+ date: 2018-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -342,6 +342,9 @@ files:
342
342
  - lib/radiator/logger.rb
343
343
  - lib/radiator/market_history_api.rb
344
344
  - lib/radiator/methods.json
345
+ - lib/radiator/mixins/acts_as_poster.rb
346
+ - lib/radiator/mixins/acts_as_voter.rb
347
+ - lib/radiator/mixins/acts_as_wallet.rb
345
348
  - lib/radiator/network_broadcast_api.rb
346
349
  - lib/radiator/operation.rb
347
350
  - lib/radiator/operation_ids.rb
@@ -378,12 +381,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
378
381
  version: '0'
379
382
  required_rubygems_version: !ruby/object:Gem::Requirement
380
383
  requirements:
381
- - - ">="
384
+ - - ">"
382
385
  - !ruby/object:Gem::Version
383
- version: '0'
386
+ version: 1.3.1
384
387
  requirements: []
385
388
  rubyforge_project:
386
- rubygems_version: 2.6.14
389
+ rubygems_version: 2.6.11
387
390
  signing_key:
388
391
  specification_version: 4
389
392
  summary: STEEM RPC Ruby Client