steem-ruby 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +7 -7
- data/README.md +4 -4
- data/lib/steem/api.rb +1 -1
- data/lib/steem/base_error.rb +50 -32
- data/lib/steem/broadcast.rb +53 -28
- data/lib/steem/mixins/retriable.rb +10 -13
- data/lib/steem/rpc/base_client.rb +2 -2
- data/lib/steem/rpc/http_client.rb +1 -1
- data/lib/steem/transaction_builder.rb +106 -42
- data/lib/steem/type/amount.rb +48 -8
- data/lib/steem/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0d2df68c704478da2f78e2cdee3a423523950f27
|
4
|
+
data.tar.gz: f8e6912e7b808be2bb7c065dfb177d0ef6a98a53
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b93714f563a05179fdbcf1c45af4e2279047343b86d1e932bb5ea306a8c7a508f8769b8a22a9415f4344effd591d0f5f86bcfc02a004bf34478fdd140a599ec
|
7
|
+
data.tar.gz: 12bf547182d8a9abae9d0182cb21f509e176c46f283b3683cebc7b57fc9efb6b3cdabf94538ba1b86550824e5483526257b13d45476d63bf7402bff5b393902e
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
steem-ruby (0.9.
|
4
|
+
steem-ruby (0.9.1)
|
5
5
|
bitcoin-ruby (~> 0.0, >= 0.0.18)
|
6
6
|
ffi (~> 1.9, >= 1.9.23)
|
7
7
|
hashie (~> 3.5, >= 3.5.7)
|
@@ -18,8 +18,8 @@ GEM
|
|
18
18
|
coderay (1.1.2)
|
19
19
|
crack (0.4.3)
|
20
20
|
safe_yaml (~> 1.0.0)
|
21
|
-
docile (1.3.
|
22
|
-
ffi (1.9.
|
21
|
+
docile (1.3.1)
|
22
|
+
ffi (1.9.25)
|
23
23
|
hashdiff (0.3.7)
|
24
24
|
hashie (3.5.7)
|
25
25
|
json (2.1.0)
|
@@ -28,8 +28,8 @@ GEM
|
|
28
28
|
little-plugger (~> 1.1)
|
29
29
|
multi_json (~> 1.10)
|
30
30
|
method_source (0.9.0)
|
31
|
-
minitest (5.
|
32
|
-
minitest-line (0.6.
|
31
|
+
minitest (5.11.3)
|
32
|
+
minitest-line (0.6.5)
|
33
33
|
minitest (~> 5.0)
|
34
34
|
minitest-proveit (1.0.0)
|
35
35
|
minitest (> 5, < 7)
|
@@ -46,11 +46,11 @@ GEM
|
|
46
46
|
simplecov-html (~> 0.10.0)
|
47
47
|
simplecov-html (0.10.2)
|
48
48
|
vcr (4.0.0)
|
49
|
-
webmock (3.
|
49
|
+
webmock (3.4.2)
|
50
50
|
addressable (>= 2.3.6)
|
51
51
|
crack (>= 0.3.2)
|
52
52
|
hashdiff
|
53
|
-
yard (0.9.
|
53
|
+
yard (0.9.14)
|
54
54
|
|
55
55
|
PLATFORMS
|
56
56
|
ruby
|
data/README.md
CHANGED
@@ -13,7 +13,7 @@ Full documentation: http://www.rubydoc.info/gems/steem-ruby
|
|
13
13
|
|
14
14
|
The `steem-ruby` gem was written from the ground up by `@inertia`, who is also the author of [`radiator`](https://github.com/inertia186/radiator).
|
15
15
|
|
16
|
-
> "I intend to continue work on `radiator` indefinitely. But in `radiator-0.5`, I intend to refactor `radiator` so that is uses `steem-ruby` as its core. This means that some features of `radiator` like Serialization will become redundant. I think it's still useful for radiator to do its own
|
16
|
+
> "I intend to continue work on `radiator` indefinitely. But in `radiator-0.5`, I intend to refactor `radiator` so that is uses `steem-ruby` as its core. This means that some features of `radiator` like Serialization will become redundant. I think it's still useful for radiator to do its own serialization because it reduces the number of API requests." - @inertia
|
17
17
|
|
18
18
|
| `radiator` | `steem-ruby` |
|
19
19
|
|-|-|
|
@@ -90,7 +90,7 @@ end
|
|
90
90
|
In addition to signing with multiple `wif` private keys, it is possible to also export a partially signed transaction to have signing completed by someone else.
|
91
91
|
|
92
92
|
```ruby
|
93
|
-
builder = TransactionBuilder.new(wif: wif1)
|
93
|
+
builder = Steem::TransactionBuilder.new(wif: wif1)
|
94
94
|
|
95
95
|
builder.put(vote: {
|
96
96
|
voter: voter,
|
@@ -110,8 +110,8 @@ Then send the contents of `trx.json` to the other signing party so they can priv
|
|
110
110
|
|
111
111
|
```ruby
|
112
112
|
trx = open('trx.json').read
|
113
|
-
builder = TransactionBuilder.new(wif: wif2, trx: trx)
|
114
|
-
api = Steem::
|
113
|
+
builder = Steem::TransactionBuilder.new(wif: wif2, trx: trx)
|
114
|
+
api = Steem::CondenserApi.new
|
115
115
|
trx = builder.transaction
|
116
116
|
api.broadcast_transaction_synchronous(trx: trx)
|
117
117
|
```
|
data/lib/steem/api.rb
CHANGED
@@ -39,7 +39,7 @@ module Steem
|
|
39
39
|
attr_accessor :chain, :methods
|
40
40
|
|
41
41
|
# Use this for debugging naive thread handler.
|
42
|
-
# DEFAULT_RPC_CLIENT_CLASS = RPC::
|
42
|
+
# DEFAULT_RPC_CLIENT_CLASS = RPC::HttpClient
|
43
43
|
DEFAULT_RPC_CLIENT_CLASS = RPC::ThreadSafeHttpClient
|
44
44
|
|
45
45
|
def self.api_name=(api_name)
|
data/lib/steem/base_error.rb
CHANGED
@@ -15,131 +15,148 @@ module Steem
|
|
15
15
|
|
16
16
|
def self.build_error(error, context)
|
17
17
|
if error.message == 'Unable to acquire database lock'
|
18
|
-
raise Steem::RemoteDatabaseLockError, error.message,
|
18
|
+
raise Steem::RemoteDatabaseLockError, error.message, build_backtrace(error)
|
19
19
|
end
|
20
20
|
|
21
21
|
if error.message.include? 'Internal Error'
|
22
|
-
raise Steem::RemoteNodeError.new, error.message,
|
22
|
+
raise Steem::RemoteNodeError.new, error.message, build_backtrace(error)
|
23
23
|
end
|
24
24
|
|
25
25
|
if error.message.include? 'plugin not enabled'
|
26
|
-
raise Steem::PluginNotEnabledError, error.message,
|
26
|
+
raise Steem::PluginNotEnabledError, error.message, build_backtrace(error)
|
27
27
|
end
|
28
28
|
|
29
29
|
if error.message.include? 'argument'
|
30
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
30
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
31
31
|
end
|
32
32
|
|
33
33
|
if error.message.start_with? 'Bad Cast:'
|
34
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
34
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
35
35
|
end
|
36
36
|
|
37
37
|
if error.message.include? 'prefix_len'
|
38
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
38
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
39
39
|
end
|
40
40
|
|
41
41
|
if error.message.include? 'Parse Error'
|
42
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
42
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
43
43
|
end
|
44
44
|
|
45
45
|
if error.message.include? 'unknown key'
|
46
|
-
raise Steem::ArgumentError, "#{context}: #{error.message} (or content has been deleted)",
|
46
|
+
raise Steem::ArgumentError, "#{context}: #{error.message} (or content has been deleted)", build_backtrace(error)
|
47
47
|
end
|
48
48
|
|
49
49
|
if error.message.include? 'Comment is not in account\'s comments'
|
50
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
50
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
51
51
|
end
|
52
52
|
|
53
53
|
if error.message.include? 'Could not find comment'
|
54
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
54
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
55
55
|
end
|
56
56
|
|
57
57
|
if error.message.include? 'unable to convert ISO-formatted string to fc::time_point_sec'
|
58
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
58
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
59
59
|
end
|
60
60
|
|
61
61
|
if error.message.include? 'Input data have to treated as object.'
|
62
|
-
raise Steem::ArgumentError, "#{context}: #{error.message}",
|
62
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
63
|
+
end
|
64
|
+
|
65
|
+
if error.message.include? 'base.amount > share_type(0)'
|
66
|
+
raise Steem::ArgumentError, "#{context}: #{error.message}", build_backtrace(error)
|
63
67
|
end
|
64
68
|
|
65
69
|
if error.message.include? 'blk->transactions.size() > itr->trx_in_block'
|
66
|
-
raise Steem::VirtualOperationsNotAllowedError, "#{context}: #{error.message}",
|
70
|
+
raise Steem::VirtualOperationsNotAllowedError, "#{context}: #{error.message}", build_backtrace(error)
|
67
71
|
end
|
68
72
|
|
69
73
|
if error.message.include? 'A transaction must have at least one operation'
|
70
|
-
raise Steem::EmptyTransactionError, "#{context}: #{error.message}",
|
74
|
+
raise Steem::EmptyTransactionError, "#{context}: #{error.message}", build_backtrace(error)
|
71
75
|
end
|
72
76
|
|
73
77
|
if error.message.include? 'transaction expiration exception'
|
74
|
-
raise Steem::TransactionExpiredError, "#{context}: #{error.message}",
|
78
|
+
raise Steem::TransactionExpiredError, "#{context}: #{error.message}", build_backtrace(error)
|
75
79
|
end
|
76
80
|
|
77
81
|
if error.message.include? 'Duplicate transaction check failed'
|
78
|
-
raise Steem::DuplicateTransactionError, "#{context}: #{error.message}",
|
82
|
+
raise Steem::DuplicateTransactionError, "#{context}: #{error.message}", build_backtrace(error)
|
79
83
|
end
|
80
84
|
|
81
85
|
if error.message.include? 'signature is not canonical'
|
82
|
-
raise Steem::NonCanonicalSignatureError, "#{context}: #{error.message}",
|
86
|
+
raise Steem::NonCanonicalSignatureError, "#{context}: #{error.message}", build_backtrace(error)
|
83
87
|
end
|
84
88
|
|
85
89
|
if error.message.include? 'attempting to push a block that is too old'
|
86
|
-
raise Steem::BlockTooOldError, "#{context}: #{error.message}",
|
90
|
+
raise Steem::BlockTooOldError, "#{context}: #{error.message}", build_backtrace(error)
|
87
91
|
end
|
88
92
|
|
89
93
|
if error.message.include? 'irrelevant signature'
|
90
|
-
raise Steem::IrrelevantSignatureError, "#{context}: #{error.message}",
|
94
|
+
raise Steem::IrrelevantSignatureError, "#{context}: #{error.message}", build_backtrace(error)
|
91
95
|
end
|
92
96
|
|
93
97
|
if error.message.include? 'missing required posting authority'
|
94
|
-
raise Steem::MissingPostingAuthorityError, "#{context}: #{error.message}",
|
98
|
+
raise Steem::MissingPostingAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
95
99
|
end
|
96
100
|
|
97
101
|
if error.message.include? 'missing required active authority'
|
98
|
-
raise Steem::MissingActiveAuthorityError, "#{context}: #{error.message}",
|
102
|
+
raise Steem::MissingActiveAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
99
103
|
end
|
100
104
|
|
101
105
|
if error.message.include? 'missing required owner authority'
|
102
|
-
raise Steem::MissingOwnerAuthorityError, "#{context}: #{error.message}",
|
106
|
+
raise Steem::MissingOwnerAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
103
107
|
end
|
104
108
|
|
105
109
|
if error.message.include? 'missing required other authority'
|
106
|
-
raise Steem::MissingOtherAuthorityError, "#{context}: #{error.message}",
|
110
|
+
raise Steem::MissingOtherAuthorityError, "#{context}: #{error.message}", build_backtrace(error)
|
111
|
+
end
|
112
|
+
|
113
|
+
if error.message.include? 'Bad or missing upstream response'
|
114
|
+
raise Steem::BadOrMissingUpstreamResponseError, "#{context}: #{error.message}", build_backtrace(error)
|
107
115
|
end
|
108
116
|
|
109
117
|
if error.message.include? 'operator has disabled operation indexing by transaction_id'
|
110
|
-
raise Steem::TransactionIndexDisabledError, "#{context}: #{error.message}",
|
118
|
+
raise Steem::TransactionIndexDisabledError, "#{context}: #{error.message}", build_backtrace(error)
|
111
119
|
end
|
112
120
|
|
113
121
|
if error.message.include? 'is_valid_account_name'
|
114
|
-
raise Steem::InvalidAccountError, "#{context}: #{error.message}",
|
122
|
+
raise Steem::InvalidAccountError, "#{context}: #{error.message}", build_backtrace(error)
|
115
123
|
end
|
116
124
|
|
117
125
|
if error.message.include? 'Invalid operation name'
|
118
|
-
raise Steem::UnknownOperationError, "#{context}: #{error.message}",
|
126
|
+
raise Steem::UnknownOperationError, "#{context}: #{error.message}", build_backtrace(error)
|
127
|
+
end
|
128
|
+
|
129
|
+
if error.message =~ /Invalid object name: .+_operation/
|
130
|
+
raise Steem::UnknownOperationError, "#{context}: #{error.message}", build_backtrace(error)
|
119
131
|
end
|
120
132
|
|
121
133
|
if error.message.include? 'Author not found'
|
122
|
-
raise Steem::AuthorNotFoundError, "#{context}: #{error.message}",
|
134
|
+
raise Steem::AuthorNotFoundError, "#{context}: #{error.message}", build_backtrace(error)
|
123
135
|
end
|
124
136
|
|
125
137
|
if error.message.include? ' != fc::time_point_sec::maximum()'
|
126
|
-
raise Steem::ReachedMaximumTimeError, "#{context}: #{error.message}",
|
138
|
+
raise Steem::ReachedMaximumTimeError, "#{context}: #{error.message}", build_backtrace(error)
|
127
139
|
end
|
128
140
|
|
129
141
|
if error.message.include? 'Cannot transfer a negative amount (aka: stealing)'
|
130
|
-
raise Steem::TheftError, "#{context}: #{error.message}",
|
142
|
+
raise Steem::TheftError, "#{context}: #{error.message}", build_backtrace(error)
|
131
143
|
end
|
132
144
|
|
133
145
|
if error.message.include? 'Must transfer a nonzero amount'
|
134
|
-
raise Steem::NonZeroRequiredError, "#{context}: #{error.message}",
|
146
|
+
raise Steem::NonZeroRequiredError, "#{context}: #{error.message}", build_backtrace(error)
|
135
147
|
end
|
136
148
|
|
137
149
|
if error.message.include? 'is_asset_type'
|
138
|
-
raise Steem::UnexpectedAssetError, "#{context}: #{error.message}",
|
150
|
+
raise Steem::UnexpectedAssetError, "#{context}: #{error.message}", build_backtrace(error)
|
139
151
|
end
|
140
152
|
|
141
153
|
puts JSON.pretty_generate(error) if ENV['DEBUG']
|
142
|
-
raise UnknownError, "#{context}: #{error.message}",
|
154
|
+
raise UnknownError, "#{context}: #{error.message}", build_backtrace(error)
|
155
|
+
end
|
156
|
+
private
|
157
|
+
def self.build_backtrace(error)
|
158
|
+
backtrace = Thread.current.backtrace.reject{ |line| line =~ /base_error/ }
|
159
|
+
JSON.pretty_generate(error) + "\n" + backtrace.join("\n")
|
143
160
|
end
|
144
161
|
end
|
145
162
|
|
@@ -169,6 +186,7 @@ module Steem
|
|
169
186
|
class MissingOtherAuthorityError < MissingAuthorityError; end
|
170
187
|
class IncorrectRequestIdError < BaseError; end
|
171
188
|
class IncorrectResponseIdError < BaseError; end
|
189
|
+
class BadOrMissingUpstreamResponseError < BaseError; end
|
172
190
|
class TransactionIndexDisabledError < BaseError; end
|
173
191
|
class NotAppBaseError < BaseError; end
|
174
192
|
class UnknownApiError < BaseError; end
|
data/lib/steem/broadcast.rb
CHANGED
@@ -32,7 +32,7 @@ module Steem
|
|
32
32
|
class Broadcast
|
33
33
|
extend Retriable
|
34
34
|
|
35
|
-
DEFAULT_MAX_ACCEPTED_PAYOUT = Type::Amount.new(
|
35
|
+
DEFAULT_MAX_ACCEPTED_PAYOUT = Type::Amount.new(amount: '1000000000', precision: 3, nai: '@@000000013')
|
36
36
|
|
37
37
|
# This operation is used to cast a vote on a post/comment.
|
38
38
|
#
|
@@ -174,9 +174,9 @@ module Steem
|
|
174
174
|
}]]
|
175
175
|
|
176
176
|
max_accepted_payout = if params.keys.include? :max_accepted_payout
|
177
|
-
|
177
|
+
normalize_amount(options.merge amount: params[:max_accepted_payout])
|
178
178
|
else
|
179
|
-
DEFAULT_MAX_ACCEPTED_PAYOUT
|
179
|
+
normalize_amount(options.merge amount: DEFAULT_MAX_ACCEPTED_PAYOUT)
|
180
180
|
end
|
181
181
|
|
182
182
|
allow_votes = if params.keys.include? :allow_votes
|
@@ -274,7 +274,7 @@ module Steem
|
|
274
274
|
params = options[:params]
|
275
275
|
check_required_fields(params, *required_fields)
|
276
276
|
|
277
|
-
params[:amount] =
|
277
|
+
params[:amount] = normalize_amount(options.merge amount: params[:amount])
|
278
278
|
|
279
279
|
ops = [[:transfer, params]]
|
280
280
|
|
@@ -310,7 +310,7 @@ module Steem
|
|
310
310
|
params = options[:params]
|
311
311
|
check_required_fields(params, *required_fields)
|
312
312
|
|
313
|
-
params[:amount] =
|
313
|
+
params[:amount] = normalize_amount(options.merge amount: params[:amount])
|
314
314
|
|
315
315
|
ops = [[:transfer_to_vesting, params]]
|
316
316
|
|
@@ -336,7 +336,7 @@ module Steem
|
|
336
336
|
params = options[:params]
|
337
337
|
check_required_fields(params, *required_fields)
|
338
338
|
|
339
|
-
params[:vesting_shares] =
|
339
|
+
params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares])
|
340
340
|
|
341
341
|
ops = [[:withdraw_vesting, params]]
|
342
342
|
|
@@ -363,8 +363,8 @@ module Steem
|
|
363
363
|
params = options[:params]
|
364
364
|
check_required_fields(params, *required_fields)
|
365
365
|
|
366
|
-
params[:amount_to_sell] =
|
367
|
-
params[:min_to_receive] =
|
366
|
+
params[:amount_to_sell] = normalize_amount(options.merge amount: params[:amount_to_sell])
|
367
|
+
params[:min_to_receive] = normalize_amount(options.merge amount: params[:min_to_receive])
|
368
368
|
|
369
369
|
if !!params[:expiration]
|
370
370
|
params[:expiration] = Time.parse(params[:expiration].to_s)
|
@@ -414,8 +414,8 @@ module Steem
|
|
414
414
|
exchange_rate = params[:exchange_rate] rescue nil || {}
|
415
415
|
base = exchange_rate[:base]
|
416
416
|
quote = exchange_rate[:quote]
|
417
|
-
params[:exchange_rate][:base] =
|
418
|
-
params[:exchange_rate][:quote] =
|
417
|
+
params[:exchange_rate][:base] = normalize_amount(options.merge amount: base)
|
418
|
+
params[:exchange_rate][:quote] = normalize_amount(options.merge amount: quote)
|
419
419
|
|
420
420
|
ops = [[:feed_publish, params]]
|
421
421
|
|
@@ -438,7 +438,7 @@ module Steem
|
|
438
438
|
params = options[:params]
|
439
439
|
check_required_fields(params, *required_fields)
|
440
440
|
|
441
|
-
params[:amount] =
|
441
|
+
params[:amount] = normalize_amount(options.merge amount: params[:amount])
|
442
442
|
|
443
443
|
ops = [[:convert, params]]
|
444
444
|
|
@@ -502,7 +502,7 @@ module Steem
|
|
502
502
|
|
503
503
|
check_required_fields(params, *required_fields)
|
504
504
|
|
505
|
-
params[:fee] =
|
505
|
+
params[:fee] = normalize_amount(options.merge amount: params[:fee])
|
506
506
|
|
507
507
|
ops = [[:account_create, params]]
|
508
508
|
|
@@ -603,8 +603,8 @@ module Steem
|
|
603
603
|
check_required_fields(params, *required_fields)
|
604
604
|
|
605
605
|
account_creation_fee = params[:props][:account_creation_fee] rescue nil
|
606
|
-
params[:props][:account_creation_fee] =
|
607
|
-
params[:fee] =
|
606
|
+
params[:props][:account_creation_fee] = normalize_amount(options.merge amount: account_creation_fee)
|
607
|
+
params[:fee] = normalize_amount(options.merge amount: params[:fee])
|
608
608
|
|
609
609
|
ops = [[:witness_update, params]]
|
610
610
|
|
@@ -844,9 +844,9 @@ module Steem
|
|
844
844
|
|
845
845
|
check_required_fields(params, *required_fields)
|
846
846
|
|
847
|
-
params[:sbd_amount] =
|
848
|
-
params[:steem_amount] =
|
849
|
-
params[:fee] =
|
847
|
+
params[:sbd_amount] = normalize_amount(options.merge amount: params[:sbd_amount])
|
848
|
+
params[:steem_amount] = normalize_amount(options.merge amount: params[:steem_amount])
|
849
|
+
params[:fee] = normalize_amount(options.merge amount: params[:fee])
|
850
850
|
|
851
851
|
params[:ratification_deadline] = Time.parse(params[:ratification_deadline].to_s)
|
852
852
|
params[:ratification_deadline] = params[:ratification_deadline].strftime('%Y-%m-%dT%H:%M:%S')
|
@@ -905,8 +905,8 @@ module Steem
|
|
905
905
|
params = options[:params]
|
906
906
|
check_required_fields(params, *required_fields)
|
907
907
|
|
908
|
-
params[:sbd_amount] =
|
909
|
-
params[:steem_amount] =
|
908
|
+
params[:sbd_amount] = normalize_amount(options.merge amount: params[:sbd_amount])
|
909
|
+
params[:steem_amount] = normalize_amount(options.merge amount: params[:steem_amount])
|
910
910
|
|
911
911
|
ops = [[:escrow_release, params]]
|
912
912
|
|
@@ -954,7 +954,7 @@ module Steem
|
|
954
954
|
check_required_fields(params, *required_fields)
|
955
955
|
|
956
956
|
params[:memo] ||= ''
|
957
|
-
params[:amount] =
|
957
|
+
params[:amount] = normalize_amount(options.merge amount: params[:amount])
|
958
958
|
|
959
959
|
ops = [[:transfer_to_savings, params]]
|
960
960
|
|
@@ -977,7 +977,7 @@ module Steem
|
|
977
977
|
check_required_fields(params, *required_fields)
|
978
978
|
|
979
979
|
params[:memo] ||= ''
|
980
|
-
params[:amount] =
|
980
|
+
params[:amount] = normalize_amount(options.merge amount: params[:amount])
|
981
981
|
|
982
982
|
ops = [[:transfer_from_savings, params]]
|
983
983
|
|
@@ -1039,7 +1039,7 @@ module Steem
|
|
1039
1039
|
params = options[:params]
|
1040
1040
|
check_required_fields(params, *required_fields)
|
1041
1041
|
|
1042
|
-
params[:vesting_shares] =
|
1042
|
+
params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares])
|
1043
1043
|
ops = [[:delegate_vesting_shares, params]]
|
1044
1044
|
|
1045
1045
|
process(options.merge(ops: ops), &block)
|
@@ -1075,8 +1075,8 @@ module Steem
|
|
1075
1075
|
|
1076
1076
|
check_required_fields(params, *required_fields)
|
1077
1077
|
|
1078
|
-
params[:fee] =
|
1079
|
-
params[:delegation] =
|
1078
|
+
params[:fee] = normalize_amount(options.merge amount: params[:fee])
|
1079
|
+
params[:delegation] = normalize_amount(options.merge amount: params[:delegation])
|
1080
1080
|
params[:extensions] ||= []
|
1081
1081
|
|
1082
1082
|
ops = [[:account_create_with_delegation, params]]
|
@@ -1097,9 +1097,17 @@ module Steem
|
|
1097
1097
|
trx = tx.transaction
|
1098
1098
|
|
1099
1099
|
response = if !!options[:pretend]
|
1100
|
-
|
1100
|
+
if !!options[:app_base]
|
1101
|
+
database_api(options).verify_authority(trx: trx)
|
1102
|
+
else
|
1103
|
+
database_api(options).verify_authority(trx)
|
1104
|
+
end
|
1101
1105
|
else
|
1102
|
-
|
1106
|
+
if !!options[:app_base]
|
1107
|
+
network_broadcast_api(options).broadcast_transaction(trx: trx)
|
1108
|
+
else
|
1109
|
+
network_broadcast_api(options).broadcast_transaction_synchronous(trx)
|
1110
|
+
end
|
1103
1111
|
end
|
1104
1112
|
|
1105
1113
|
break
|
@@ -1120,13 +1128,30 @@ module Steem
|
|
1120
1128
|
end
|
1121
1129
|
private
|
1122
1130
|
# @private
|
1131
|
+
def self.normalize_amount(options)
|
1132
|
+
if !!options[:app_base]
|
1133
|
+
Type::Amount.to_h(options[:amount])
|
1134
|
+
else
|
1135
|
+
Type::Amount.to_s(options[:amount])
|
1136
|
+
end
|
1137
|
+
end
|
1138
|
+
|
1139
|
+
# @privats
|
1123
1140
|
def self.database_api(options)
|
1124
|
-
options[:database_api] ||=
|
1141
|
+
options[:database_api] ||= if !!options[:app_base]
|
1142
|
+
Steem::DatabaseApi.new(options)
|
1143
|
+
else
|
1144
|
+
Steem::CondenserApi.new(options)
|
1145
|
+
end
|
1125
1146
|
end
|
1126
1147
|
|
1127
1148
|
# @private
|
1128
1149
|
def self.network_broadcast_api(options)
|
1129
|
-
options[:network_broadcast_api] ||=
|
1150
|
+
options[:network_broadcast_api] ||= if !!options[:app_base]
|
1151
|
+
Steem::NetworkBroadcaseApi.new(options)
|
1152
|
+
else
|
1153
|
+
Steem::CondenserApi.new(options)
|
1154
|
+
end
|
1130
1155
|
end
|
1131
1156
|
|
1132
1157
|
# @private
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Steem
|
2
2
|
module Retriable
|
3
3
|
# @private
|
4
|
-
MAX_RETRY_COUNT =
|
4
|
+
MAX_RETRY_COUNT = 30
|
5
5
|
|
6
|
-
|
7
|
-
MAX_BACKOFF = 30
|
6
|
+
MAX_RETRY_ELAPSE = 60
|
8
7
|
|
9
|
-
|
8
|
+
# @private
|
9
|
+
MAX_BACKOFF = MAX_RETRY_ELAPSE / 4
|
10
10
|
|
11
11
|
RETRYABLE_EXCEPTIONS = [
|
12
12
|
NonCanonicalSignatureError, IncorrectRequestIdError,
|
@@ -19,14 +19,7 @@ module Steem
|
|
19
19
|
def backoff
|
20
20
|
@backoff ||= 0.1
|
21
21
|
@backoff *= 2
|
22
|
-
if @backoff > MAX_BACKOFF
|
23
|
-
@backoff = 0.1
|
24
|
-
|
25
|
-
if Time.now.utc - @first_retry_at > MAX_RETRY_ELAPSE
|
26
|
-
@retry_count = nil
|
27
|
-
@first_retry_at = nil
|
28
|
-
end
|
29
|
-
end
|
22
|
+
@backoff = 0.1 if @backoff > MAX_BACKOFF
|
30
23
|
|
31
24
|
sleep @backoff
|
32
25
|
end
|
@@ -37,7 +30,11 @@ module Steem
|
|
37
30
|
|
38
31
|
return false if @retry_count >= MAX_RETRY_COUNT
|
39
32
|
|
40
|
-
@retry_count
|
33
|
+
@retry_count = if Time.now.utc - @first_retry_at > MAX_RETRY_ELAPSE
|
34
|
+
@first_retry_at = nil
|
35
|
+
else
|
36
|
+
@retry_count + 1
|
37
|
+
end
|
41
38
|
|
42
39
|
can_retry = case e
|
43
40
|
when *RETRYABLE_EXCEPTIONS then true
|
@@ -118,7 +118,7 @@ module Steem
|
|
118
118
|
error = response['error'].to_json if !!response['error']
|
119
119
|
|
120
120
|
if req_id != res_id
|
121
|
-
raise IncorrectResponseIdError, "#{method}: The json-rpc id did not match. Request was: #{req_id}, got: #{res_id.inspect}",
|
121
|
+
raise IncorrectResponseIdError, "#{method}: The json-rpc id did not match. Request was: #{req_id}, got: #{res_id.inspect}", BaseError.send(:build_backtrace, error)
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
@@ -143,7 +143,7 @@ module Steem
|
|
143
143
|
raise TooManyTimeoutsError.new("Too many timeouts for: #{context}", cause)
|
144
144
|
elsif @timeout_retry_count % 10 == 0
|
145
145
|
msg = "#{@timeout_retry_count} retry attempts for: #{context}"
|
146
|
-
msg += "; cause: #{
|
146
|
+
msg += "; cause: #{cause}" if !!cause
|
147
147
|
error_pipe.puts msg
|
148
148
|
end
|
149
149
|
|
@@ -30,7 +30,7 @@ module Steem
|
|
30
30
|
def http
|
31
31
|
@http ||= Net::HTTP.new(uri.host, uri.port).tap do |http|
|
32
32
|
http.use_ssl = true if uri.to_s =~ /^https/i
|
33
|
-
http.keep_alive_timeout =
|
33
|
+
http.keep_alive_timeout = 150 # seconds
|
34
34
|
|
35
35
|
# WARNING This method opens a serious security hole. Never use this
|
36
36
|
# method in production code.
|
@@ -15,7 +15,7 @@ module Steem
|
|
15
15
|
# })
|
16
16
|
#
|
17
17
|
# trx = builder.transaction
|
18
|
-
# network_broadcast_api = Steem::
|
18
|
+
# network_broadcast_api = Steem::CondenserApi.new
|
19
19
|
# network_broadcast_api.broadcast_transaction_synchronous(trx: trx)
|
20
20
|
#
|
21
21
|
#
|
@@ -26,13 +26,25 @@ module Steem
|
|
26
26
|
include ChainConfig
|
27
27
|
include Utils
|
28
28
|
|
29
|
-
attr_accessor :database_api, :block_api, :expiration, :operations
|
29
|
+
attr_accessor :app_base, :database_api, :block_api, :expiration, :operations
|
30
30
|
attr_writer :wif
|
31
31
|
attr_reader :signed
|
32
32
|
|
33
|
+
alias app_base? app_base
|
34
|
+
|
33
35
|
def initialize(options = {})
|
34
|
-
@
|
35
|
-
@
|
36
|
+
@app_base = !!options[:app_base] # default false
|
37
|
+
@database_api = options[:database_api]
|
38
|
+
@block_api = options[:block_api]
|
39
|
+
|
40
|
+
if app_base?
|
41
|
+
@database_api ||= Steem::DatabaseApi.new(options)
|
42
|
+
@block_api ||= Steem::BlockApi.new(options)
|
43
|
+
else
|
44
|
+
@database_api ||= Steem::CondenserApi.new(options)
|
45
|
+
@block_api ||= Steem::CondenserApi.new(options)
|
46
|
+
end
|
47
|
+
|
36
48
|
@wif = [options[:wif]].flatten
|
37
49
|
@signed = false
|
38
50
|
|
@@ -114,9 +126,18 @@ module Steem
|
|
114
126
|
catch :prepare_header do; begin
|
115
127
|
@database_api.get_dynamic_global_properties do |properties|
|
116
128
|
block_number = properties.last_irreversible_block_num
|
129
|
+
block_header_args = if app_base?
|
130
|
+
{block_num: block_number}
|
131
|
+
else
|
132
|
+
block_number
|
133
|
+
end
|
117
134
|
|
118
|
-
@block_api.get_block_header(
|
119
|
-
header =
|
135
|
+
@block_api.get_block_header(block_header_args) do |result|
|
136
|
+
header = if app_base?
|
137
|
+
result.header
|
138
|
+
else
|
139
|
+
result
|
140
|
+
end
|
120
141
|
|
121
142
|
@ref_block_num = (block_number - 1) & 0xFFFF
|
122
143
|
@ref_block_prefix = unhexlify(header.previous[8..-1]).unpack('V*')[0]
|
@@ -138,7 +159,7 @@ module Steem
|
|
138
159
|
|
139
160
|
# Sets operations all at once, then prepares.
|
140
161
|
def operations=(operations)
|
141
|
-
@operations = operations
|
162
|
+
@operations = operations.map{ |op| normalize_operation(op) }
|
142
163
|
prepare
|
143
164
|
@operations
|
144
165
|
end
|
@@ -167,34 +188,8 @@ module Steem
|
|
167
188
|
# @return {TransactionBuilder}
|
168
189
|
def put(type, op = nil)
|
169
190
|
@expiration = nil
|
170
|
-
|
171
|
-
## Saving this for later. This block, or something like it, might replace
|
172
|
-
## API broadcast operation structure.
|
173
|
-
# case type
|
174
|
-
# when Symbol, String
|
175
|
-
# type_value = "#{type}_operation"
|
176
|
-
# @operations << {type: type_value, value: op}
|
177
|
-
# when Hash
|
178
|
-
# type_value = "#{type.keys.first}_operation"
|
179
|
-
# @operations << {type: type_value, value: type.values.first}
|
180
|
-
# when Array
|
181
|
-
# type_value = "#{type[0]}_operation"
|
182
|
-
# @operations << {type: type_value, value: type[1]}
|
183
|
-
# else
|
184
|
-
# # don't know what to do with it, skipped
|
185
|
-
# end
|
186
|
-
|
187
|
-
case type
|
188
|
-
when Symbol then @operations << [type, op]
|
189
|
-
when String then @operations << [type.to_sym, op]
|
190
|
-
when Hash then @operations << [type.keys.first.to_sym, type.values.first]
|
191
|
-
when Array then @operations << type
|
192
|
-
else
|
193
|
-
# don't know what to do with it, skipped
|
194
|
-
end
|
195
|
-
|
191
|
+
@operations << normalize_operation(type, op)
|
196
192
|
prepare
|
197
|
-
|
198
193
|
self
|
199
194
|
end
|
200
195
|
|
@@ -240,8 +235,20 @@ module Steem
|
|
240
235
|
|
241
236
|
unless @signed
|
242
237
|
catch :serialize do; begin
|
243
|
-
|
244
|
-
|
238
|
+
transaction_hex_args = if app_base?
|
239
|
+
{trx: trx}
|
240
|
+
else
|
241
|
+
trx
|
242
|
+
end
|
243
|
+
|
244
|
+
@database_api.get_transaction_hex(transaction_hex_args) do |result|
|
245
|
+
hex = if app_base?
|
246
|
+
result.hex
|
247
|
+
else
|
248
|
+
result
|
249
|
+
end
|
250
|
+
|
251
|
+
hex = @chain_id + hex[0..-4] # Why do we have to chop the last two bytes?
|
245
252
|
digest = unhexlify(hex)
|
246
253
|
digest_hex = Digest::SHA256.digest(digest)
|
247
254
|
private_keys = @wif.map{ |wif| Bitcoin::Key.from_base58 wif }
|
@@ -283,8 +290,18 @@ module Steem
|
|
283
290
|
|
284
291
|
# @return [Array] All public keys that could possibly sign for a given transaction.
|
285
292
|
def potential_signatures
|
286
|
-
|
287
|
-
|
293
|
+
potential_signatures_args = if app_base?
|
294
|
+
{trx: transaction}
|
295
|
+
else
|
296
|
+
transaction
|
297
|
+
end
|
298
|
+
|
299
|
+
@database_api.get_potential_signatures(potential_signatures_args) do |result|
|
300
|
+
if app_base?
|
301
|
+
result[:keys]
|
302
|
+
else
|
303
|
+
result
|
304
|
+
end
|
288
305
|
end
|
289
306
|
end
|
290
307
|
|
@@ -294,15 +311,35 @@ module Steem
|
|
294
311
|
#
|
295
312
|
# @return [Array] The minimal subset of public keys that should add signatures to the transaction.
|
296
313
|
def required_signatures
|
297
|
-
|
298
|
-
|
314
|
+
required_signatures_args = if app_base?
|
315
|
+
{trx: transaction}
|
316
|
+
else
|
317
|
+
[transaction, []]
|
318
|
+
end
|
319
|
+
|
320
|
+
@database_api.get_required_signatures(*required_signatures_args) do |result|
|
321
|
+
if app_base?
|
322
|
+
result[:keys]
|
323
|
+
else
|
324
|
+
result
|
325
|
+
end
|
299
326
|
end
|
300
327
|
end
|
301
328
|
|
302
329
|
# @return [Boolean] True if the transaction has all of the required signatures.
|
303
330
|
def valid?
|
304
|
-
|
305
|
-
|
331
|
+
verify_authority_args = if app_base?
|
332
|
+
{trx: transaction}
|
333
|
+
else
|
334
|
+
transaction
|
335
|
+
end
|
336
|
+
|
337
|
+
@database_api.verify_authority(verify_authority_args) do |result|
|
338
|
+
if app_base?
|
339
|
+
result.valid
|
340
|
+
else
|
341
|
+
result
|
342
|
+
end
|
306
343
|
end
|
307
344
|
end
|
308
345
|
private
|
@@ -318,5 +355,32 @@ module Steem
|
|
318
355
|
((sig[33] & 0x80 ) != 0)
|
319
356
|
)
|
320
357
|
end
|
358
|
+
|
359
|
+
def normalize_operation(type, op = nil)
|
360
|
+
if app_base?
|
361
|
+
case type
|
362
|
+
when Symbol, String
|
363
|
+
type_value = "#{type}_operation"
|
364
|
+
{type: type_value, value: op}
|
365
|
+
when Hash
|
366
|
+
type_value = "#{type.keys.first}_operation"
|
367
|
+
{type: type_value, value: type.values.first}
|
368
|
+
when Array
|
369
|
+
type_value = "#{type[0]}_operation"
|
370
|
+
{type: type_value, value: type[1]}
|
371
|
+
else
|
372
|
+
raise Steem::ArgumentError, "Don't know what to do with operation type #{type.class}: #{type} (#{op})"
|
373
|
+
end
|
374
|
+
else
|
375
|
+
case type
|
376
|
+
when Symbol then [type, op]
|
377
|
+
when String then [type.to_sym, op]
|
378
|
+
when Hash then [type.keys.first.to_sym, type.values.first]
|
379
|
+
when Array then type
|
380
|
+
else
|
381
|
+
raise Steem::ArgumentError, "Don't know what to do with operation type #{type.class}: #{type} (#{op})"
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
321
385
|
end
|
322
386
|
end
|
data/lib/steem/type/amount.rb
CHANGED
@@ -3,8 +3,10 @@ module Steem
|
|
3
3
|
|
4
4
|
# See: https://github.com/xeroc/piston-lib/blob/34a7525cee119ec9b24a99577ede2d54466fca0e/steembase/operations.py
|
5
5
|
class Amount < BaseType
|
6
|
-
|
7
|
-
|
6
|
+
attr_reader :amount, :precision, :nai, :asset
|
7
|
+
|
8
|
+
def self.to_h(amount)
|
9
|
+
new(amount).to_h
|
8
10
|
end
|
9
11
|
|
10
12
|
def self.to_s(amount)
|
@@ -16,15 +18,33 @@ module Steem
|
|
16
18
|
|
17
19
|
case value
|
18
20
|
when Array
|
19
|
-
|
20
|
-
@asset = case
|
21
|
+
@amount, @precision, @nai = value
|
22
|
+
@asset = case @nai
|
21
23
|
when '@@000000013' then 'SBD'
|
22
24
|
when '@@000000021' then 'STEEM'
|
23
25
|
when '@@000000037' then 'VESTS'
|
24
|
-
else; raise TypeError, "Asset #{@
|
26
|
+
else; raise TypeError, "Asset #{@nai} unknown."
|
27
|
+
end
|
28
|
+
|
29
|
+
@amount = "%.#{@precision}f" % (@amount.to_f / 10 ** @precision)
|
30
|
+
when Hash
|
31
|
+
@amount, @precision, @nai = value.map do |k, v|
|
32
|
+
v if %i(amount precision nai).include? k.to_sym
|
33
|
+
end.compact
|
34
|
+
|
35
|
+
@asset = case @nai
|
36
|
+
when '@@000000013' then 'SBD'
|
37
|
+
when '@@000000021' then 'STEEM'
|
38
|
+
when '@@000000037' then 'VESTS'
|
39
|
+
else; raise TypeError, "Asset #{@nai} unknown."
|
25
40
|
end
|
26
|
-
|
27
|
-
@amount = "%.#{
|
41
|
+
|
42
|
+
@amount = "%.#{@precision}f" % (@amount.to_f / 10 ** @precision)
|
43
|
+
when Amount
|
44
|
+
@precision = value.precision
|
45
|
+
@nai = value.nai
|
46
|
+
@asset = value.asset
|
47
|
+
@amount = value.amount
|
28
48
|
else
|
29
49
|
@amount, @asset = value.strip.split(' ') rescue ['', '']
|
30
50
|
@precision = case @asset
|
@@ -45,7 +65,7 @@ module Steem
|
|
45
65
|
asset
|
46
66
|
end
|
47
67
|
|
48
|
-
def
|
68
|
+
def to_a
|
49
69
|
case @asset
|
50
70
|
when 'STEEM' then [(@amount.to_f * 1000).to_i.to_s, 3, '@@000000021']
|
51
71
|
when 'VESTS' then [(@amount.to_f * 1000000).to_i.to_s, 6, '@@000000037']
|
@@ -53,6 +73,26 @@ module Steem
|
|
53
73
|
end
|
54
74
|
end
|
55
75
|
|
76
|
+
def to_h
|
77
|
+
case @asset
|
78
|
+
when 'STEEM' then {
|
79
|
+
amount: (@amount.to_f * 1000).to_i.to_s,
|
80
|
+
precision: 3,
|
81
|
+
nai: '@@000000021'
|
82
|
+
}
|
83
|
+
when 'VESTS' then {
|
84
|
+
amount: (@amount.to_f * 1000000).to_i.to_s,
|
85
|
+
precision: 6,
|
86
|
+
nai: '@@000000037'
|
87
|
+
}
|
88
|
+
when 'SBD' then {
|
89
|
+
amount: (@amount.to_f * 1000).to_i.to_s,
|
90
|
+
precision: 3,
|
91
|
+
nai: '@@000000013'
|
92
|
+
}
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
56
96
|
def to_s
|
57
97
|
"#{@amount} #{@asset}"
|
58
98
|
end
|
data/lib/steem/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steem-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Anthony Martin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-06-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|