crea-ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +55 -0
  3. data/CONTRIBUTING.md +79 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +22 -0
  6. data/README.md +234 -0
  7. data/Rakefile +332 -0
  8. data/crea-ruby.gemspec +39 -0
  9. data/gource.sh +6 -0
  10. data/lib/crea.rb +85 -0
  11. data/lib/crea/api.rb +208 -0
  12. data/lib/crea/base_error.rb +218 -0
  13. data/lib/crea/block_api.rb +78 -0
  14. data/lib/crea/broadcast.rb +1334 -0
  15. data/lib/crea/chain_config.rb +36 -0
  16. data/lib/crea/formatter.rb +14 -0
  17. data/lib/crea/jsonrpc.rb +108 -0
  18. data/lib/crea/marshal.rb +231 -0
  19. data/lib/crea/mixins/jsonable.rb +37 -0
  20. data/lib/crea/mixins/retriable.rb +58 -0
  21. data/lib/crea/mixins/serializable.rb +45 -0
  22. data/lib/crea/operation.rb +141 -0
  23. data/lib/crea/operation/account_create.rb +10 -0
  24. data/lib/crea/operation/account_create_with_delegation.rb +12 -0
  25. data/lib/crea/operation/account_update.rb +8 -0
  26. data/lib/crea/operation/account_witness_proxy.rb +4 -0
  27. data/lib/crea/operation/account_witness_vote.rb +5 -0
  28. data/lib/crea/operation/cancel_transfer_from_savings.rb +4 -0
  29. data/lib/crea/operation/challenge_authority.rb +5 -0
  30. data/lib/crea/operation/change_recovery_account.rb +5 -0
  31. data/lib/crea/operation/claim_account.rb +5 -0
  32. data/lib/crea/operation/claim_reward_balance.rb +6 -0
  33. data/lib/crea/operation/comment.rb +9 -0
  34. data/lib/crea/operation/comment_options.rb +10 -0
  35. data/lib/crea/operation/convert.rb +5 -0
  36. data/lib/crea/operation/create_claimed_account.rb +10 -0
  37. data/lib/crea/operation/custom.rb +5 -0
  38. data/lib/crea/operation/custom_binary.rb +8 -0
  39. data/lib/crea/operation/custom_json.rb +6 -0
  40. data/lib/crea/operation/decline_voting_rights.rb +4 -0
  41. data/lib/crea/operation/delegate_vesting_shares.rb +5 -0
  42. data/lib/crea/operation/delete_comment.rb +4 -0
  43. data/lib/crea/operation/escrow_approve.rb +8 -0
  44. data/lib/crea/operation/escrow_dispute.rb +7 -0
  45. data/lib/crea/operation/escrow_release.rb +10 -0
  46. data/lib/crea/operation/escrow_transfer.rb +12 -0
  47. data/lib/crea/operation/feed_publish.rb +4 -0
  48. data/lib/crea/operation/limit_order_cancel.rb +4 -0
  49. data/lib/crea/operation/limit_order_create.rb +8 -0
  50. data/lib/crea/operation/limit_order_create2.rb +8 -0
  51. data/lib/crea/operation/prove_authority.rb +4 -0
  52. data/lib/crea/operation/recover_account.rb +6 -0
  53. data/lib/crea/operation/report_over_production.rb +5 -0
  54. data/lib/crea/operation/request_account_recovery.rb +6 -0
  55. data/lib/crea/operation/reset_account.rb +5 -0
  56. data/lib/crea/operation/set_reset_account.rb +5 -0
  57. data/lib/crea/operation/set_withdraw_vesting_route.rb +6 -0
  58. data/lib/crea/operation/transfer.rb +6 -0
  59. data/lib/crea/operation/transfer_from_savings.rb +7 -0
  60. data/lib/crea/operation/transfer_to_savings.rb +6 -0
  61. data/lib/crea/operation/transfer_to_vesting.rb +5 -0
  62. data/lib/crea/operation/vote.rb +6 -0
  63. data/lib/crea/operation/withdraw_vesting.rb +4 -0
  64. data/lib/crea/operation/witness_set_properties.rb +5 -0
  65. data/lib/crea/operation/witness_update.rb +7 -0
  66. data/lib/crea/rpc/base_client.rb +179 -0
  67. data/lib/crea/rpc/http_client.rb +143 -0
  68. data/lib/crea/rpc/thread_safe_http_client.rb +35 -0
  69. data/lib/crea/stream.rb +385 -0
  70. data/lib/crea/transaction.rb +96 -0
  71. data/lib/crea/transaction_builder.rb +393 -0
  72. data/lib/crea/type/amount.rb +107 -0
  73. data/lib/crea/type/base_type.rb +10 -0
  74. data/lib/crea/utils.rb +17 -0
  75. data/lib/crea/version.rb +4 -0
  76. metadata +478 -0
@@ -0,0 +1,78 @@
1
+ module Crea
2
+ # {BlockApi} is used to query values related to the block plugin. It can also
3
+ # be used to access a range of multiple blocks by using
4
+ # {http://www.jsonrpc.org/specification#batch JSON-RPC 2.0 batch} requests.
5
+ #
6
+ # Also see: {https://developers.crea.io/apidefinitions/block-api Block API Definitions}
7
+ class BlockApi < Api
8
+ MAX_RANGE_SIZE = 50
9
+
10
+ def initialize(options = {})
11
+ self.class.api_name = :block_api
12
+ super
13
+ end
14
+
15
+ # Uses a batched requst on a range of block headers.
16
+ #
17
+ # @param options [Hash] The attributes to get a block range with.
18
+ # @option options [Range] :block_range starting on one block number and ending on an higher block number.
19
+ def get_block_headers(options = {block_range: (0..0)}, &block)
20
+ get_block_objects(options.merge(object: :block_header), block)
21
+ end
22
+
23
+ # Uses a batched requst on a range of blocks.
24
+ #
25
+ # @param options [Hash] The attributes to get a block range with.
26
+ # @option options [Range] :block_range starting on one block number and ending on an higher block number.
27
+ def get_blocks(options = {block_range: (0..0)}, &block)
28
+ get_block_objects(options.merge(object: :block), block)
29
+ end
30
+ private
31
+ def get_block_objects(options = {block_range: (0..0)}, block = nil)
32
+ object = options[:object]
33
+ object_method = "get_#{object}".to_sym
34
+ block_range = options[:block_range] || (0..0)
35
+
36
+ if (start = block_range.first) < 1
37
+ raise Crea::ArgumentError, "Invalid starting block: #{start}"
38
+ end
39
+
40
+ chunks = if block_range.size > MAX_RANGE_SIZE
41
+ block_range.each_slice(MAX_RANGE_SIZE)
42
+ else
43
+ [block_range]
44
+ end
45
+
46
+ for sub_range in chunks do
47
+ request_object = []
48
+
49
+ for i in sub_range do
50
+ @rpc_client.put(self.class.api_name, object_method, block_num: i, request_object: request_object)
51
+ end
52
+
53
+ if !!block
54
+ index = 0
55
+ @rpc_client.rpc_batch_execute(request_object: request_object) do |result, error, id|
56
+ block_num = sub_range.to_a[index]
57
+ index = index + 1
58
+
59
+ case object
60
+ when :block_header
61
+ block.call(result.nil? ? nil : result[:header], block_num)
62
+ else
63
+ block.call(result.nil? ? nil : result[object], block_num)
64
+ end
65
+ end
66
+ else
67
+ blocks = []
68
+
69
+ @rpc_client.rpc_batch_execute(request_object: request_object) do |result, error, id|
70
+ blocks << result
71
+ end
72
+ end
73
+ end
74
+
75
+ blocks
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,1334 @@
1
+ require 'bitcoin'
2
+ require 'digest'
3
+ require 'time'
4
+
5
+ module Crea
6
+
7
+ # These class methods make it simple to do things like broacast a {Broadcast#vote}
8
+ # or {Broadcast#comment} operation. They accept all of the fields expected by
9
+ # the blockchain plus the following additional options:
10
+ #
11
+ # * wif
12
+ # * url (optional)
13
+ # * database_api (optional)
14
+ # * block_api (optional)
15
+ # * network_broadcast_api (optional)
16
+ # * pretend (optional)
17
+ #
18
+ # These options are not sent in the broadcast. The `wif` authorities can be
19
+ # posting, active, and owner.
20
+ #
21
+ # Setting `url` will allow you to specify a different node instead of taking
22
+ # the default: ({ChainConfig::NETWORKS_CREA_DEFAULT_NODE}).
23
+ #
24
+ # Setting `database_api`, `block_api`, and `network_broadcast_api` is
25
+ # optional, doing so will allow you to override the default node and/or the
26
+ # RPC Client.
27
+ #
28
+ # When passing the `pretend` field, if it is set to {::True}, nothing is
29
+ # broadcasted, but the `wif` is checked for the proper authority.
30
+ #
31
+ # For details on what to pass to these methods, check out the {https://developers.crea.io/apidefinitions/broadcast-ops Crea Developer Portal Broadcast Operations} page.
32
+ class Broadcast
33
+ extend Retriable
34
+ extend Utils
35
+
36
+ DEFAULT_MAX_ACCEPTED_PAYOUT = Type::Amount.new(amount: '1000000000', precision: 3, nai: '@@000000013')
37
+
38
+ # This operation is used to cast a vote on a post/comment.
39
+ #
40
+ # options = {
41
+ # wif: wif,
42
+ # params: {
43
+ # voter: voter,
44
+ # author: author,
45
+ # permlink: permlink,
46
+ # weight: weight
47
+ # }
48
+ # }
49
+ #
50
+ # Crea::Broadcast.vote(options) do |result|
51
+ # puts result
52
+ # end
53
+ #
54
+ # @param options [Hash] options
55
+ # @option options [String] :wif Posting wif
56
+ # @option options [Hash] :params
57
+ # * :voter (String)
58
+ # * :author (String)
59
+ # * :permlink (String)
60
+ # * :weight (Number)
61
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
62
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_vote
63
+ def self.vote(options, &block)
64
+ required_fields = %i(voter author permlink weight)
65
+ params = options[:params]
66
+ check_required_fields(params, *required_fields)
67
+
68
+ ops = [[:vote, params]]
69
+
70
+ process(options.merge(ops: ops), &block)
71
+ end
72
+
73
+ # Creates a post/comment. This method simplifies content creation by
74
+ # combining `comment` and `comment_options` into one transaction.
75
+ #
76
+ # options = {
77
+ # wif: wif,
78
+ # params: {
79
+ # author: author,
80
+ # title: 'This is my fancy post title.',
81
+ # body: 'This is my fancy post body.',
82
+ # metadata: {
83
+ # tags: %w(these are my fancy tags)
84
+ # }
85
+ # }
86
+ # }
87
+ #
88
+ # Crea::Broadcast.comment(options)
89
+ #
90
+ # options = {
91
+ # wif: wif,
92
+ # params: {
93
+ # author: author,
94
+ # title: 'This is my fancy post title.',
95
+ # body: 'This is my fancy post body.',
96
+ # metadata: {
97
+ # tags: %w(these are my fancy tags)
98
+ # },
99
+ # beneficiaries: [
100
+ # {account: "david", weight: 500},
101
+ # {account: "erin", weight: 500},
102
+ # {account: "faythe", weight: 1000},
103
+ # {account: "frank", weight: 500}
104
+ # ]
105
+ # }
106
+ # }
107
+ #
108
+ # Crea::Broadcast.comment(options)
109
+ #
110
+ # In addition to the above denormalized `comment_options` fields, the author
111
+ # can also vote for the content in the same transaction by setting `author_vote_weight`:
112
+ #
113
+ # options = {
114
+ # wif: wif,
115
+ # params: {
116
+ # author: author,
117
+ # title: 'This is my fancy post title.',
118
+ # body: 'This is my fancy post body.',
119
+ # metadata: {
120
+ # tags: %w(these are my fancy tags)
121
+ # },
122
+ # author_vote_weight: 10000
123
+ # }
124
+ # }
125
+ #
126
+ # Crea::Broadcast.comment(options)
127
+ #
128
+ # @param options [Hash] options
129
+ # @option options [String] :wif Posting wif
130
+ # @option options [Hash] :params
131
+ # * :author (String)
132
+ # * :title (String) Title of the content.
133
+ # * :body (String) Body of the content.
134
+ # * :metadata (Hash) Metadata of the content, becomes `json_metadata`.
135
+ # * :json_metadata (String) String version of `metadata` (use one or the other).
136
+ # * :permlink (String) (automatic) Permlink of the content, defaults to formatted title.
137
+ # * :parent_permlink (String) (automatic) Parent permlink of the content, defaults to first tag.
138
+ # * :parent_author (String) (optional) Parent author of the content (only used if reply).
139
+ # * :max_accepted_payout (String) (1000000.000 CBD) Maximum accepted payout, set to '0.000 CBD' to deline payout
140
+ # * :percent_crea_dollars (Numeric) (5000) Percent CREA Dollars is used to set 50/50 or 100% CREA Power
141
+ # * :allow_votes (Numeric) (true) Allow votes for this content.
142
+ # * :allow_curation_rewards (Numeric) (true) Allow curation rewards for this content.
143
+ # * :beneficiaries (Array<Hash>) Sets the beneficiaries of this content.
144
+ # * :author_vote_weight (Number) (optional) Cast a vote by the author in the same transaction.
145
+ # * :pretend (Boolean) Just validate, do not broadcast.
146
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_comment
147
+ def self.comment(options, &block)
148
+ required_fields = %i(author body permlink parent_permlink)
149
+ params = options[:params]
150
+
151
+ if !!params[:metadata] && !!params[:json_metadata]
152
+ raise Crea::ArgumentError, 'Assign either metadata or json_metadata, not both.'
153
+ end
154
+
155
+ metadata = params[:metadata] || {}
156
+ metadata ||= (JSON[params[:json_metadata]] || nil) || {}
157
+ metadata['app'] ||= Crea::AGENT_ID
158
+ tags = metadata['tags'] || []
159
+ params[:parent_permlink] ||= tags.first
160
+
161
+ if !!params[:title]
162
+ params[:permlink] ||= params[:title].downcase.gsub(/[^a-z0-9\-]+/, '-')
163
+ end
164
+
165
+ check_required_fields(params, *required_fields)
166
+
167
+ ops = [[:comment, {
168
+ parent_author: params[:parent_author] || '',
169
+ parent_permlink: params[:parent_permlink],
170
+ author: params[:author],
171
+ permlink: params[:permlink],
172
+ title: params[:title] || '',
173
+ body: params[:body],
174
+ json_metadata: metadata.to_json
175
+ }]]
176
+
177
+ max_accepted_payout = if params.keys.include? :max_accepted_payout
178
+ normalize_amount(options.merge amount: params[:max_accepted_payout])
179
+ else
180
+ normalize_amount(options.merge amount: DEFAULT_MAX_ACCEPTED_PAYOUT)
181
+ end
182
+
183
+ allow_votes = if params.keys.include? :allow_votes
184
+ !!params[:allow_votes]
185
+ else
186
+ true
187
+ end
188
+
189
+ allow_curation_rewards = if params.keys.include? :allow_curation_rewards
190
+ !!params[:allow_curation_rewards]
191
+ else
192
+ true
193
+ end
194
+
195
+ comment_options = {
196
+ author: params[:author],
197
+ permlink: params[:permlink],
198
+ max_accepted_payout: max_accepted_payout,
199
+ percent_crea_dollars: params[:percent_crea_dollars] || 10000,
200
+ # allow_replies: allow_replies,
201
+ allow_votes: allow_votes,
202
+ allow_curation_rewards: allow_curation_rewards,
203
+ extensions: []
204
+ }
205
+
206
+ if !!params[:beneficiaries]
207
+ comment_options[:extensions] << [
208
+ comment_options[:extensions].size,
209
+ normalize_beneficiaries(options.merge(beneficiaries: params[:beneficiaries]))
210
+ ]
211
+ end
212
+
213
+ ops << [:comment_options, comment_options]
214
+
215
+ if !!params[:author_vote_weight]
216
+ author_vote = {
217
+ voter: params[:author],
218
+ author: params[:author],
219
+ permlink: params[:permlink],
220
+ weight: params[:author_vote_weight]
221
+ }
222
+
223
+ ops << [:vote, author_vote]
224
+ end
225
+
226
+ process(options.merge(ops: ops), &block)
227
+ end
228
+
229
+ # Deletes a post/comment.
230
+ #
231
+ # Crea::Broadcast.delete_comment(wif: wif, params: {author: author, permlink: permlink}) do |result|
232
+ # puts result
233
+ # end
234
+ #
235
+ # @param options [Hash] options
236
+ # @option options [String] :wif Posting wif
237
+ # @option options [Hash] :params
238
+ # * :author (String)
239
+ # * :permlink (String)
240
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
241
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_delete_comment
242
+ def self.delete_comment(options, &block)
243
+ required_fields = %i(author permlink)
244
+ params = options[:params]
245
+ check_required_fields(params, *required_fields)
246
+
247
+ ops = [[:delete_comment, params]]
248
+
249
+ process(options.merge(ops: ops), &block)
250
+ end
251
+
252
+ # Transfers asset from one account to another.
253
+ #
254
+ # options = {
255
+ # wif: wif,
256
+ # params: {
257
+ # from: from,
258
+ # to: to,
259
+ # amount: amount,
260
+ # memo: memo
261
+ # }
262
+ # }
263
+ #
264
+ # Crea::Broadcast.transfer(options) do |result|
265
+ # puts result
266
+ # end
267
+ #
268
+ # @param options [Hash] options
269
+ # @option options [String] :wif Active wif
270
+ # @option options [Hash] :params
271
+ # * :from (String)
272
+ # * :to (String)
273
+ # * :amount (String)
274
+ # * :memo (String)
275
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
276
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_transfer
277
+ def self.transfer(options, &block)
278
+ required_fields = %i(from to amount memo)
279
+ params = options[:params]
280
+ check_required_fields(params, *required_fields)
281
+
282
+ params[:amount] = normalize_amount(options.merge amount: params[:amount])
283
+
284
+ ops = [[:transfer, params]]
285
+
286
+ process(options.merge(ops: ops), &block)
287
+ end
288
+
289
+ # This operation converts CREA into VFS (Vesting Fund Shares) at the
290
+ # current exchange rate.
291
+ #
292
+ # options = {
293
+ # wif: wif,
294
+ # params: {
295
+ # from: from,
296
+ # to: to,
297
+ # amount: amount,
298
+ # }
299
+ # }
300
+ #
301
+ # Crea::Broadcast.transfer_to_vesting(options) do |result|
302
+ # puts result
303
+ # end
304
+ #
305
+ # @param options [Hash] options
306
+ # @option options [String] :wif Active wif
307
+ # @option options [Hash] :params
308
+ # * :from (String)
309
+ # * :to (String)
310
+ # * :amount (String)
311
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
312
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_transfer_to_vesting
313
+ def self.transfer_to_vesting(options, &block)
314
+ required_fields = %i(from to amount)
315
+ params = options[:params]
316
+ check_required_fields(params, *required_fields)
317
+
318
+ params[:amount] = normalize_amount(options.merge amount: params[:amount])
319
+
320
+ ops = [[:transfer_to_vesting, params]]
321
+
322
+ process(options.merge(ops: ops), &block)
323
+ end
324
+
325
+ # At any given point in time an account can be withdrawing from their
326
+ # vesting shares.
327
+ #
328
+ # Crea::Broadcast.withdraw_vesting(wif: wif, params: {account: account, vesting_shares: vesting_shares}) do |result|
329
+ # puts result
330
+ # end
331
+ #
332
+ # @param options [Hash] options
333
+ # @option options [String] :wif Active wif
334
+ # @option options [Hash] :params
335
+ # * :account (String)
336
+ # * :vesting_shares (String)
337
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
338
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_withdraw_vesting
339
+ def self.withdraw_vesting(options, &block)
340
+ required_fields = %i(account vesting_shares)
341
+ params = options[:params]
342
+ check_required_fields(params, *required_fields)
343
+
344
+ params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares])
345
+
346
+ ops = [[:withdraw_vesting, params]]
347
+
348
+ process(options.merge(ops: ops), &block)
349
+ end
350
+
351
+ # This operation creates a limit order and matches it against existing open
352
+ # orders.
353
+ #
354
+ # @param options [Hash] options
355
+ # @option options [String] :wif Active wif
356
+ # @option options [Hash] :params
357
+ # * :owner (String)
358
+ # * :orderid (String)
359
+ # * :amount_to_sell (String)
360
+ # * :min_to_receive (String)
361
+ # * :fill_or_kill (Boolean)
362
+ # * :expiration (String)
363
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
364
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_limit_order_create
365
+ def self.limit_order_create(options, &block)
366
+ required_fields = %i(owner orderid amount_to_sell min_to_receive
367
+ fill_or_kill)
368
+ params = options[:params]
369
+ check_required_fields(params, *required_fields)
370
+
371
+ params[:amount_to_sell] = normalize_amount(options.merge amount: params[:amount_to_sell])
372
+ params[:min_to_receive] = normalize_amount(options.merge amount: params[:min_to_receive])
373
+
374
+ if !!params[:expiration]
375
+ params[:expiration] = Time.parse(params[:expiration].to_s)
376
+ params[:expiration] = params[:expiration].strftime('%Y-%m-%dT%H:%M:%S')
377
+ end
378
+
379
+ ops = [[:limit_order_create, params]]
380
+
381
+ process(options.merge(ops: ops), &block)
382
+ end
383
+
384
+ # Cancels an order and returns the balance to owner.
385
+ #
386
+ # @param options [Hash] options
387
+ # @option options [String] :wif Active wif
388
+ # @option options [Hash] :params
389
+ # * :owner (String)
390
+ # * :orderid (String)
391
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
392
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_limit_order_cancel
393
+ def self.limit_order_cancel(options, &block)
394
+ required_fields = %i(owner orderid)
395
+ params = options[:params]
396
+ check_required_fields(params, *required_fields)
397
+
398
+ ops = [[:limit_order_cancel, params]]
399
+
400
+ process(options.merge(ops: ops), &block)
401
+ end
402
+
403
+ # Feeds can only be published by the top N witnesses which are included in
404
+ # every round and are used to define the exchange rate between crea and the
405
+ # dollar.
406
+ #
407
+ # @param options [Hash] options
408
+ # @option options [String] :wif Active wif
409
+ # @option options [Hash] :params
410
+ # * :publisher (String)
411
+ # * :exchange_rate (Hash)
412
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
413
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_feed_publish
414
+ def self.feed_publish(options, &block)
415
+ required_fields = %i(publisher exchange_rate)
416
+ params = options[:params]
417
+ check_required_fields(params, *required_fields)
418
+
419
+ exchange_rate = params[:exchange_rate] rescue nil || {}
420
+ base = exchange_rate[:base]
421
+ quote = exchange_rate[:quote]
422
+ params[:exchange_rate][:base] = normalize_amount(options.merge amount: base)
423
+ params[:exchange_rate][:quote] = normalize_amount(options.merge amount: quote)
424
+
425
+ ops = [[:feed_publish, params]]
426
+
427
+ process(options.merge(ops: ops), &block)
428
+ end
429
+
430
+ # This operation instructs the blockchain to start a conversion between
431
+ # CREA and CBD, the funds are deposited after 3.5 days.
432
+ #
433
+ # @param options [Hash] options
434
+ # @option options [String] :wif Active wif
435
+ # @option options [Hash] :params
436
+ # * :owner (String)
437
+ # * :requestid (String)
438
+ # * :amount (String)
439
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
440
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_convert
441
+ def self.convert(options, &block)
442
+ required_fields = %i(owner requestid amount)
443
+ params = options[:params]
444
+ check_required_fields(params, *required_fields)
445
+
446
+ params[:amount] = normalize_amount(options.merge amount: params[:amount])
447
+
448
+ ops = [[:convert, params]]
449
+
450
+ process(options.merge(ops: ops), &block)
451
+ end
452
+
453
+ # Create an account.
454
+ # options = {
455
+ # wif: wif,
456
+ # params: {
457
+ # fee: '1.000 CREA',
458
+ # creator: creator_account_name,
459
+ # new_account_name: new_account_name,
460
+ # owner: {
461
+ # weight_threshold: 1,
462
+ # account_auths: [],
463
+ # key_auths: [[owner_public_key, 1]],
464
+ # },
465
+ # active: {
466
+ # weight_threshold: 1,
467
+ # account_auths: [],
468
+ # key_auths: [[active_public_key, 1]],
469
+ # },
470
+ # posting: {
471
+ # weight_threshold: 1,
472
+ # account_auths: [],
473
+ # key_auths: [[posting_public_key, 1]],
474
+ # },
475
+ # memo_key: memo_public_key,
476
+ # json_metadata: '{}'
477
+ # }
478
+ # }
479
+ #
480
+ # Crea::Broadcast.account_create(options)
481
+ #
482
+ # @param options [Hash] options
483
+ # @option options [String] :wif Active wif
484
+ # @option options [Hash] :params
485
+ # * :fee (String)
486
+ # * :creator (String)
487
+ # * :new_account_name (String)
488
+ # * :owner (Hash)
489
+ # * :active (Hash)
490
+ # * :posting (Hash)
491
+ # * :memo_key (String)
492
+ # * :metadata (Hash) Metadata of the account, becomes `json_metadata`.
493
+ # * :json_metadata (String) String version of `metadata` (use one or the other).
494
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
495
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_account_create
496
+ def self.account_create(options, &block)
497
+ required_fields = %i(fee creator new_account_name owner active posting memo_key json_metadata)
498
+ params = options[:params]
499
+
500
+ if !!params[:metadata] && !!params[:json_metadata]
501
+ raise Crea::ArgumentError, 'Assign either metadata or json_metadata, not both.'
502
+ end
503
+
504
+ metadata = params.delete(:metadata) || {}
505
+ metadata ||= (JSON[params[:json_metadata]] || nil) || {}
506
+ params[:json_metadata] = metadata.to_json
507
+
508
+ check_required_fields(params, *required_fields)
509
+
510
+ params[:fee] = normalize_amount(options.merge amount: params[:fee])
511
+
512
+ ops = [[:account_create, params]]
513
+
514
+ process(options.merge(ops: ops), &block)
515
+ end
516
+
517
+ # Create a claimed account.
518
+ # options = {
519
+ # wif: wif,
520
+ # params: {
521
+ # creator: creator_account_name,
522
+ # new_account_name: new_account_name,
523
+ # owner: {
524
+ # weight_threshold: 1,
525
+ # account_auths: [],
526
+ # key_auths: [[owner_public_key, 1]],
527
+ # },
528
+ # active: {
529
+ # weight_threshold: 1,
530
+ # account_auths: [],
531
+ # key_auths: [[active_public_key, 1]],
532
+ # },
533
+ # posting: {
534
+ # weight_threshold: 1,
535
+ # account_auths: [],
536
+ # key_auths: [[posting_public_key, 1]],
537
+ # },
538
+ # memo_key: memo_public_key,
539
+ # json_metadata: '{}'
540
+ # }
541
+ # }
542
+ #
543
+ # Crea::Broadcast.create_claimed_account(options)
544
+ #
545
+ # @param options [Hash] options
546
+ # @option options [String] :wif Active wif
547
+ # @option options [Hash] :params
548
+ # * :creator (String)
549
+ # * :new_account_name (String)
550
+ # * :owner (Hash)
551
+ # * :active (Hash)
552
+ # * :posting (Hash)
553
+ # * :memo_key (String)
554
+ # * :metadata (Hash) Metadata of the account, becomes `json_metadata`.
555
+ # * :json_metadata (String) String version of `metadata` (use one or the other).
556
+ # * :extensions (Array) (optional)
557
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
558
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_create_claimed_account
559
+ def self.create_claimed_account(options, &block)
560
+ required_fields = %i(creator new_account_name owner active posting memo_key json_metadata)
561
+ params = options[:params]
562
+
563
+ if !!params[:metadata] && !!params[:json_metadata]
564
+ raise Crea::ArgumentError, 'Assign either metadata or json_metadata, not both.'
565
+ end
566
+
567
+ metadata = params.delete(:metadata) || {}
568
+ metadata ||= (JSON[params[:json_metadata]] || nil) || {}
569
+ params[:json_metadata] = metadata.to_json
570
+
571
+ check_required_fields(params, *required_fields)
572
+
573
+ params[:extensions] ||= []
574
+ ops = [[:create_claimed_account, params]]
575
+
576
+ process(options.merge(ops: ops), &block)
577
+ end
578
+
579
+ # Update an account.
580
+ # options = {
581
+ # wif: wif,
582
+ # params: {
583
+ # account: new_account_name,
584
+ # owner: {
585
+ # weight_threshold: 1,
586
+ # account_auths: [],
587
+ # key_auths: [[owner_public_key, 1]],
588
+ # },
589
+ # active: {
590
+ # weight_threshold: 1,
591
+ # account_auths: [],
592
+ # key_auths: [[active_public_key, 1]],
593
+ # },
594
+ # posting: {
595
+ # weight_threshold: 1,
596
+ # account_auths: [],
597
+ # key_auths: [[posting_public_key, 1]],
598
+ # },
599
+ # memo_key: memo_public_key,
600
+ # json_metadata: '{}'
601
+ # }
602
+ # }
603
+ #
604
+ # Crea::Broadcast.account_update(options)
605
+ #
606
+ # @param options [Hash] options
607
+ # @option options [String] :wif Active wif
608
+ # @option options [Hash] :params
609
+ # * :account (String)
610
+ # * :owner (Hash) (optional)
611
+ # * :active (Hash) (optional)
612
+ # * :posting (Hash) (optional)
613
+ # * :memo_key (String) (optional)
614
+ # * :metadata (Hash) Metadata of the account, becomes `json_metadata`.
615
+ # * :json_metadata (String) String version of `metadata` (use one or the other).
616
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
617
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_account_update
618
+ def self.account_update(options, &block)
619
+ required_fields = %i(account)
620
+ params = options[:params]
621
+
622
+ if !!params[:metadata] && !!params[:json_metadata]
623
+ raise Crea::ArgumentError, 'Assign either metadata or json_metadata, not both.'
624
+ end
625
+
626
+ metadata = params.delete(:metadata) || {}
627
+ metadata ||= (JSON[params[:json_metadata]] || nil) || {}
628
+ params[:json_metadata] = metadata.to_json
629
+
630
+ check_required_fields(params, *required_fields)
631
+
632
+ ops = [[:account_update, params]]
633
+
634
+ process(options.merge(ops: ops), &block)
635
+ end
636
+
637
+ # Users who wish to become a witness must pay a fee acceptable to the
638
+ # current witnesses to apply for the position and allow voting to begin.
639
+ #
640
+ # options = {
641
+ # wif: wif,
642
+ # params: {
643
+ # owner: witness_account_name,
644
+ # url: '',
645
+ # block_signing_key: 'CREA8ZSyzjPm48GmUuMSRufkVYkwYbZzbxeMysAVp7KFQwbTf98TcG',
646
+ # props: {
647
+ # account_creation_fee: '0.000 CREA',
648
+ # maximum_block_size: 131072,
649
+ # cbd_interest_rate:1000
650
+ # },
651
+ # fee: '0.000 CREA',
652
+ # }
653
+ # }
654
+ #
655
+ # Crea::Broadcast.witness_update(options)
656
+ #
657
+ # @param options [Hash] options
658
+ # @option options [String] :wif Active wif
659
+ # @option options [Hash] :params
660
+ # * :owner (String)
661
+ # * :url (String) (optional)
662
+ # * :block_signing_key (String)
663
+ # * :props (String)
664
+ # * :fee (String)
665
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
666
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_witness_update
667
+ def self.witness_update(options, &block)
668
+ required_fields = %i(owner block_signing_key props fee)
669
+ params = options[:params]
670
+ check_required_fields(params, *required_fields)
671
+
672
+ account_creation_fee = params[:props][:account_creation_fee] rescue nil
673
+ params[:props][:account_creation_fee] = normalize_amount(options.merge amount: account_creation_fee)
674
+ params[:fee] = normalize_amount(options.merge amount: params[:fee])
675
+
676
+ ops = [[:witness_update, params]]
677
+
678
+ process(options.merge(ops: ops), &block)
679
+ end
680
+
681
+ # Extensible replacement for #witness_update that supports additional
682
+ # properties added since HF20 and beyond.
683
+ #
684
+ # options = {
685
+ # wif: wif,
686
+ # params: {
687
+ # owner: witness_account_name,
688
+ # props: {
689
+ # account_creation_fee: '0.000 CREA',
690
+ # maximum_block_size: 131072,
691
+ # cbd_interest_rate: 1000,
692
+ # account_subsidy_budget: 50000,
693
+ # account_subsidy_decay: 330782,
694
+ # cbd_exchange_rate: '1.000 CREA',
695
+ # url: "https://creary.net",
696
+ # new_signing_key: 'CREA8LoQjQqJHvotqBo7HjnqmUbFW9oJ2theyqonzUd9DdJ7YYHsvD'
697
+ # }
698
+ # }
699
+ # }
700
+ #
701
+ # Crea::Broadcast.witness_set_properties(options)
702
+ #
703
+ # @param options [Hash] options
704
+ # @option options [String] :wif Active wif
705
+ # @option options [Hash] :params
706
+ # * :owner (String)
707
+ # * :props (String)
708
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
709
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_witness_set_properties
710
+ # @see https://github.com/creary/crea/blob/master/doc/witness_parameters.md
711
+ def self.witness_set_properties(options, &block)
712
+ required_fields = %i(owner props)
713
+ params = options[:params]
714
+ check_required_fields(params, *required_fields)
715
+
716
+ if !!(account_creation_fee = params[:props][:account_creation_fee] rescue nil)
717
+ params[:props][:account_creation_fee] = normalize_amount(options.merge amount: account_creation_fee, serialize: true)
718
+ end
719
+
720
+ if !!(cbd_exchange_rate = params[:props][:cbd_exchange_rate] rescue nil)
721
+ params[:props][:cbd_exchange_rate][:base] = normalize_amount(options.merge amount: cbd_exchange_rate[:base], serialize: true)
722
+ params[:props][:cbd_exchange_rate][:quote] = normalize_amount(options.merge amount: cbd_exchange_rate[:quote], serialize: true)
723
+ params[:props][:cbd_exchange_rate] = params[:props][:cbd_exchange_rate].to_json
724
+ end
725
+
726
+ %i(key new_signing_key).each do |key|
727
+ if !!params[key] && params[key].size == 53
728
+ params[key] = params[key][3..-1]
729
+ end
730
+ end
731
+
732
+ %i(account_creation_fee cbd_exchange_rate url new_signing_key).each do |key|
733
+ next unless !!params[:props][key]
734
+
735
+ val = params[:props][key].to_s
736
+
737
+ params[:props][key] = hexlify val unless val =~ /^[0-9A-F]+$/i
738
+ end
739
+
740
+ params[:props] = params[:props].to_a
741
+
742
+ params[:extensions] ||= []
743
+ ops = [[:witness_set_properties, params]]
744
+
745
+ process(options.merge(ops: ops), &block)
746
+ end
747
+
748
+ # All accounts with a VFS (Vesting Fund Shares) can vote for or against any
749
+ # witness.
750
+ #
751
+ # @param options [Hash] options
752
+ # @option options [String] :wif Active wif
753
+ # @option options [Hash] :params
754
+ # * :account (String)
755
+ # * :witness (String)
756
+ # * :approve (Boolean)
757
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
758
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_account_witness_vote
759
+ def self.account_witness_vote(options, &block)
760
+ required_fields = %i(account witness approve)
761
+ params = options[:params]
762
+ check_required_fields(params, *required_fields)
763
+
764
+ ops = [[:account_witness_vote, params]]
765
+
766
+ process(options.merge(ops: ops), &block)
767
+ end
768
+
769
+ # @param options [Hash] options
770
+ # @option options [String] :wif Active wif
771
+ # @option options [Hash] :params
772
+ # * :account (String)
773
+ # * :proxy (String)
774
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
775
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_account_witness_proxy
776
+ def self.account_witness_proxy(options, &block)
777
+ required_fields = %i(account proxy)
778
+ params = options[:params]
779
+ check_required_fields(params, *required_fields)
780
+
781
+ ops = [[:account_witness_proxy, params]]
782
+
783
+ process(options.merge(ops: ops), &block)
784
+ end
785
+
786
+ # Provides a generic way to add higher level protocols on top of witness
787
+ # consensus.
788
+ #
789
+ # @param options [Hash] options
790
+ # @option options [String] :wif Active wif
791
+ # @option options [Hash] :params
792
+ # * :required_auths (Array<String>)
793
+ # * :id (String)
794
+ # * :data (String)
795
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
796
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_custom
797
+ def self.custom(options, &block)
798
+ required_fields = %i(required_auths id data)
799
+ params = options[:params]
800
+ check_required_fields(params, *required_fields)
801
+
802
+ ops = [[:custom, params]]
803
+
804
+ process(options.merge(ops: ops), &block)
805
+ end
806
+
807
+ # The semmantics for this operation are the same as the {Broadcast#custom_json}
808
+ # operation, but with a binary payload.
809
+ #
810
+ # @param options [Hash] options
811
+ # @option options [String] :wif Posting wif
812
+ # @option options [Hash] :params
813
+ # * :id (String)
814
+ # * :data (String)
815
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
816
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_custom_binary
817
+ def self.custom_binary(options, &block)
818
+ required_fields = %i(id data)
819
+ params = options[:params]
820
+ check_required_fields(params, *required_fields)
821
+
822
+ ops = [[:custom_binary, params]]
823
+
824
+ process(options.merge(ops: ops), &block)
825
+ end
826
+
827
+ # Serves the same purpose as {Broadcast#custom} but also supports required
828
+ # posting authorities.
829
+ #
830
+ # @param options [Hash] options
831
+ # @option options [String] :wif Posting wif
832
+ # @option options [Hash] :params
833
+ # * :required_auths (Array<String>)
834
+ # * :required_posting_auths (Arrat<String>)
835
+ # * :id (String)
836
+ # * :data (Hash) Data of the custom json, becomes `json`.
837
+ # * :json (String) String version of `data` (use one or the other).
838
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
839
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_custom_json
840
+ def self.custom_json(options, &block)
841
+ required_fields = %i(id)
842
+ params = options[:params]
843
+
844
+ if !!params[:data] && !!params[:json]
845
+ raise Crea::ArgumentError, 'Assign either data or json, not both.'
846
+ end
847
+
848
+ data = params.delete(:data) || {}
849
+ data ||= (JSON[params[:json]] || nil) || {}
850
+ params[:json] = data.to_json
851
+
852
+ check_required_fields(params, *required_fields)
853
+
854
+ params[:required_auths] ||= []
855
+ params[:required_posting_auths] ||= []
856
+ ops = [[:custom_json, params]]
857
+
858
+ process(options.merge(ops: ops), &block)
859
+ end
860
+
861
+ # Allows an account to setup a vesting withdraw but with the additional
862
+ # request for the funds to be transferred directly to another account’s
863
+ # balance rather than the withdrawing account.
864
+ #
865
+ # @param options [Hash] options
866
+ # @option options [String] :wif Active wif
867
+ # @option options [Hash] :params
868
+ # * :from_account (String)
869
+ # * :to_account (String)
870
+ # * :percent (Numeric)
871
+ # * :auto_vest (Boolean)
872
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
873
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_set_withdraw_vesting_route
874
+ def self.set_withdraw_vesting_route(options, &block)
875
+ required_fields = %i(from_account to_account percent auto_vest)
876
+ params = options[:params]
877
+ check_required_fields(params, *required_fields)
878
+
879
+ ops = [[:set_withdraw_vesting_route, params]]
880
+
881
+ process(options.merge(ops: ops), &block)
882
+ end
883
+
884
+ # All account recovery requests come from a listed recovery account.
885
+ #
886
+ # @param options [Hash] options
887
+ # @option options [String] :wif Active wif
888
+ # @option options [Hash] :params
889
+ # * :recovery_account (String)
890
+ # * :account_to_recover (String)
891
+ # * :new_owner_authority (Hash)
892
+ # * :extensions (Array) (optional)
893
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
894
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_request_account_recovery
895
+ def self.request_account_recovery(options, &block)
896
+ required_fields = %i(recovery_account account_to_recover new_owner_authority)
897
+ params = options[:params]
898
+ check_required_fields(params, *required_fields)
899
+
900
+ params[:extensions] ||= []
901
+ ops = [[:request_account_recovery, params]]
902
+
903
+ process(options.merge(ops: ops), &block)
904
+ end
905
+
906
+ # @param options [Hash] options
907
+ # @option options [String] :wif Active wif
908
+ # @option options [Hash] :params
909
+ # * :account_to_recover (String)
910
+ # * :new_owner_authority (Hash)
911
+ # * :recent_owner_authority (Hash)
912
+ # * :extensions (Array) (optional)
913
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
914
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_recover_account
915
+ def self.recover_account(options, &block)
916
+ required_fields = %i(account_to_recover new_owner_authority recent_owner_authority)
917
+ params = options[:params]
918
+ check_required_fields(params, *required_fields)
919
+
920
+ params[:extensions] ||= []
921
+ ops = [[:recover_account, params]]
922
+
923
+ process(options.merge(ops: ops), &block)
924
+ end
925
+
926
+ # Each account lists another account as their recovery account.
927
+ #
928
+ # @param options [Hash] options
929
+ # @option options [String] :wif Posting wif
930
+ # @option options [Hash] :params
931
+ # * :account_to_recover (String)
932
+ # * :new_recovery_account (String)
933
+ # * :extensions (Array) (optional)
934
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
935
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_change_recovery_account
936
+ def self.change_recovery_account(options, &block)
937
+ required_fields = %i(account_to_recover)
938
+ params = options[:params]
939
+ check_required_fields(params, *required_fields)
940
+
941
+ params[:new_recovery_account] ||= ''
942
+ params[:extensions] ||= []
943
+ ops = [[:change_recovery_account, params]]
944
+
945
+ process(options.merge(ops: ops), &block)
946
+ end
947
+
948
+ # The purpose of this operation is to enable someone to send money
949
+ # contingently to another individual.
950
+ #
951
+ # @param options [Hash] options
952
+ # @option options [String] :wif Active wif
953
+ # @option options [Hash] :params
954
+ # * :from (String)
955
+ # * :to (String)
956
+ # * :agent (String)
957
+ # * :escrow_id (String)
958
+ # * :cbd_amount (String)
959
+ # * :crea_amount (String)
960
+ # * :fee (String)
961
+ # * :ratification_deadline (String)
962
+ # * :escrow_expiration (String)
963
+ # * :meta (Hash) Meta of the escrow transfer, becomes `json_meta`.
964
+ # * :json_meta (String) String version of `metadata` (use one or the other).
965
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
966
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_escrow_transfer
967
+ def self.escrow_transfer(options, &block)
968
+ required_fields = %i(from to agent escrow_id fee ratification_deadline)
969
+ params = options[:params]
970
+
971
+ if !!params[:meta] && !!params[:json_meta]
972
+ raise Crea::ArgumentError, 'Assign either meta or json_meta, not both.'
973
+ end
974
+
975
+ meta = params.delete(:meta) || {}
976
+ meta ||= (JSON[params[:json_meta]] || nil) || {}
977
+ params[:json_meta] = meta.to_json
978
+
979
+ check_required_fields(params, *required_fields)
980
+
981
+ params[:cbd_amount] = normalize_amount(options.merge amount: params[:cbd_amount])
982
+ params[:crea_amount] = normalize_amount(options.merge amount: params[:crea_amount])
983
+ params[:fee] = normalize_amount(options.merge amount: params[:fee])
984
+
985
+ params[:ratification_deadline] = Time.parse(params[:ratification_deadline].to_s)
986
+ params[:ratification_deadline] = params[:ratification_deadline].strftime('%Y-%m-%dT%H:%M:%S')
987
+
988
+ if !!params[:escrow_expiration]
989
+ params[:escrow_expiration] = Time.parse(params[:escrow_expiration].to_s)
990
+ params[:escrow_expiration] = params[:escrow_expiration].strftime('%Y-%m-%dT%H:%M:%S')
991
+ end
992
+
993
+ ops = [[:escrow_transfer, params]]
994
+
995
+ process(options.merge(ops: ops), &block)
996
+ end
997
+
998
+ # If either the sender or receiver of an escrow payment has an issue, they
999
+ # can raise it for dispute.
1000
+ #
1001
+ # @param options [Hash] options
1002
+ # @option options [String] :wif Active wif
1003
+ # @option options [Hash] :params
1004
+ # * :from (String)
1005
+ # * :to (String)
1006
+ # * :agent (String)
1007
+ # * :who (String)
1008
+ # * :escrow_id (String)
1009
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1010
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_escrow_dispute
1011
+ def self.escrow_dispute(options, &block)
1012
+ required_fields = %i(from to agent who escrow_id)
1013
+ params = options[:params]
1014
+ check_required_fields(params, *required_fields)
1015
+
1016
+ ops = [[:escrow_dispute, params]]
1017
+
1018
+ process(options.merge(ops: ops), &block)
1019
+ end
1020
+
1021
+ # This operation can be used by anyone associated with the escrow transfer
1022
+ # to release funds if they have permission.
1023
+ #
1024
+ # @param options [Hash] options
1025
+ # @option options [String] :wif Active wif
1026
+ # @option options [Hash] :params
1027
+ # * :from (String)
1028
+ # * :to (String)
1029
+ # * :agent (String)
1030
+ # * :who (String)
1031
+ # * :receiver (String)
1032
+ # * :escrow_id (String)
1033
+ # * :cbd_amount (String)
1034
+ # * :crea_amount (String)
1035
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1036
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_escrow_release
1037
+ def self.escrow_release(options, &block)
1038
+ required_fields = %i(from to agent who receiver escrow_id)
1039
+ params = options[:params]
1040
+ check_required_fields(params, *required_fields)
1041
+
1042
+ params[:cbd_amount] = normalize_amount(options.merge amount: params[:cbd_amount])
1043
+ params[:crea_amount] = normalize_amount(options.merge amount: params[:crea_amount])
1044
+
1045
+ ops = [[:escrow_release, params]]
1046
+
1047
+ process(options.merge(ops: ops), &block)
1048
+ end
1049
+
1050
+ # The agent and to accounts must approve an escrow transaction for it to be
1051
+ # valid on the blockchain.
1052
+ #
1053
+ # @param options [Hash] options
1054
+ # @option options [String] :wif Active wif
1055
+ # @option options [Hash] :params
1056
+ # * :from (String)
1057
+ # * :to (String)
1058
+ # * :agent (String)
1059
+ # * :who (String)
1060
+ # * :escrow_id (String)
1061
+ # * :approve (String)
1062
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1063
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_escrow_approve
1064
+ def self.escrow_approve(options, &block)
1065
+ required_fields = %i(from to agent who escrow_id approve)
1066
+ params = options[:params]
1067
+ check_required_fields(params, *required_fields)
1068
+
1069
+ ops = [[:escrow_approve, params]]
1070
+
1071
+ process(options.merge(ops: ops), &block)
1072
+ end
1073
+
1074
+ # For time locked savings accounts.
1075
+ #
1076
+ # @param options [Hash] options
1077
+ # @option options [String] :wif Active wif
1078
+ # @option options [Hash] :params
1079
+ # * :from (String)
1080
+ # * :to (String)
1081
+ # * :amount (String)
1082
+ # * :memo (String) (optional)
1083
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1084
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_transfer_to_savings
1085
+ def self.transfer_to_savings(options, &block)
1086
+ required_fields = %i(from to amount)
1087
+ params = options[:params]
1088
+ check_required_fields(params, *required_fields)
1089
+
1090
+ params[:memo] ||= ''
1091
+ params[:amount] = normalize_amount(options.merge amount: params[:amount])
1092
+
1093
+ ops = [[:transfer_to_savings, params]]
1094
+
1095
+ process(options.merge(ops: ops), &block)
1096
+ end
1097
+
1098
+ # @param options [Hash] options
1099
+ # @option options [String] :wif Active wif
1100
+ # @option options [Hash] :params
1101
+ # * :from (String)
1102
+ # * :request_id (String)
1103
+ # * :to (String)
1104
+ # * :amount (String)
1105
+ # * :memo (String) (optional)
1106
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1107
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_transfer_from_savings
1108
+ def self.transfer_from_savings(options, &block)
1109
+ required_fields = %i(from request_id to amount)
1110
+ params = options[:params]
1111
+ check_required_fields(params, *required_fields)
1112
+
1113
+ params[:memo] ||= ''
1114
+ params[:amount] = normalize_amount(options.merge amount: params[:amount])
1115
+
1116
+ ops = [[:transfer_from_savings, params]]
1117
+
1118
+ process(options.merge(ops: ops), &block)
1119
+ end
1120
+
1121
+ # @param options [Hash] options
1122
+ # @option options [String] :wif Active wif
1123
+ # @option options [Hash] :params
1124
+ # * :from (String)
1125
+ # * :request_id (String)
1126
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1127
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_cancel_transfer_from_savings
1128
+ def self.cancel_transfer_from_savings(options, &block)
1129
+ required_fields = %i(from request_id)
1130
+ params = options[:params]
1131
+ check_required_fields(params, *required_fields)
1132
+
1133
+ ops = [[:cancel_transfer_from_savings, params]]
1134
+
1135
+ process(options.merge(ops: ops), &block)
1136
+ end
1137
+
1138
+ # An account can chose to decline their voting rights after a 30 day delay.
1139
+ # This includes voting on content and witnesses. **The voting rights cannot
1140
+ # be acquired again once they have been declined.** This is only to
1141
+ # formalize a smart contract between certain accounts and the community that
1142
+ # currently only exists as a social contract.
1143
+ #
1144
+ # @param options [Hash] options
1145
+ # @option options [String] :wif Owner wif
1146
+ # @option options [Hash] :params
1147
+ # * :account (String)
1148
+ # * :decline (String)
1149
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1150
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_decline_voting_rights
1151
+ def self.decline_voting_rights(options, &block)
1152
+ required_fields = %i(account decline)
1153
+ params = options[:params]
1154
+ check_required_fields(params, *required_fields)
1155
+
1156
+ ops = [[:decline_voting_rights, params]]
1157
+
1158
+ process(options.merge(ops: ops), &block)
1159
+ end
1160
+
1161
+ # Delegate vesting shares from one account to the other.
1162
+ #
1163
+ # @param options [Hash] options
1164
+ # @option options [String] :wif Active wif
1165
+ # @option options [Hash] :params
1166
+ # * :delegator (String)
1167
+ # * :delegatee (String)
1168
+ # * :vesting_shares (String)
1169
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1170
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_delegate_vesting_shares
1171
+ def self.delegate_vesting_shares(options, &block)
1172
+ required_fields = %i(delegator delegatee vesting_shares)
1173
+ params = options[:params]
1174
+ check_required_fields(params, *required_fields)
1175
+
1176
+ params[:vesting_shares] = normalize_amount(options.merge amount: params[:vesting_shares])
1177
+ ops = [[:delegate_vesting_shares, params]]
1178
+
1179
+ process(options.merge(ops: ops), &block)
1180
+ end
1181
+
1182
+ # @param options [Hash] options
1183
+ # @option options [String] :wif Active wif
1184
+ # @option options [Hash] :params
1185
+ # * :fee (String)
1186
+ # * :delegation (String)
1187
+ # * :creator (String)
1188
+ # * :new_account_name (String)
1189
+ # * :owner (String)
1190
+ # * :active (String)
1191
+ # * :posting (String)
1192
+ # * :memo_key (String)
1193
+ # * :metadata (Hash) Metadata of the account, becomes `json_metadata`.
1194
+ # * :json_metadata (String) String version of `metadata` (use one or the other).
1195
+ # * :extensions (Array)
1196
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1197
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_account_create_with_delegation
1198
+ def self.account_create_with_delegation(options, &block)
1199
+ required_fields = %i(fee delegation creator new_account_name owner active posting memo_key)
1200
+ params = options[:params]
1201
+
1202
+ if !!params[:metadata] && !!params[:json_metadata]
1203
+ raise Crea::ArgumentError, 'Assign either metadata or json_metadata, not both.'
1204
+ end
1205
+
1206
+ metadata = params.delete(:metadata) || {}
1207
+ metadata ||= (JSON[params[:json_metadata]] || nil) || {}
1208
+ params[:json_metadata] = metadata.to_json
1209
+
1210
+ check_required_fields(params, *required_fields)
1211
+
1212
+ params[:fee] = normalize_amount(options.merge amount: params[:fee])
1213
+ params[:delegation] = normalize_amount(options.merge amount: params[:delegation])
1214
+ params[:extensions] ||= []
1215
+
1216
+ ops = [[:account_create_with_delegation, params]]
1217
+
1218
+ process(options.merge(ops: ops), &block)
1219
+ end
1220
+
1221
+ # @param options [Hash] options
1222
+ # @option options [String] :wif Active wif
1223
+ # @option options [Hash] :params
1224
+ # * :creator (String)
1225
+ # * :fee (String)
1226
+ # * :extensions (Array)
1227
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1228
+ # @see https://developers.crea.io/apidefinitions/broadcast-ops#broadcast_ops_claim_account
1229
+ def self.claim_account(options, &block)
1230
+ required_fields = %i(creator fee)
1231
+ params = options[:params]
1232
+
1233
+ check_required_fields(params, *required_fields)
1234
+
1235
+ params[:fee] = normalize_amount(options.merge amount: params[:fee])
1236
+ params[:extensions] ||= []
1237
+
1238
+ ops = [[:claim_account, params]]
1239
+
1240
+ process(options.merge(ops: ops), &block)
1241
+ end
1242
+
1243
+ # @param options [Hash] options
1244
+ # @option options [Array<Array<Hash>] :ops Operations to process.
1245
+ # @option options [Boolean] :pretend Just validate, do not broadcast.
1246
+ def self.process(options, &block)
1247
+ ops = options[:ops]
1248
+ tx = TransactionBuilder.new(options)
1249
+ response = nil
1250
+
1251
+ loop do; begin
1252
+ tx.operations = ops
1253
+ trx = tx.transaction
1254
+
1255
+ response = if !!options[:pretend]
1256
+ if !!options[:app_base]
1257
+ database_api(options).verify_authority(trx: trx)
1258
+ else
1259
+ database_api(options).verify_authority(trx)
1260
+ end
1261
+ else
1262
+ if !!options[:app_base]
1263
+ network_broadcast_api(options).broadcast_transaction(trx: trx)
1264
+ else
1265
+ network_broadcast_api(options).broadcast_transaction_synchronous(trx)
1266
+ end
1267
+ end
1268
+
1269
+ break
1270
+ rescue => e
1271
+ if can_retry? e
1272
+ tx.expiration = nil
1273
+ redo
1274
+ end
1275
+
1276
+ raise e
1277
+ end; end
1278
+
1279
+ if !!block
1280
+ block.call response.result
1281
+ else
1282
+ return response.result
1283
+ end
1284
+ end
1285
+ private
1286
+ # @private
1287
+ def self.normalize_amount(options)
1288
+ if !!options[:app_base]
1289
+ Type::Amount.to_h(options[:amount])
1290
+ elsif !!options[:serialize]
1291
+ Type::Amount.to_s(options[:amount])
1292
+ else
1293
+ Type::Amount.to_s(options[:amount])
1294
+ end
1295
+ end
1296
+
1297
+ def self.normalize_beneficiaries(options)
1298
+ # Type::Beneficiaries.new(options[:beneficiaries])
1299
+ {beneficiaries: options[:beneficiaries]}
1300
+ end
1301
+
1302
+ # @private
1303
+ def self.database_api(options)
1304
+ options[:database_api] ||= if !!options[:app_base]
1305
+ Crea::DatabaseApi.new(options)
1306
+ else
1307
+ Crea::CondenserApi.new(options)
1308
+ end
1309
+ end
1310
+
1311
+ # @private
1312
+ def self.network_broadcast_api(options)
1313
+ options[:network_broadcast_api] ||= if !!options[:app_base]
1314
+ Crea::NetworkBroadcaseApi.new(options)
1315
+ else
1316
+ Crea::CondenserApi.new(options)
1317
+ end
1318
+ end
1319
+
1320
+ # @private
1321
+ def self.check_required_fields(hash, *fields)
1322
+ fields.each do |field|
1323
+ value = hash[field]
1324
+
1325
+ raise Crea::ArgumentError, "#{field}: required" if value.nil?
1326
+
1327
+ case value
1328
+ when String, Array, Hash
1329
+ raise Crea::ArgumentError, "#{field}: required" if value.empty?
1330
+ end
1331
+ end
1332
+ end
1333
+ end
1334
+ end