cosgrove 0.0.2 → 0.0.3rc1

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.
@@ -120,7 +120,7 @@ module Cosgrove
120
120
  end
121
121
  private
122
122
  def chain
123
- @chain ||= yml[:chain]
123
+ @chain_hash ||= yml[:chain]
124
124
  end
125
125
 
126
126
  def yml
@@ -4,18 +4,19 @@ module Cosgrove
4
4
  include ActionView::Helpers::NumberHelper
5
5
 
6
6
  def price_feed(chain = :steem)
7
- feed_history = api(chain).get_feed_history.result
8
- base_per_mvest = api(chain).steem_per_mvest
9
-
10
- current_median_history = feed_history.current_median_history
11
- base = current_median_history.base
12
- base = base.split(' ').first.to_f
13
- quote = current_median_history.quote
14
- quote = quote.split(' ').first.to_f
15
-
16
- base_per_debt = (base / quote) * base_per_mvest
17
-
18
- [base_per_mvest, base_per_debt]
7
+ api(chain).get_feed_history do |feed_history|
8
+ base_per_mvest = api(chain).steem_per_mvest
9
+
10
+ current_median_history = feed_history.current_median_history
11
+ base = current_median_history.base
12
+ base = base.split(' ').first.to_f
13
+ quote = current_median_history.quote
14
+ quote = quote.split(' ').first.to_f
15
+
16
+ base_per_debt = (base / quote) * base_per_mvest
17
+
18
+ [base_per_mvest, base_per_debt]
19
+ end
19
20
  end
20
21
 
21
22
  # https://api.vaultoro.com/#api-Basic_API-getMarkets
@@ -113,13 +114,12 @@ module Cosgrove
113
114
  if a =~ /.*\*$/
114
115
  wildcards = true
115
116
  lower_bound_name = a.split('*').first
116
- response = api(chain).lookup_accounts(a, 1000)
117
- result = response.result
118
-
119
- if result.any?
120
- account_names -= [a]
121
- account_names += [lower_bound_name]
122
- account_names += result.map { |name| name if name =~ /#{lower_bound_name}.*/ }.compact
117
+ api(chain).lookup_accounts(a, 1000) do |names, error|
118
+ if names.any?
119
+ account_names -= [a]
120
+ account_names += [lower_bound_name]
121
+ account_names += names.map { |name| name if name =~ /#{lower_bound_name}.*/ }.compact
122
+ end
123
123
  end
124
124
  end
125
125
  end
@@ -128,10 +128,21 @@ module Cosgrove
128
128
  accounts = SteemData::Account.where(:name.in => account_names)
129
129
  account = accounts.last
130
130
 
131
+ if accounts.size == 0
132
+ accounts = SteemApi::Account.where(name: account_names)
133
+ account = accounts.limit(1).last
134
+ end
135
+
131
136
  if accounts.count == account_names.size
132
- vests = accounts.sum('vesting_shares.amount')
133
- delegated_vests = accounts.sum('delegated_vesting_shares.amount')
134
- received_vests = accounts.sum('received_vesting_shares.amount')
137
+ if accounts.kind_of? Mongoid::Criteria
138
+ vests = accounts.sum('vesting_shares.amount')
139
+ delegated_vests = accounts.sum('delegated_vesting_shares.amount')
140
+ received_vests = accounts.sum('received_vesting_shares.amount')
141
+ else
142
+ vests = accounts.pluck(:vesting_shares).map(&:to_f).sum
143
+ delegated_vests = accounts.pluck(:delegated_vesting_shares).map(&:to_f).sum
144
+ received_vests = accounts.pluck(:received_vesting_shares).map(&:to_f).sum
145
+ end
135
146
  elsif !wildcards
136
147
  valid_names = accounts.distinct(:name)
137
148
  unknown_names = account_names - valid_names
@@ -141,11 +152,12 @@ module Cosgrove
141
152
  if accounts.count == 1 && vests == 0.0
142
153
  # Falling back to RPC because balance is out of date and we only want
143
154
  # a single account.
144
- response = api(:steem).get_accounts([account.name])
145
- account = response.result.first
146
- vests = account.vesting_shares.split(' ').first.to_f
147
- delegated_vests = account.delegated_vesting_shares.split(' ').first.to_f
148
- received_vests = account.received_vesting_shares.split(' ').first.to_f
155
+ api(:steem).get_accounts([account.name]) do |accounts|
156
+ account = accounts.first
157
+ vests = account.vesting_shares.split(' ').first.to_f
158
+ delegated_vests = account.delegated_vesting_shares.split(' ').first.to_f
159
+ received_vests = account.received_vesting_shares.split(' ').first.to_f
160
+ end
149
161
  end
150
162
 
151
163
  mvests = vests / 1000000
@@ -177,9 +189,13 @@ module Cosgrove
177
189
  "**#{pluralize(accounts.count, 'account')}:** `#{balance.join(' ')}`"
178
190
  end
179
191
  when :golos
180
- response = api(:golos).get_accounts(account_names)
181
- account = response.result.first
182
- gests = account.vesting_shares.split(' ').first.to_f
192
+ account = nil
193
+ gests = nil
194
+
195
+ api(:golos).get_accounts(account_names) do |accounts, error|
196
+ account = accounts.first
197
+ gests = account.vesting_shares.split(' ').first.to_f
198
+ end
183
199
 
184
200
  mgests = gests / 1000000
185
201
  golos = base_per_mvest * mgests
@@ -203,10 +219,10 @@ module Cosgrove
203
219
 
204
220
  case chain
205
221
  when :steem
206
- response = api(chain).get_reward_fund 'post'
207
- reward_fund = response.result
208
- total = reward_fund.reward_balance
209
- total = total.split(' ').first.to_f
222
+ total = api(chain).get_reward_fund('post') do |reward_fund|
223
+ reward_fund.reward_balance.split(' ').first.to_f
224
+ end
225
+
210
226
  total_usd = (total / base_per_mvest) * base_per_debt
211
227
  btx_total_usd = total * btx_usdt_steem
212
228
 
@@ -216,10 +232,10 @@ module Cosgrove
216
232
 
217
233
  "Total Reward Fund: `#{total} STEEM (Worth: #{total_usd} internally; #{btx_total_usd} on Bittrex)`"
218
234
  when :golos
219
- response = api(chain).get_dynamic_global_properties
220
- properties = response.result
221
- total = properties.total_reward_fund_steem
222
- total = total.split(' ').first.to_f
235
+ total = api(chain).get_dynamic_global_properties do |properties|
236
+ properties.total_reward_fund_steem.split(' ').first.to_f
237
+ end
238
+
223
239
  total_gbg = (total / base_per_mvest) * base_per_debt
224
240
  btx_total_usd = total * btx_usdt_golos
225
241
 
@@ -258,10 +274,9 @@ module Cosgrove
258
274
  sum_promoted = promoted.sum('amount.amount')
259
275
 
260
276
  base_per_mvest, base_per_debt = price_feed(chain)
261
- response = api(chain).get_reward_fund 'post'
262
- reward_fund = response.result
263
- total = reward_fund.reward_balance
264
- total = total.split(' ').first.to_f
277
+ total = api(chain).get_reward_fund('post') do |reward_fund|
278
+ reward_fund.reward_balance.split(' ').first.to_f
279
+ end
265
280
 
266
281
  total_usd = (total / base_per_mvest) * base_per_debt
267
282
  ratio = (sum_promoted / total_usd) * 100
@@ -274,23 +289,22 @@ module Cosgrove
274
289
 
275
290
  def supply(chain)
276
291
  base_per_mvest, base_per_debt = price_feed(chain)
277
-
278
- response = api(chain).get_dynamic_global_properties
279
- properties = response.result
292
+ properties = api(chain).get_dynamic_global_properties do |_properties, error|
293
+ _properties
294
+ end
295
+
280
296
  current_supply = properties.current_supply.split(' ').first.to_f
281
297
  current_debt_supply = properties.current_sbd_supply.split(' ').first.to_f
282
298
  total_vesting_fund_steem = properties.total_vesting_fund_steem.split(' ').first.to_f
283
-
284
299
  total_base = (current_supply / base_per_mvest) * base_per_debt
285
300
  ratio = (current_debt_supply / total_base) * 100
286
301
 
287
302
  supply = []
288
303
  case chain
289
304
  when :steem
290
- response = api(chain).get_reward_fund 'post'
291
- reward_fund = response.result
292
- reward_balance = reward_fund.reward_balance
293
- reward_balance = reward_balance.split(' ').first.to_f
305
+ reward_balance = api(chain).get_reward_fund('post') do |reward_fund|
306
+ reward_fund.reward_balance.split(' ').first.to_f
307
+ end
294
308
 
295
309
  liquid_supply = current_supply - reward_balance - total_vesting_fund_steem
296
310
  ratio_liquid = (liquid_supply / current_supply) * 100
@@ -306,7 +320,6 @@ module Cosgrove
306
320
  supply << ["#{current_debt_supply} SBD (#{ratio} of supply)"]
307
321
  supply << ["#{liquid_supply} Liquid STEEM (#{ratio_liquid} of supply)"]
308
322
  when :golos
309
- properties = response.result
310
323
  reward_balance = properties.total_reward_fund_steem
311
324
  reward_balance = reward_balance.split(' ').first.to_f
312
325
 
@@ -324,7 +337,6 @@ module Cosgrove
324
337
  supply << ["#{current_debt_supply} GBG (#{ratio} of supply)"]
325
338
  supply << ["#{liquid_supply} Liquid GOLOS (#{ratio_liquid} of supply)"]
326
339
  when :test
327
- properties = response.result
328
340
  reward_balance = properties.total_reward_fund_steem
329
341
  reward_balance = reward_balance.split(' ').first.to_f
330
342
 
@@ -358,9 +370,9 @@ module Cosgrove
358
370
 
359
371
  def debt_exchange_rate(chain = :steem, limit = 19)
360
372
  chain = chain.to_sym
361
- response = api(chain).get_witnesses_by_vote('', limit)
362
- witnesses = response.result
363
- rates = witnesses.map(&:sbd_exchange_rate)
373
+ rates = api(chain).get_witnesses_by_vote('', limit) do |witnesses|
374
+ witnesses.map(&:sbd_exchange_rate)
375
+ end
364
376
 
365
377
  symbol = case chain
366
378
  when :steem then 'SBD'
@@ -382,9 +394,9 @@ module Cosgrove
382
394
 
383
395
  def apr(chain = :steem, limit = 19)
384
396
  chain = chain.to_sym
385
- response = api(chain).get_witnesses_by_vote('', limit)
386
- witnesses = response.result
387
- rates = witnesses.map(&:props).map { |p| p['sbd_interest_rate'] }
397
+ rates = api(chain).get_witnesses_by_vote('', limit) do |witnesses|
398
+ witnesses.map(&:props).map { |p| p['sbd_interest_rate'] }
399
+ end
388
400
 
389
401
  rate = rates.sum / rates.size
390
402
  rate = rate / 100.0
@@ -393,9 +405,9 @@ module Cosgrove
393
405
 
394
406
  def effective_apr(chain = :steem)
395
407
  chain = chain.to_sym
396
- response = api(chain).get_dynamic_global_properties
397
- properties = response.result
398
- rate = properties.sbd_interest_rate
408
+ rate = api(chain).get_dynamic_global_properties do |properties|
409
+ properties.sbd_interest_rate
410
+ end
399
411
 
400
412
  rate = rate / 100.0
401
413
  number_to_percentage(rate, precision: 3)
@@ -403,9 +415,9 @@ module Cosgrove
403
415
 
404
416
  def effective_price(chain = :steem)
405
417
  chain = chain.to_sym
406
- response = api(chain).get_feed_history
407
- feed_history = response.result
408
- current_median_history = feed_history.current_median_history
418
+ current_median_history = api(chain).get_feed_history do |feed_history|
419
+ feed_history.current_median_history
420
+ end
409
421
 
410
422
  b = current_median_history.base.split(' ').first.to_f
411
423
  q = current_median_history.quote.split(' ').first.to_f
@@ -29,12 +29,16 @@ module Cosgrove
29
29
  end
30
30
 
31
31
  def mongo_behind_warning(event)
32
+ elapse = -1
33
+
32
34
  begin
33
35
  message = []
34
36
 
35
37
  if (blocks = head_block_number(:steem) - steem_data_head_block_number) > 1200
36
38
  elapse = blocks * 3
37
39
  message << "Mongo is behind by #{time_ago_in_words(elapse.seconds.ago)}."
40
+ else
41
+ 0
38
42
  end
39
43
 
40
44
  if message.size > 0
@@ -45,6 +49,8 @@ module Cosgrove
45
49
  sleep 15
46
50
  event.respond Cosgrove::SnarkCommands::WITTY.sample
47
51
  end
52
+
53
+ elapse
48
54
  end
49
55
 
50
56
  def cannot_find_input(event, message_prefix = "Unable to find that.")
@@ -62,16 +68,31 @@ module Cosgrove
62
68
 
63
69
  def append_link_details(event, slug)
64
70
  author_name, permlink = parse_slug slug
71
+ created = nil
72
+ cashout_time = nil
73
+
74
+ if slug =~ /steemit.com/
75
+ chain = :steem
76
+ elsif slug =~ /golos.io/
77
+ chain = :golos
78
+ elsif slug =~ /golos.blog/
79
+ chain = :golos
80
+ else
81
+ return # silntlly ignore this slug
82
+ end
65
83
 
66
- post = SteemData::Post.where(author: author_name, permlink: permlink).last
84
+ post = case chain
85
+ when :steem then SteemData::Post.where(author: author_name, permlink: permlink).last
86
+ when :golos then GolosCloud::Comment.where(author: author_name, permlink: permlink).last
87
+ end
67
88
 
68
89
  if post.nil?
69
90
  # Fall back to RPC
70
- response = api(:steem).get_content(author_name, permlink)
71
- unless response.result.author.empty?
72
- post = response.result
73
- created = Time.parse(post.created + 'Z')
74
- cashout_time = Time.parse(post.cashout_time + 'Z')
91
+ api(chain).get_content(author_name, permlink) do |content, errors|
92
+ unless content.author.empty?
93
+ created = Time.parse(content.created + 'Z')
94
+ cashout_time = Time.parse(content.cashout_time + 'Z')
95
+ end
75
96
  end
76
97
  end
77
98
 
@@ -98,7 +119,10 @@ module Cosgrove
98
119
 
99
120
  # Only append this detail of the post less than an hour old.
100
121
  if created > 1.hour.ago
101
- votes = SteemData::AccountOperation.type('vote').starting(post.created)
122
+ votes = case chain
123
+ when :steem then SteemData::AccountOperation.type('vote').starting(post.created)
124
+ when :golos then GolosCloud::Vote.where('timestamp > ?', post.created)
125
+ end
102
126
  total_votes = votes.count
103
127
  total_voters = votes.distinct(:voter).size
104
128
 
@@ -115,7 +139,7 @@ module Cosgrove
115
139
 
116
140
  begin
117
141
  event.respond details.join('; ')
118
- rescue Discordrb::Errors::NoPermission => e
142
+ rescue Discordrb::Errors::NoPermission => _
119
143
  puts "Unable to append link details on #{event.channel.server.name} in #{event.channel.name}"
120
144
  end
121
145
 
@@ -124,19 +148,41 @@ module Cosgrove
124
148
 
125
149
  def find_account(key, event = nil, chain = :steem)
126
150
  key = key.to_s.downcase
151
+ chain = chain.to_sym
127
152
 
128
- if (accounts = SteemData::Account.where(name: key)).any?
129
- return accounts.first
130
- elsif !!(cb_account = Cosgrove::Account.find_by_discord_id(key, chain))
131
- return SteemData::Account.find_by(name: cb_account.account_name)
132
- else
133
- # Fall back to RPC
134
- if !!key
135
- response = api(chain).get_accounts([key])
136
- return account = response.result.first
153
+ raise "Required argument: chain" if chain.nil?
154
+
155
+ if chain == :steem
156
+ account = if (accounts = SteemData::Account.where(name: key)).any?
157
+ accounts.first
137
158
  end
159
+ end
160
+
161
+ if account.nil?
162
+ account = if !!(cb_account = Cosgrove::Account.find_by_discord_id(key, chain))
163
+ cb_account.chain_account
164
+ end
165
+ end
166
+
167
+ if account.nil?
168
+ account = if !!key
169
+ if chain == :steem && (accounts = SteemApi::Account.where(name: key)).any?
170
+ accounts.first
171
+ elsif chain == :golos && (accounts = GolosCloud::Account.where(name: key)).any?
172
+ accounts.first
173
+ else
174
+ # Fall back to RPC
175
+ api(chain).get_accounts([key]) do |_accounts, errors|
176
+ _accounts.first
177
+ end
178
+ end
179
+ end
180
+ end
138
181
 
139
- unknown_account(key, event) unless !!account
182
+ if account.nil?
183
+ unknown_account(key, event)
184
+ else
185
+ account
140
186
  end
141
187
  end
142
188
 
@@ -204,9 +250,12 @@ module Cosgrove
204
250
  count = -1
205
251
  until count == ignoring.size
206
252
  count = ignoring.size
207
- response = follow_api(chain).get_following(a, ignoring.last, 'ignore', 100)
208
- ignoring += response.result.map(&:following)
209
- ignoring = ignoring.uniq
253
+ follow_api(chain).get_following(a, ignoring.last, 'ignore', 100) do |ignores, errors|
254
+ next unless defined? ignores.following
255
+
256
+ ignoring += ignores.map(&:following)
257
+ ignoring = ignoring.uniq
258
+ end
210
259
  end
211
260
  muted += ignoring
212
261
  end
@@ -22,7 +22,13 @@ module Cosgrove
22
22
  muters << steem_account
23
23
  muted = muted by: muters, chain: :steem
24
24
 
25
- posts = SteemData::Post.root_posts.where(author: author_name, permlink: permlink)
25
+ post = find_comment(author: author_name, permlink: permlink)
26
+
27
+ if post.nil?
28
+ cannot_find_input(event)
29
+ return
30
+ end
31
+
26
32
  votes_today = SteemData::AccountOperation.type('vote').where(voter: steem_account).today
27
33
  today_count = votes_today.count
28
34
  author_count = votes_today.where(author: author_name).count
@@ -32,27 +38,15 @@ module Cosgrove
32
38
  author_count.to_f / today_count
33
39
  end
34
40
 
35
- post = posts.first
36
-
37
- if post.nil?
38
- # Fall back to RPC
39
- response = api(:steem).get_content(author_name, permlink)
40
- unless response.result.author.empty?
41
- post = response.result
42
- created = Time.parse(post.created + 'Z')
43
- cashout_time = Time.parse(post.cashout_time + 'Z')
44
- end
45
- end
46
-
47
- if post.nil?
48
- cannot_find_input(event)
49
- return
50
- end
51
-
52
41
  created ||= post.created
53
42
  cashout_time ||= post.cashout_time
54
43
  root_post = post.parent_author == ''
55
44
 
45
+ if created.class == String
46
+ created = Time.parse(created + 'Z')
47
+ cashout_time = Time.parse(cashout_time + 'Z')
48
+ end
49
+
56
50
  nope = if created > 1.minute.ago
57
51
  "Give it a second! It's going to SPACE! Can you give it a second to come back from space?"
58
52
  elsif created > 20.minutes.ago
@@ -103,19 +97,63 @@ module Cosgrove
103
97
  }
104
98
 
105
99
  tx = new_tx :steem
106
- op = Radiator::Operation.new(vote)
107
- tx.operations << op
108
- response = tx.process(true)
109
-
110
- ap response.to_json
100
+ tx.operations << vote
101
+ friendy_error = nil
102
+
103
+ loop do
104
+ begin
105
+ response = tx.process(true)
106
+ rescue => e
107
+ puts "Unable to vote: #{e}"
108
+ ap e
109
+ end
110
+
111
+ if !!response && !!response.error
112
+ message = response.error.message
113
+ if message.to_s =~ /missing required posting authority/
114
+ friendy_error = "Failed: Check posting key."
115
+ break
116
+ elsif message.to_s =~ /You have already voted in a similar way./
117
+ friendy_error = "Failed: duplicate vote."
118
+ break
119
+ elsif message.to_s =~ /Can only vote once every 3 seconds./
120
+ puts "Retrying: voting too quickly."
121
+ sleep 3
122
+ redo
123
+ elsif message.to_s =~ /Voting weight is too small, please accumulate more voting power or steem power./
124
+ friendy_error = "Failed: voting weight too small"
125
+ break
126
+ elsif message.to_s =~ /unknown key/
127
+ friendy_error = "Failed: unknown key (testing?)"
128
+ break
129
+ elsif message.to_s =~ /tapos_block_summary/
130
+ puts "Retrying vote/comment: tapos_block_summary (?)"
131
+ redo
132
+ elsif message.to_s =~ /now < trx.expiration/
133
+ puts "Retrying vote/comment: now < trx.expiration (?)"
134
+ redo
135
+ elsif message.to_s =~ /signature is not canonical/
136
+ puts "Retrying vote/comment: signature was not canonical (bug in Radiator?)"
137
+ redo
138
+ elsif message.to_s =~ /STEEMIT_UPVOTE_LOCKOUT_HF17/
139
+ friendy_error = "Failed: upvote lockout (last twelve hours before payout)"
140
+ break
141
+ else
142
+ friendy_error = 'Unable to vote right now. Maybe I already voted on that. Try again later.'
143
+ ap e
144
+ ap e.backtrace
145
+ break
146
+ end
147
+ end
148
+
149
+ break
150
+ end
111
151
 
112
- if !!response.error
113
- 'Unable to vote right now. Maybe I already voted on that. Try again later.'
152
+ if !!friendy_error
153
+ friendy_error
114
154
  elsif !!response.result.id
115
- # if created > 30.minutes.ago
116
- # event.respond "*#{SteemSlap.slap(event.author.display_name)}*"
117
- # end
118
-
155
+ ap response.to_json
156
+
119
157
  if !!@on_success
120
158
  begin
121
159
  @on_success.call(event, "@#{post.author}/#{post.permlink}")