stellar-base 0.29.0 → 0.30.0

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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/generated/stellar/allow_trust_result_code.rb +4 -1
  4. data/generated/stellar/alpha_num12.rb +20 -0
  5. data/generated/stellar/alpha_num4.rb +20 -0
  6. data/generated/stellar/asset.rb +2 -15
  7. data/generated/stellar/asset_type.rb +3 -1
  8. data/generated/stellar/change_trust_asset.rb +39 -0
  9. data/generated/stellar/change_trust_op.rb +2 -2
  10. data/generated/stellar/change_trust_result_code.rb +13 -7
  11. data/generated/stellar/claim_atom.rb +31 -0
  12. data/generated/stellar/claim_atom_type.rb +24 -0
  13. data/generated/stellar/claim_liquidity_atom.rb +30 -0
  14. data/generated/stellar/claim_offer_atom_v0.rb +33 -0
  15. data/generated/stellar/envelope_type.rb +10 -8
  16. data/generated/stellar/{operation_id/id.rb → hash_id_preimage/operation_id.rb} +2 -2
  17. data/generated/stellar/{operation_id.rb → hash_id_preimage/revoke_id.rb} +12 -16
  18. data/generated/stellar/hash_id_preimage.rb +44 -0
  19. data/generated/stellar/ledger_entry/data.rb +4 -0
  20. data/generated/stellar/ledger_entry.rb +2 -0
  21. data/generated/stellar/ledger_entry_type.rb +3 -1
  22. data/generated/stellar/ledger_header/ext.rb +4 -0
  23. data/generated/stellar/ledger_header.rb +2 -0
  24. data/generated/stellar/{asset/alpha_num12.rb → ledger_header_extension_v1/ext.rb} +9 -7
  25. data/generated/stellar/ledger_header_extension_v1.rb +30 -0
  26. data/generated/stellar/ledger_header_flags.rb +24 -0
  27. data/generated/stellar/{asset/alpha_num4.rb → ledger_key/liquidity_pool.rb} +4 -6
  28. data/generated/stellar/ledger_key/trust_line.rb +2 -2
  29. data/generated/stellar/ledger_key.rb +10 -1
  30. data/generated/stellar/ledger_upgrade.rb +4 -0
  31. data/generated/stellar/ledger_upgrade_type.rb +3 -1
  32. data/generated/stellar/liquidity_pool_constant_product_parameters.rb +22 -0
  33. data/generated/stellar/liquidity_pool_deposit_op.rb +26 -0
  34. data/generated/stellar/liquidity_pool_deposit_result.rb +26 -0
  35. data/generated/stellar/liquidity_pool_deposit_result_code.rb +41 -0
  36. data/generated/stellar/liquidity_pool_entry/body/constant_product.rb +31 -0
  37. data/generated/stellar/liquidity_pool_entry/body.rb +37 -0
  38. data/generated/stellar/liquidity_pool_entry.rb +38 -0
  39. data/generated/stellar/liquidity_pool_parameters.rb +23 -0
  40. data/generated/stellar/liquidity_pool_type.rb +20 -0
  41. data/generated/stellar/liquidity_pool_withdraw_op.rb +24 -0
  42. data/generated/stellar/liquidity_pool_withdraw_result.rb +26 -0
  43. data/generated/stellar/liquidity_pool_withdraw_result_code.rb +36 -0
  44. data/generated/stellar/manage_offer_success_result.rb +2 -2
  45. data/generated/stellar/operation/body.rb +8 -0
  46. data/generated/stellar/operation.rb +4 -0
  47. data/generated/stellar/operation_result/tr.rb +8 -0
  48. data/generated/stellar/operation_result.rb +4 -0
  49. data/generated/stellar/operation_type.rb +5 -1
  50. data/generated/stellar/path_payment_strict_receive_result/success.rb +2 -2
  51. data/generated/stellar/path_payment_strict_receive_result.rb +1 -1
  52. data/generated/stellar/path_payment_strict_send_result/success.rb +2 -2
  53. data/generated/stellar/path_payment_strict_send_result.rb +1 -1
  54. data/generated/stellar/revoke_sponsorship_result_code.rb +3 -1
  55. data/generated/stellar/scp_quorum_set.rb +2 -2
  56. data/generated/stellar/set_trust_line_flags_result_code.rb +4 -1
  57. data/generated/stellar/trust_line_asset.rb +39 -0
  58. data/generated/stellar/trust_line_entry/ext/v1/ext.rb +4 -0
  59. data/generated/stellar/trust_line_entry/ext/v1.rb +2 -0
  60. data/generated/stellar/trust_line_entry/ext.rb +2 -0
  61. data/generated/stellar/trust_line_entry.rb +7 -5
  62. data/generated/stellar/trust_line_entry_extension_v2/ext.rb +24 -0
  63. data/generated/stellar/trust_line_entry_extension_v2.rb +30 -0
  64. data/generated/stellar-base-generated.rb +25 -1
  65. data/lib/stellar/account_flags.rb +1 -1
  66. data/lib/stellar/amount.rb +36 -0
  67. data/lib/stellar/asset.rb +8 -0
  68. data/lib/stellar/dsl.rb +3 -0
  69. data/lib/stellar/ledger_key.rb +5 -3
  70. data/lib/stellar/liquidity_pool/base_pool.rb +47 -0
  71. data/lib/stellar/liquidity_pool/constant_product_pool.rb +15 -0
  72. data/lib/stellar/liquidity_pool.rb +12 -0
  73. data/lib/stellar/operation.rb +346 -444
  74. data/lib/stellar/price.rb +13 -7
  75. data/lib/stellar/transaction_builder.rb +8 -5
  76. data/lib/stellar/version.rb +1 -1
  77. data/lib/stellar-base.rb +2 -0
  78. metadata +39 -10
@@ -15,212 +15,194 @@ module Stellar
15
15
  # Construct a new Stellar::Operation from the provided
16
16
  # source account and body
17
17
  #
18
- # @param [Hash] attributes the attributes to create the operation with
19
- # @option attributes [Stellar::KeyPair] :source_account
20
- # @option attributes [Stellar::Operation::Body] :body
18
+ # @param source_account [KeyPair, nil] the source account for the operation
19
+ # @param [(Symbol, XDR::Struct)] body a tuple containing operation type and operation object
21
20
  #
22
21
  # @return [Stellar::Operation] the built operation
23
- def make(attributes = {})
24
- source_account = attributes[:source_account]
22
+ def make(body:, source_account: nil)
23
+ raise ArgumentError, "Bad :source_account" if source_account && !source_account.is_a?(Stellar::KeyPair)
25
24
 
26
- if source_account && !source_account.is_a?(Stellar::KeyPair)
27
- raise ArgumentError, "Bad :source_account"
28
- end
29
-
30
- body = Stellar::Operation::Body.new(*attributes[:body])
25
+ body = Stellar::Operation::Body.new(*body)
31
26
 
32
27
  Stellar::Operation.new(
33
- body: body,
34
- source_account: source_account&.muxed_account
28
+ source_account: source_account&.muxed_account,
29
+ body: body
35
30
  )
36
31
  end
37
32
 
33
+ # Create Account operation builder
38
34
  #
39
- # Helper method to create a valid PaymentOp, wrapped
40
- # in the necessary XDR structs to be included within a
41
- # transactions `operations` array.
35
+ # @param source_account [KeyPair, nil] the source account for the operation
36
+ # @param destination [KeyPair] the account to create
37
+ # @param starting_balance [String, Numeric] the amount to deposit to the newly created account
42
38
  #
43
- # @see Stellar::Asset
44
- #
45
- # @param [Hash] attributes the attributes to create the operation with
46
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
47
- # @option attributes [Array] :amount the amount to pay
48
- # @return [Stellar::Operation] the built operation, containing a
49
- # Stellar::PaymentOp body
50
- def payment(attributes = {})
51
- destination = attributes[:destination]
52
- asset, amount = get_asset_amount(attributes[:amount])
53
-
54
- raise ArgumentError unless destination.is_a?(KeyPair)
55
-
56
- op = PaymentOp.new
57
- op.asset = asset
58
- op.amount = amount
59
- op.destination = destination.muxed_account
39
+ # @return [Stellar::Operation] the built operation
40
+ def create_account(destination:, starting_balance:, source_account: nil)
41
+ op = CreateAccountOp.new(
42
+ destination: KeyPair(destination).account_id,
43
+ starting_balance: interpret_amount(starting_balance)
44
+ )
60
45
 
61
- make(attributes.merge({
62
- body: [:payment, op]
63
- }))
46
+ make(source_account: source_account, body: [:create_account, op])
64
47
  end
65
48
 
49
+ # Account Merge operation builder
66
50
  #
67
- # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
68
- # in the necessary XDR structs to be included within a
69
- # transactions `operations` array.
70
- #
71
- # @deprecated Please use Operation.path_payment_strict_receive
72
- #
73
- # @see Stellar::Asset
51
+ # @param [Stellar::KeyPair, nil] source_account the source account for the operation
52
+ # @param [Stellar::KeyPair] destination the account to merge into
74
53
  #
75
- # @param [Hash] attributes the attributes to create the operation with
76
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
77
- # @option attributes [Array] :amount the destination asset and the amount to pay
78
- # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
79
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
80
- #
81
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
82
- #
83
- def path_payment(attributes = {})
84
- path_payment_strict_receive(attributes)
54
+ # @return [Stellar::Operation] the built operation
55
+ def account_merge(destination:, source_account: nil)
56
+ raise ArgumentError, "Bad destination" unless destination.is_a?(KeyPair)
57
+
58
+ make(source_account: source_account, body: [:account_merge, destination.muxed_account])
85
59
  end
86
60
 
61
+ # Set Options operation builder.
87
62
  #
88
- # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
89
- # in the necessary XDR structs to be included within a
90
- # transactions `operations` array.
91
- #
92
- # @see Stellar::Asset
63
+ # @param source_account [KeyPair, nil] the source account for the operation
64
+ # @param home_domain [String, nil\] the home domain of the account
65
+ # @param signer [Signer, nil] add, remove or adjust weight of the co-signer
66
+ # @param set [Array<AccountFlags>] flags to set
67
+ # @param clear [Array<AccountFlags>] flags to clear
68
+ # @param inflation_dest [KeyPair, nil] the inflation destination of the account
93
69
  #
94
- # @param [Hash] attributes the attributes to create the operation with
95
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
96
- # @option attributes [Array] :amount the destination asset and the amount to pay
97
- # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
98
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
70
+ # @return [Stellar::Operation] the built operation
71
+ def set_options(set: [], clear: [], home_domain: nil, signer: nil, inflation_dest: nil, source_account: nil, **attributes)
72
+ raise ArgumentError, "Bad inflation_dest" if inflation_dest && !inflation_dest.is_a?(KeyPair)
73
+
74
+ op = SetOptionsOp.new(
75
+ set_flags: Stellar::AccountFlags.make_mask(set),
76
+ clear_flags: Stellar::AccountFlags.make_mask(clear),
77
+ master_weight: attributes[:master_weight],
78
+ low_threshold: attributes[:low_threshold],
79
+ med_threshold: attributes[:med_threshold],
80
+ high_threshold: attributes[:high_threshold],
81
+ signer: signer,
82
+ home_domain: home_domain,
83
+ inflation_dest: inflation_dest&.account_id
84
+ )
85
+
86
+ make(source_account: source_account, body: [:set_options, op])
87
+ end
88
+
89
+ # Bump Sequence operation builder
99
90
  #
100
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
91
+ # @param [Stellar::KeyPair] source_account the source account for the operation
92
+ # @param [Integer] bump_to the target sequence number for the account
101
93
  #
102
- def path_payment_strict_receive(attributes = {})
103
- destination = attributes[:destination]
104
- asset, amount = get_asset_amount(attributes[:amount])
105
- send_asset, send_max = get_asset_amount(attributes[:with])
106
- path = (attributes[:path] || []).map { |p|
107
- p.is_a?(Array) ? Stellar::Asset.send(*p) : p
108
- }
94
+ # @return [Stellar::Operation] the built operation
95
+ def bump_sequence(bump_to:, source_account: nil)
96
+ raise ArgumentError, ":bump_to too big" unless bump_to <= MAX_INT64
109
97
 
110
- raise ArgumentError unless destination.is_a?(KeyPair)
98
+ op = BumpSequenceOp.new(
99
+ bump_to: bump_to
100
+ )
111
101
 
112
- op = PathPaymentStrictReceiveOp.new
113
- op.send_asset = send_asset
114
- op.send_max = send_max
115
- op.destination = destination.muxed_account
116
- op.dest_asset = asset
117
- op.dest_amount = amount
118
- op.path = path
119
-
120
- make(attributes.merge({
121
- body: [:path_payment_strict_receive, op]
122
- }))
102
+ make(source_account: source_account, body: [:bump_sequence, op])
123
103
  end
124
104
 
105
+ # Manage Data operation builder
125
106
  #
126
- # Helper method to create a valid PathPaymentStrictSendOp, wrapped
127
- # in the necessary XDR structs to be included within a
128
- # transactions `operations` array.
129
- #
130
- # @see Stellar::Asset
131
- #
132
- # @param [Hash] attributes the attributes to create the operation with
133
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
134
- # @option attributes [Array] :amount the destination asset and the minimum amount of destination asset to be received
135
- # @option attributes [Array] :with the source asset and amount to pay with
136
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
137
- #
138
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
107
+ # @param [Stellar::KeyPair, nil] source_account the source account for the operation
108
+ # @param [String] name the name of the data entry
109
+ # @param [String, nil] value the value of the data entry (nil to remove the entry)
139
110
  #
140
- def path_payment_strict_send(attributes = {})
141
- destination = attributes[:destination]
142
- asset, dest_min = get_asset_amount(attributes[:amount])
143
- send_asset, send_amount = get_asset_amount(attributes[:with])
144
- path = (attributes[:path] || []).map { |p|
145
- p.is_a?(Array) ? Stellar::Asset.send(*p) : p
146
- }
111
+ # @return [Stellar::Operation] the built operation
112
+ def manage_data(name:, value: nil, source_account: nil)
113
+ raise ArgumentError, "Invalid :name" unless name.is_a?(String)
114
+ raise ArgumentError, ":name too long" if name.bytesize > 64
115
+ raise ArgumentError, ":value too long" if value && value.bytesize > 64
147
116
 
148
- raise ArgumentError unless destination.is_a?(KeyPair)
117
+ op = ManageDataOp.new(
118
+ data_name: name,
119
+ data_value: value
120
+ )
149
121
 
150
- op = PathPaymentStrictSendOp.new
151
- op.send_asset = send_asset
152
- op.send_amount = send_amount
153
- op.destination = destination.muxed_account
154
- op.dest_asset = asset
155
- op.dest_min = dest_min
156
- op.path = path
157
-
158
- make(attributes.merge({
159
- body: [:path_payment_strict_send, op]
160
- }))
122
+ make(source_account: source_account, body: [:manage_data, op])
161
123
  end
162
124
 
163
- def create_account(attributes = {})
164
- destination = attributes[:destination]
165
- starting_balance = interpret_amount(attributes[:starting_balance])
125
+ # Change Trust operation builder
126
+ #
127
+ # @param source_account [KeyPair, nil] the source account for the operation
128
+ # @param asset [Asset] the asset to trust
129
+ # @param limit [String, Numeric] the maximum amount to trust, defaults to max int64 (0 deletes the trustline)
130
+ #
131
+ # @return [Stellar::Operation] the built operation
132
+ def change_trust(asset: nil, limit: nil, source_account: nil, **attrs)
133
+ if attrs.key?(:line) && !asset
134
+ Stellar::Deprecation.warn("`line` parameter is deprecated, use `asset` instead")
135
+ asset = attrs[:line]
136
+ end
137
+
138
+ op = ChangeTrustOp.new(
139
+ line: Asset(asset).to_change_trust_asset,
140
+ limit: limit ? interpret_amount(limit) : MAX_INT64
141
+ )
166
142
 
167
- raise ArgumentError unless destination.is_a?(KeyPair)
143
+ make(source_account: source_account, body: [:change_trust, op])
144
+ end
168
145
 
169
- op = CreateAccountOp.new
170
- op.destination = destination.account_id
171
- op.starting_balance = starting_balance
146
+ # Set Trustline Flags operation builder
147
+ #
148
+ # @param source_account [KeyPair, nil] the source account for the operation
149
+ # @param asset [Stellar::Asset]
150
+ # @param trustor [Stellar::KeyPair]
151
+ # @param flags [{String, Symbol, Stellar::TrustLineFlags => true, false}] flags to to set or clear
152
+ #
153
+ # @return [Stellar::Operation] the built operation
154
+ def set_trust_line_flags(asset:, trustor:, flags: {}, source_account: nil)
155
+ op = Stellar::SetTrustLineFlagsOp.new(
156
+ trustor: KeyPair(trustor).account_id,
157
+ asset: Asset(asset),
158
+ attributes: TrustLineFlags.set_clear_masks(flags)
159
+ )
172
160
 
173
- make(attributes.merge({
174
- body: [:create_account, op]
175
- }))
161
+ make(source_account: source_account, body: [:set_trust_line_flags, op])
176
162
  end
177
163
 
178
- # Helper method to create a valid ChangeTrustOp, wrapped
179
- # in the necessary XDR structs to be included within a
180
- # transactions `operations` array.
181
- #
182
- # @param [Hash] attributes the attributes to create the operation with
183
- # @option attributes [Stellar::Asset] :line the asset to trust
184
- # @option attributes [Fixnum] :limit the maximum amount to trust, defaults to max int64,
185
- # if the limit is set to 0 it deletes the trustline.
186
- #
187
- # @return [Stellar::Operation] the built operation, containing a
188
- # Stellar::ChangeTrustOp body
189
- def change_trust(attributes = {})
190
- line = attributes[:line]
191
- unless line.is_a?(Asset)
192
- unless Asset::TYPES.include?(line[0])
193
- fail ArgumentError, "must be one of #{Asset::TYPES}"
194
- end
195
- line = Asset.send(*line)
196
- end
164
+ # Clawback operation builder
165
+ #
166
+ # @param [Stellar::KeyPair] source_account the source account for the operation
167
+ # @param [String|Account|PublicKey|SignerKey|KeyPair] from the account to clawback from
168
+ # @param [(Asset, Numeric)] amount the amount of asset to subtract from the balance
169
+ #
170
+ # @return [Stellar::Operation] the built operation
171
+ def clawback(from:, amount:, source_account: nil)
172
+ asset, amount = get_asset_amount(amount)
197
173
 
198
- limit = attributes.key?(:limit) ? interpret_amount(attributes[:limit]) : MAX_INT64
174
+ if amount == 0
175
+ raise ArgumentError, "Amount can not be zero"
176
+ end
199
177
 
200
- raise ArgumentError, "Bad :limit #{limit}" unless limit.is_a?(Integer)
178
+ if amount < 0
179
+ raise ArgumentError, "Negative amount is not allowed"
180
+ end
201
181
 
202
- op = ChangeTrustOp.new(line: line, limit: limit)
182
+ op = ClawbackOp.new(
183
+ amount: amount,
184
+ from: KeyPair(from).muxed_account,
185
+ asset: asset
186
+ )
203
187
 
204
- make(attributes.merge({
205
- body: [:change_trust, op]
206
- }))
188
+ make(source_account: source_account, body: [:clawback, op])
207
189
  end
208
190
 
209
- # Helper method to create a valid CreateClaimableBalanceOp, ready to be used
210
- # within a transactions `operations` array.
191
+ # Create Claimable Balance operation builder.
211
192
  #
212
193
  # @see Stellar::DSL::Claimant
213
194
  # @see https://github.com/astroband/ruby-stellar-sdk/tree/master/base/examples/claimable_balances.rb
214
195
  #
196
+ # @param source_account [KeyPair, nil] the source account for the operation
215
197
  # @param asset [Asset] the asset to transfer to a claimable balance
216
198
  # @param amount [Fixnum] the amount of `asset` to put into a claimable balance
217
199
  # @param claimants [Array<Claimant>] accounts authorized to claim the balance in the future
218
200
  #
219
201
  # @return [Operation] the built operation
220
- def create_claimable_balance(asset:, amount:, claimants:, **attributes)
202
+ def create_claimable_balance(asset:, amount:, claimants:, source_account: nil)
221
203
  op = CreateClaimableBalanceOp.new(asset: asset, amount: amount, claimants: claimants)
222
204
 
223
- make(attributes.merge(body: [:create_claimable_balance, op]))
205
+ make(source_account: source_account, body: [:create_claimable_balance, op])
224
206
  end
225
207
 
226
208
  # Helper method to create a valid CreateClaimableBalanceOp, ready to be used
@@ -229,337 +211,276 @@ module Stellar
229
211
  # @see Stellar::DSL::Claimant
230
212
  # @see https://github.com/astroband/ruby-stellar-sdk/tree/master/base/examples/claimable_balances.rb
231
213
  #
214
+ # @param source_account [KeyPair, nil] the source account for the operation
232
215
  # @param balance_id [ClaimableBalanceID] unique ID of claimable balance
233
216
  #
234
- # @return [Operation] the built operation, containing a Stellar::ChangeTrustOp body
235
- def claim_claimable_balance(balance_id:, **attributes)
217
+ # @return [Operation] the built operation
218
+ def claim_claimable_balance(balance_id:, source_account: nil)
236
219
  op = ClaimClaimableBalanceOp.new(balance_id: balance_id)
237
220
 
238
- make(attributes.merge(body: [:claim_claimable_balance, op]))
221
+ make(source_account: source_account, body: [:claim_claimable_balance, op])
239
222
  end
240
223
 
241
- def begin_sponsoring_future_reserves(sponsored:, **attributes)
242
- op = BeginSponsoringFutureReservesOp.new(
243
- sponsored_id: KeyPair(sponsored).account_id
244
- )
224
+ # Clawback Claimable Balance operation builder
225
+ #
226
+ # @param [Stellar::KeyPair] source_account the source account for the operation
227
+ # @param [String] balance_id claimable balance ID as a hexadecimal string
228
+ #
229
+ # @return [Stellar::Operation] the built operation
230
+ def clawback_claimable_balance(balance_id:, source_account: nil)
231
+ balance_id = Stellar::ClaimableBalanceID.from_xdr(balance_id, :hex)
232
+ op = ClawbackClaimableBalanceOp.new(balance_id: balance_id)
245
233
 
246
- make(attributes.merge(body: [:begin_sponsoring_future_reserves, op]))
234
+ make(source_account: source_account, body: [:clawback_claimable_balance, op])
235
+ rescue XDR::ReadError
236
+ raise ArgumentError, "Claimable balance id '#{balance_id}' is invalid"
247
237
  end
248
238
 
249
- def end_sponsoring_future_reserves(**attributes)
250
- make(attributes.merge(body: [:end_sponsoring_future_reserves]))
239
+ # Payment Operation builder
240
+ #
241
+ # @param source_account [KeyPair, nil] the source account for the operation
242
+ # @param [Stellar::KeyPair] destination the receiver of the payment
243
+ # @param [(Asset, Numeric)] amount the amount to pay
244
+ #
245
+ # @return [Stellar::Operation] the built operation
246
+ def payment(destination:, amount:, source_account: nil)
247
+ raise ArgumentError unless destination.is_a?(KeyPair)
248
+ asset, amount = get_asset_amount(amount)
249
+
250
+ op = PaymentOp.new(
251
+ asset: asset,
252
+ amount: amount,
253
+ destination: destination.muxed_account
254
+ )
255
+
256
+ make(
257
+ source_account: source_account,
258
+ body: [:payment, op]
259
+ )
251
260
  end
252
261
 
253
- # @param sponsored [#to_keypair] owner of sponsored entry
254
- def revoke_sponsorship(sponsored:, **attributes)
255
- key_fields = attributes.slice(:offer_id, :data_name, :balance_id, :asset, :signer)
256
- raise ArgumentError, "conflicting attributes: #{key_fields.keys.join(", ")}" if key_fields.size > 1
257
- account_id = KeyPair(sponsored).account_id
258
- key, value = key_fields.first
259
- op = if key == :signer
260
- RevokeSponsorshipOp.signer(account_id: account_id, signer_key: SignerKey(value))
261
- else
262
- RevokeSponsorshipOp.ledger_key(LedgerKey.from(account_id: account_id, **key_fields))
263
- end
264
- make(attributes.merge(body: [:revoke_sponsorship, op]))
262
+ # Path Payment Strict Receive operation builder.
263
+ #
264
+ # @param source_account [KeyPair, nil] the source account for the operation
265
+ # @param destination [Stellar::KeyPair] the receiver of the payment
266
+ # @param amount [Array] the destination asset and the amount to pay
267
+ # @param with [Array] the source asset and maximum allowed source amount to pay with
268
+ # @param path [Array<Stellar::Asset>] the payment path to use
269
+ #
270
+ # @return [Stellar::Operation] the built operation
271
+ def path_payment_strict_receive(destination:, amount:, with:, path: [], source_account: nil)
272
+ raise ArgumentError unless destination.is_a?(KeyPair)
273
+
274
+ dest_asset, dest_amount = get_asset_amount(amount)
275
+ send_asset, send_max = get_asset_amount(with)
276
+
277
+ op = PathPaymentStrictReceiveOp.new(
278
+ destination: destination.muxed_account,
279
+ dest_asset: dest_asset,
280
+ dest_amount: dest_amount,
281
+ send_asset: send_asset,
282
+ send_max: send_max,
283
+ path: path.map { |p| Asset(p) }
284
+ )
285
+
286
+ make(source_account: source_account, body: [:path_payment_strict_receive, op])
265
287
  end
288
+ alias_method :path_payment, :path_payment_strict_receive
266
289
 
267
- def manage_sell_offer(attributes = {})
268
- buying = attributes[:buying]
269
- if buying.is_a?(Array)
270
- buying = Asset.send(*buying)
271
- end
272
- selling = attributes[:selling]
273
- if selling.is_a?(Array)
274
- selling = Asset.send(*selling)
275
- end
276
- amount = interpret_amount(attributes[:amount])
277
- offer_id = attributes[:offer_id] || 0
278
- price = interpret_price(attributes[:price])
290
+ # Path Payment Strict Receive operation builder.
291
+ #
292
+ # @param source_account [KeyPair, nil] the source account for the operation
293
+ # @param destination [Stellar::KeyPair] the receiver of the payment
294
+ # @param amount [Array] the destination asset and the minimum amount of destination asset to be received
295
+ # @param with [Array] the source asset and amount to pay with
296
+ # @param path [Array<Stellar::Asset>] the payment path to use
297
+ #
298
+ # @return [Stellar::Operation] the built operation
299
+ def path_payment_strict_send(destination:, amount:, with:, path: [], source_account: nil)
300
+ raise ArgumentError unless destination.is_a?(KeyPair)
279
301
 
280
- op = ManageSellOfferOp.new({
281
- buying: buying,
282
- selling: selling,
283
- amount: amount,
284
- price: price,
285
- offer_id: offer_id
286
- })
302
+ dest_asset, dest_min = get_asset_amount(amount)
303
+ send_asset, send_amount = get_asset_amount(with)
287
304
 
288
- make(attributes.merge({
289
- body: [:manage_sell_offer, op]
290
- }))
305
+ op = PathPaymentStrictSendOp.new(
306
+ destination: destination.muxed_account,
307
+ send_asset: send_asset,
308
+ send_amount: send_amount,
309
+ dest_asset: dest_asset,
310
+ dest_min: dest_min,
311
+ path: path.map { |p| Asset(p) }
312
+ )
313
+
314
+ make(source_account: source_account, body: [:path_payment_strict_send, op])
291
315
  end
292
316
 
293
- def manage_buy_offer(attributes = {})
294
- buying = attributes[:buying]
295
- if buying.is_a?(Array)
296
- buying = Asset.send(*buying)
297
- end
298
- selling = attributes[:selling]
299
- if selling.is_a?(Array)
300
- selling = Asset.send(*selling)
301
- end
302
- amount = interpret_amount(attributes[:amount])
303
- offer_id = attributes[:offer_id] || 0
304
- price = interpret_price(attributes[:price])
317
+ # Manage Sell Offer operation builder
318
+ #
319
+ # @param source_account [KeyPair, nil] the source account for the operation
320
+ # @param selling [Asset] the asset to sell
321
+ # @param buying [Asset] the asset to buy
322
+ # @param amount [String, Numeric] the amount of asset to sell
323
+ # @param price [String, Numeric, Price] the price of the selling asset in terms of buying asset
324
+ # @param offer_id [Integer] the offer ID to modify (0 to create a new offer)
325
+ #
326
+ # @return [Operation] the built operation
327
+ def manage_sell_offer(selling:, buying:, amount:, price:, offer_id: 0, source_account: nil)
328
+ selling = Asset.send(*selling) if selling.is_a?(Array)
329
+ buying = Asset.send(*buying) if buying.is_a?(Array)
305
330
 
306
- op = ManageBuyOfferOp.new({
331
+ op = ManageSellOfferOp.new(
307
332
  buying: buying,
308
333
  selling: selling,
309
- buy_amount: amount,
310
- price: price,
334
+ amount: interpret_amount(amount),
335
+ price: Price.from(price),
311
336
  offer_id: offer_id
312
- })
337
+ )
313
338
 
314
- make(attributes.merge({
315
- body: [:manage_buy_offer, op]
316
- }))
339
+ make(source_account: source_account, body: [:manage_sell_offer, op])
317
340
  end
318
341
 
319
- def create_passive_sell_offer(attributes = {})
320
- buying = attributes[:buying]
321
- if buying.is_a?(Array)
322
- buying = Asset.send(*buying)
323
- end
324
- selling = attributes[:selling]
325
- if selling.is_a?(Array)
326
- selling = Asset.send(*selling)
327
- end
328
- amount = interpret_amount(attributes[:amount])
329
- price = interpret_price(attributes[:price])
342
+ # Manage Buy Offer operation builder
343
+ #
344
+ # @param source_account [KeyPair, nil] the source account for the operation
345
+ # @param buying [Asset] the asset to buy
346
+ # @param selling [Asset] the asset to sell
347
+ # @param amount [String, Numeric] the amount of asset to buy
348
+ # @param price [String, Numeric, Price] the price of the buying asset in terms of the selling asset
349
+ # @param offer_id [Integer] the offer ID to modify (0 to create a new offer)
350
+ #
351
+ # @return [Operation] the built operation
352
+ def manage_buy_offer(buying:, selling:, amount:, price:, offer_id: 0, source_account: nil)
353
+ buying = Asset.send(*buying) if buying.is_a?(Array)
354
+ selling = Asset.send(*selling) if selling.is_a?(Array)
330
355
 
331
- op = CreatePassiveSellOfferOp.new({
356
+ op = ManageBuyOfferOp.new(
332
357
  buying: buying,
333
358
  selling: selling,
334
- amount: amount,
335
- price: price
336
- })
359
+ buy_amount: interpret_amount(amount),
360
+ price: Price.from(price),
361
+ offer_id: offer_id
362
+ )
337
363
 
338
- make(attributes.merge({
339
- body: [:create_passive_sell_offer, op]
340
- }))
364
+ make(source_account: source_account, body: [:manage_buy_offer, op])
341
365
  end
342
366
 
367
+ # Create Passive Sell Offer operation builder
343
368
  #
344
- # Helper method to create a valid SetOptionsOp, wrapped
345
- # in the necessary XDR structs to be included within a
346
- # transactions `operations` array.
347
- #
348
- # @param [Hash] attributes the attributes to create the operation with
349
- # @option attributes [Stellar::KeyPair] :inflation_dest
350
- # @option attributes [Array<Stellar::AccountFlags>] :set flags to set
351
- # @option attributes [Array<Stellar::AccountFlags>] :clear flags to clear
352
- # @option attributes [String] :thresholds
353
- # @option attributes [Stellar::Signer] :signer
354
- #
355
- # @return [Stellar::Operation] the built operation, containing a
356
- # Stellar::SetOptionsOp body
357
- def set_options(attributes = {})
358
- op = SetOptionsOp.new
359
- op.set_flags = Stellar::AccountFlags.make_mask attributes[:set]
360
- op.clear_flags = Stellar::AccountFlags.make_mask attributes[:clear]
361
- op.master_weight = attributes[:master_weight]
362
- op.low_threshold = attributes[:low_threshold]
363
- op.med_threshold = attributes[:med_threshold]
364
- op.high_threshold = attributes[:high_threshold]
365
-
366
- op.signer = attributes[:signer]
367
- op.home_domain = attributes[:home_domain]
368
-
369
- inflation_dest = attributes[:inflation_dest]
370
- if inflation_dest
371
- raise ArgumentError, "Bad :inflation_dest" unless inflation_dest.is_a?(Stellar::KeyPair)
372
- op.inflation_dest = inflation_dest.account_id
373
- end
374
-
375
- make(attributes.merge({
376
- body: [:set_options, op]
377
- }))
378
- end
379
-
380
- # @param asset [Stellar::Asset]
381
- # @param trustor [Stellar::KeyPair]
382
- # @param flags [{String, Symbol, Stellar::TrustLineFlags => true, false}] flags to to set or clear
383
- # @param source_account [Stellar::KeyPair] source account (default is `nil`, which will use the source account of transaction)
384
- def set_trust_line_flags(asset:, trustor:, flags: {}, source_account: nil)
385
- op = Stellar::SetTrustLineFlagsOp.new
386
- op.trustor = KeyPair(trustor).account_id
387
- op.asset = Asset(asset)
388
- op.attributes = Stellar::TrustLineFlags.set_clear_masks(flags)
369
+ # @param source_account [KeyPair, nil] the source account for the operation
370
+ # @param selling [Asset] the asset to sell
371
+ # @param buying [Asset] the asset to buy
372
+ # @param amount [String, Numeric] the amount of asset to sell
373
+ # @param price [String, Numeric, Price] the price of the selling asset in terms of buying asset
374
+ #
375
+ # @return [Operation] the built operation
376
+ def create_passive_sell_offer(selling:, buying:, amount:, price:, source_account: nil)
377
+ selling = Asset.send(*selling) if selling.is_a?(Array)
378
+ buying = Asset.send(*buying) if buying.is_a?(Array)
389
379
 
390
- make(
391
- source_account: source_account,
392
- body: [:set_trust_line_flags, op]
380
+ op = CreatePassiveSellOfferOp.new(
381
+ buying: buying,
382
+ selling: selling,
383
+ amount: interpret_amount(amount),
384
+ price: Price.from(price)
393
385
  )
394
- end
395
-
396
- # DEPRECATED in favor of `set_trustline_flags`
397
- #
398
- # Helper method to create a valid AllowTrustOp, wrapped
399
- # in the necessary XDR structs to be included within a
400
- # transactions `operations` array.
401
- #
402
- # @deprecated Use `set_trustline_flags` operation
403
- # See {https://github.com/stellar/stellar-protocol/blob/master/core/cap-0035.md#allow-trust-operation-1 CAP-35 description}
404
- # for more details
405
- # @param [Hash] attributes the attributes to create the operation with
406
- # @option attributes [Stellar::KeyPair] :trustor
407
- # @option attributes [Stellar::Asset] :asset
408
- # @option attributes [Symbol, Boolean] :authorize :full, maintain_liabilities or :none
409
- #
410
- # @return [Stellar::Operation] the built operation, containing a
411
- # Stellar::AllowTrustOp body
412
- def allow_trust(attributes = {})
413
- op = AllowTrustOp.new
414
-
415
- trustor = attributes[:trustor]
416
- # we handle booleans here for the backward compatibility
417
- authorize = attributes[:authorize].yield_self { |value| value == true ? :full : value }
418
- asset = attributes[:asset]
419
- if asset.is_a?(Array)
420
- asset = Asset.send(*asset)
421
- end
422
-
423
- raise ArgumentError, "Bad :trustor" unless trustor.is_a?(Stellar::KeyPair)
424
-
425
- allowed_flags = TRUST_LINE_FLAGS_MAPPING.slice(:full, :maintain_liabilities)
426
-
427
- # we handle booleans here for the backward compatibility
428
- op.authorize = if allowed_flags.key?(authorize)
429
- allowed_flags[authorize].value
430
- elsif [:none, false].include?(authorize)
431
- 0
432
- else
433
- raise ArgumentError, "Bad :authorize, supported values: :full, :maintain_liabilities, :none"
434
- end
435
386
 
436
- raise ArgumentError, "Bad :asset" unless asset.type == Stellar::AssetType.asset_type_credit_alphanum4
437
-
438
- op.trustor = trustor.account_id
439
- op.asset = AssetCode.new(:asset_type_credit_alphanum4, asset.code)
440
-
441
- make(attributes.merge({
442
- body: [:allow_trust, op]
443
- }))
387
+ make(source_account: source_account, body: [:create_passive_sell_offer, op])
444
388
  end
445
389
 
390
+ # Liquidity Pool Deposit operation builder
446
391
  #
447
- # Helper method to create an account merge operation
448
- #
449
- # @param [Hash] attributes the attributes to create the operation with
450
- # @option attributes [Stellar::KeyPair] :destination
392
+ # @param [Stellar::KeyPair] source_account the source account for the operation
393
+ # @param [String] liquidity_pool_id the liquidity pool id as hexadecimal string
394
+ # @param [String, Numeric] max_amount_a the maximum amount of asset A to deposit
395
+ # @param [String, Numeric] max_amount_b the maximum amount of asset B to deposit
396
+ # @param [String, Numeric, Stellar::Price] min_price the minimum valid price of asset A in terms of asset B
397
+ # @param [String, Numeric, Stellar::Price] max_price the maximum valid price of asset A in terms of asset B
451
398
  #
452
399
  # @return [Stellar::Operation] the built operation
453
- def account_merge(attributes = {})
454
- destination = attributes[:destination]
455
-
456
- raise ArgumentError, "Bad :destination" unless destination.is_a?(KeyPair)
400
+ def liquidity_pool_deposit(liquidity_pool_id:, max_amount_a:, max_amount_b:, min_price:, max_price:, source_account: nil)
401
+ op = LiquidityPoolDepositOp.new(
402
+ liquidity_pool_id: PoolID.from_xdr(liquidity_pool_id, :hex),
403
+ max_amount_a: interpret_amount(max_amount_a),
404
+ max_amount_b: interpret_amount(max_amount_b),
405
+ min_price: Price.from(min_price),
406
+ max_price: Price.from(max_price)
407
+ )
457
408
 
458
- # TODO: add source_account support
459
- make(attributes.merge({
460
- body: [:account_merge, destination.muxed_account]
461
- }))
409
+ make(source_account: source_account, body: [:liquidity_pool_deposit, op])
410
+ rescue XDR::ReadError
411
+ raise ArgumentError, "invalid liquidity pool ID '#{balance_id}'"
462
412
  end
463
413
 
414
+ # Liquidity Pool Withdraw operation builder
464
415
  #
465
- # Helper method to create an inflation operation
466
- #
467
- # @param [Hash] attributes the attributes to create the operation with
468
- # @option attributes [Integer] :sequence
416
+ # @param [Stellar::KeyPair] source_account the source account for the operation
417
+ # @param [String] liquidity_pool_id the liquidity pool id as hexadecimal string
418
+ # @param [String, Numeric] amount the number of pool shares to withdraw
419
+ # @param [String, Numeric] min_amount_a the minimum amount of asset A to withdraw
420
+ # @param [String, Numeric] min_amount_b the minimum amount of asset B to withdraw
469
421
  #
470
422
  # @return [Stellar::Operation] the built operation
471
- def inflation(attributes = {})
472
- sequence = attributes[:sequence]
473
-
474
- raise ArgumentError, "Bad :sequence #{sequence}" unless sequence.is_a?(Integer)
423
+ def liquidity_pool_withdraw(liquidity_pool_id:, amount:, min_amount_a:, min_amount_b:, source_account: nil)
424
+ op = LiquidityPoolWithdrawOp.new(
425
+ liquidity_pool_id: PoolID.from_xdr(liquidity_pool_id, :hex),
426
+ amount: interpret_amount(amount),
427
+ min_amount_a: interpret_amount(min_amount_a),
428
+ min_amount_b: interpret_amount(min_amount_b)
429
+ )
475
430
 
476
- # TODO: add source_account support
477
- make(attributes.merge({
478
- body: [:inflation]
479
- }))
431
+ make(source_account: source_account, body: [:liquidity_pool_withdraw, op])
432
+ rescue XDR::ReadError
433
+ raise ArgumentError, "invalid liquidity pool ID '#{balance_id}'"
480
434
  end
481
435
 
436
+ # Begin Sponsoring Future Reserves operation builder
482
437
  #
483
- # Helper method to create an manage data operation
484
- #
485
- # @param [Hash] attributes the attributes to create the operation with
486
- # @option attributes [Integer] :sequence
438
+ # @param source_account [KeyPair, nil] the source account for the operation
487
439
  #
488
- # @return [Stellar::Operation] the built operation
489
- def manage_data(attributes = {})
490
- op = ManageDataOp.new
491
-
492
- name = attributes[:name]
493
- value = attributes[:value]
494
-
495
- raise ArgumentError, "Invalid :name" unless name.is_a?(String)
496
- raise ArgumentError, ":name too long" unless name.bytesize <= 64
497
-
498
- if value.present?
499
- raise ArgumentError, ":value too long" unless value.bytesize <= 64
500
- end
501
-
502
- op.data_name = name
503
- op.data_value = value
440
+ # @return [Operation] the built operation
441
+ def begin_sponsoring_future_reserves(sponsored:, source_account: nil)
442
+ op = BeginSponsoringFutureReservesOp.new(
443
+ sponsored_id: KeyPair(sponsored).account_id
444
+ )
504
445
 
505
- make(attributes.merge({
506
- body: [:manage_data, op]
507
- }))
446
+ make(source_account: source_account, body: [:begin_sponsoring_future_reserves, op])
508
447
  end
509
448
 
510
- def bump_sequence(attributes = {})
511
- op = BumpSequenceOp.new
512
-
513
- bump_to = attributes[:bump_to]
514
-
515
- raise ArgumentError, ":bump_to too big" unless bump_to <= MAX_INT64
516
-
517
- op.bump_to = bump_to
518
-
519
- make(attributes.merge({
520
- body: [:bump_sequence, op]
521
- }))
449
+ # End Sponsoring Future Reserves operation builder
450
+ #
451
+ # @param source_account [KeyPair, nil] the source account for the operation
452
+ #
453
+ # @return [Operation] the built operation
454
+ def end_sponsoring_future_reserves(source_account: nil)
455
+ make(source_account: source_account, body: [:end_sponsoring_future_reserves])
522
456
  end
523
457
 
524
- def clawback(source_account:, from:, amount:)
525
- asset, amount = get_asset_amount(amount)
526
-
527
- if amount == 0
528
- raise ArgumentError, "Amount can not be zero"
529
- end
530
-
531
- if amount < 0
532
- raise ArgumentError, "Negative amount is not allowed"
458
+ # Revoke Sponsorship operation builder
459
+ #
460
+ # @param source_account [KeyPair, nil] the source account for the operation
461
+ # @param sponsored [#to_keypair] owner of sponsored entry
462
+ #
463
+ # @return [Operation] the built operation
464
+ def revoke_sponsorship(sponsored:, source_account: nil, **attributes)
465
+ key_fields = attributes.slice(:offer_id, :data_name, :balance_id, :liquidity_pool_id, :asset, :signer)
466
+ raise ArgumentError, "conflicting attributes: #{key_fields.keys.join(", ")}" if key_fields.size > 1
467
+ account_id = KeyPair(sponsored).account_id
468
+ key, value = key_fields.first
469
+ op = if key == :signer
470
+ RevokeSponsorshipOp.signer(account_id: account_id, signer_key: SignerKey(value))
471
+ else
472
+ RevokeSponsorshipOp.ledger_key(LedgerKey.from(account_id: account_id, **key_fields))
533
473
  end
534
-
535
- op = ClawbackOp.new(
536
- amount: amount,
537
- from: from.muxed_account,
538
- asset: asset
539
- )
540
-
541
- make({
542
- source_account: source_account,
543
- body: [:clawback, op]
544
- })
474
+ make(source_account: source_account, body: [:revoke_sponsorship, op])
545
475
  end
546
476
 
547
- # Helper method to create clawback claimable balance operation
477
+ # Inflation operation builder
548
478
  #
549
- # @param [Stellar::KeyPair] source_account the attributes to create the operation with
550
- # @param [String] balance_id `ClaimableBalanceID`, serialized in hex
479
+ # @param [Stellar::KeyPair, nil] source_account the source account for the operation
551
480
  #
552
481
  # @return [Stellar::Operation] the built operation
553
- def clawback_claimable_balance(source_account:, balance_id:)
554
- balance_id = Stellar::ClaimableBalanceID.from_xdr(balance_id, :hex)
555
- op = ClawbackClaimableBalanceOp.new(balance_id: balance_id)
556
-
557
- make(
558
- source_account: source_account,
559
- body: [:clawback_claimable_balance, op]
560
- )
561
- rescue XDR::ReadError
562
- raise ArgumentError, "Claimable balance id '#{balance_id}' is invalid"
482
+ def inflation(source_account: nil)
483
+ make(source_account: source_account, body: [:inflation])
563
484
  end
564
485
 
565
486
  private
@@ -576,29 +497,10 @@ module Stellar
576
497
  end
577
498
 
578
499
  def interpret_amount(amount)
579
- case amount
580
- when String
581
- (BigDecimal(amount) * Stellar::ONE).floor
582
- when Integer
583
- amount * Stellar::ONE
584
- when Numeric
500
+ if amount.is_a?(Float)
585
501
  (amount * Stellar::ONE).floor
586
502
  else
587
- raise ArgumentError, "Invalid amount type: #{amount.class}. Must be String or Numeric"
588
- end
589
- end
590
-
591
- def interpret_price(price)
592
- case price
593
- when String
594
- bd = BigDecimal(price)
595
- Price.from_f(bd)
596
- when Numeric
597
- Price.from_f(price)
598
- when Stellar::Price
599
- price
600
- else
601
- raise ArgumentError, "Invalid price type: #{price.class}. Must be String, Numeric, or Stellar::Price"
503
+ (BigDecimal(amount) * Stellar::ONE).floor
602
504
  end
603
505
  end
604
506
  end