steem-ruby 0.9.0 → 0.9.1
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.
- 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
|