stellar-base 0.22.0 → 0.23.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE.txt → LICENSE} +0 -0
  3. data/README.md +2 -3
  4. data/generated/stellar-base-generated.rb +10 -1
  5. data/generated/stellar/allow_trust_op.rb +3 -2
  6. data/generated/stellar/authenticated_message.rb +4 -4
  7. data/generated/stellar/authenticated_message/v0.rb +4 -4
  8. data/generated/stellar/change_trust_result_code.rb +1 -1
  9. data/generated/stellar/crypto_key_type.rb +8 -4
  10. data/generated/stellar/curve25519_public.rb +1 -1
  11. data/generated/stellar/curve25519_secret.rb +1 -1
  12. data/generated/stellar/envelope_type.rb +9 -5
  13. data/generated/stellar/fee_bump_transaction.rb +39 -0
  14. data/generated/stellar/fee_bump_transaction/ext.rb +24 -0
  15. data/generated/stellar/fee_bump_transaction/inner_tx.rb +25 -0
  16. data/generated/stellar/fee_bump_transaction_envelope.rb +22 -0
  17. data/generated/stellar/hmac_sha256_key.rb +1 -1
  18. data/generated/stellar/hmac_sha256_mac.rb +1 -1
  19. data/generated/stellar/inner_transaction_result.rb +56 -0
  20. data/generated/stellar/inner_transaction_result/ext.rb +24 -0
  21. data/generated/stellar/inner_transaction_result/result.rb +52 -0
  22. data/generated/stellar/inner_transaction_result_pair.rb +20 -0
  23. data/generated/stellar/ledger_close_meta.rb +1 -1
  24. data/generated/stellar/manage_buy_offer_result_code.rb +5 -4
  25. data/generated/stellar/manage_sell_offer_result_code.rb +12 -8
  26. data/generated/stellar/muxed_account.rb +35 -0
  27. data/generated/stellar/muxed_account/med25519.rb +22 -0
  28. data/generated/stellar/operation.rb +3 -3
  29. data/generated/stellar/operation/body.rb +2 -2
  30. data/generated/stellar/operation_result.rb +1 -1
  31. data/generated/stellar/operation_result/tr.rb +1 -1
  32. data/generated/stellar/operation_result_code.rb +3 -3
  33. data/generated/stellar/path_payment_strict_receive_op.rb +4 -4
  34. data/generated/stellar/path_payment_strict_receive_result_code.rb +21 -12
  35. data/generated/stellar/path_payment_strict_send_op.rb +6 -6
  36. data/generated/stellar/path_payment_strict_send_result_code.rb +20 -12
  37. data/generated/stellar/payment_op.rb +4 -4
  38. data/generated/stellar/survey_response_body.rb +2 -2
  39. data/generated/stellar/transaction.rb +2 -2
  40. data/generated/stellar/transaction_envelope.rb +17 -8
  41. data/generated/stellar/transaction_result.rb +3 -0
  42. data/generated/stellar/transaction_result/result.rb +9 -3
  43. data/generated/stellar/transaction_result_code.rb +21 -14
  44. data/generated/stellar/transaction_signature_payload.rb +3 -1
  45. data/generated/stellar/transaction_signature_payload/tagged_transaction.rb +7 -3
  46. data/generated/stellar/transaction_v0.rb +39 -0
  47. data/generated/stellar/transaction_v0/ext.rb +24 -0
  48. data/generated/stellar/transaction_v0_envelope.rb +22 -0
  49. data/generated/stellar/transaction_v1_envelope.rb +22 -0
  50. data/generated/stellar/trust_line_flags.rb +6 -2
  51. data/lib/stellar-base.rb +27 -25
  52. data/lib/stellar/account_flags.rb +2 -4
  53. data/lib/stellar/asset.rb +6 -6
  54. data/lib/stellar/base.rb +1 -1
  55. data/lib/stellar/{base/compat.rb → compat.rb} +6 -7
  56. data/lib/stellar/concerns/transaction.rb +49 -0
  57. data/lib/stellar/convert.rb +2 -2
  58. data/lib/stellar/factories.rb +1 -3
  59. data/lib/stellar/fee_bump_transaction.rb +21 -0
  60. data/lib/stellar/key_pair.rb +9 -6
  61. data/lib/stellar/networks.rb +5 -7
  62. data/lib/stellar/operation.rb +421 -416
  63. data/lib/stellar/path_payment_strict_receive_result.rb +1 -2
  64. data/lib/stellar/price.rb +2 -4
  65. data/lib/stellar/signer_key.rb +4 -8
  66. data/lib/stellar/thresholds.rb +5 -7
  67. data/lib/stellar/transaction.rb +154 -198
  68. data/lib/stellar/transaction_builder.rb +66 -23
  69. data/lib/stellar/transaction_envelope.rb +40 -8
  70. data/lib/stellar/transaction_v0.rb +39 -0
  71. data/lib/stellar/util/continued_fraction.rb +19 -19
  72. data/lib/stellar/util/strkey.rb +39 -14
  73. data/lib/stellar/{base/version.rb → version.rb} +1 -1
  74. metadata +33 -203
  75. data/.gitignore +0 -17
  76. data/.travis.yml +0 -16
  77. data/.yardopts +0 -8
  78. data/CHANGELOG.md +0 -149
  79. data/CONTRIBUTING.md +0 -48
  80. data/Gemfile +0 -9
  81. data/Guardfile +0 -5
  82. data/Rakefile +0 -4
  83. data/examples/allow_trust.rb +0 -51
  84. data/examples/create_account.rb +0 -26
  85. data/examples/low_level_transaction_post.rb +0 -46
  86. data/examples/mid_level_transaction_post.rb +0 -33
  87. data/examples/non_native_payment.rb +0 -60
  88. data/examples/offer.rb +0 -75
  89. data/examples/transaction_merge.rb +0 -23
  90. data/ruby-stellar-base.gemspec +0 -34
  91. data/spec/lib/stellar/account_flags_spec.rb +0 -19
  92. data/spec/lib/stellar/asset_spec.rb +0 -45
  93. data/spec/lib/stellar/convert_spec.rb +0 -61
  94. data/spec/lib/stellar/key_pair_spec.rb +0 -251
  95. data/spec/lib/stellar/networks_spec.rb +0 -77
  96. data/spec/lib/stellar/operation_spec.rb +0 -131
  97. data/spec/lib/stellar/path_payment_strict_receive_result_spec.rb +0 -95
  98. data/spec/lib/stellar/price_spec.rb +0 -34
  99. data/spec/lib/stellar/signer_key_spec.rb +0 -26
  100. data/spec/lib/stellar/thresholds_spec.rb +0 -62
  101. data/spec/lib/stellar/transaction_builder_spec.rb +0 -263
  102. data/spec/lib/stellar/transaction_envelope_spec.rb +0 -93
  103. data/spec/lib/stellar/transaction_spec.rb +0 -132
  104. data/spec/lib/stellar/util/strkey_spec.rb +0 -54
  105. data/spec/spec_helper.rb +0 -16
  106. data/spec/support/matchers/be_strkey.rb +0 -9
  107. data/spec/support/matchers/eq_bytes.rb +0 -5
  108. data/spec/support/matchers/have_length.rb +0 -5
  109. data/tasks/rspec.rake +0 -6
  110. data/tasks/travis.rake +0 -1
  111. data/tasks/xdr.rake +0 -45
  112. data/xdr/Stellar-SCP.x +0 -86
  113. data/xdr/Stellar-ledger-entries.x +0 -295
  114. data/xdr/Stellar-ledger.x +0 -372
  115. data/xdr/Stellar-overlay.x +0 -229
  116. data/xdr/Stellar-transaction.x +0 -901
  117. data/xdr/Stellar-types.x +0 -81
@@ -3,10 +3,10 @@ module Stellar
3
3
  # Generic format conversion module
4
4
  #
5
5
  module Convert
6
- require 'base64'
6
+ require "base64"
7
7
 
8
8
  def to_hex(string)
9
- string.unpack("H*").first
9
+ string.unpack1("H*")
10
10
  end
11
11
 
12
12
  def from_hex(hex_string)
@@ -1,5 +1,4 @@
1
1
  FactoryBot.define do
2
-
3
2
  factory :stellar_ledger, class: Hyperclient::Resource do
4
3
  initialize_with { new(attributes.stringify_keys, nil, nil) }
5
4
 
@@ -39,7 +38,7 @@ FactoryBot.define do
39
38
  fee_meta_xdr { "AAAAAgAAAAMAAAABAAAAAAAAAAABlHJijueOuScU0i0DkJY8JNkn6gCZmUhuiR+sLaqcIQ3gtrOnZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAABlHJijueOuScU0i0DkJY8JNkn6gCZmUhuiR+sLaqcIQ3gtrOnY/7UAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAA==" }
40
39
  memo_type { "text" }
41
40
  signatures do
42
- [ "SsKlst02jsaBp35vXlI300Qbz39+HbwwNDX/gfM+MwaG/dFF7bgqpkKsDAsh/qJDiN3NOW695IZB9Mj+JAsHBA==" ]
41
+ ["SsKlst02jsaBp35vXlI300Qbz39+HbwwNDX/gfM+MwaG/dFF7bgqpkKsDAsh/qJDiN3NOW695IZB9Mj+JAsHBA=="]
43
42
  end
44
43
  end
45
44
 
@@ -57,5 +56,4 @@ FactoryBot.define do
57
56
  funder { "GAAZI4TCR3TY5OJHCTJC2A4QSY6CJWJH5IAJTGKIN2ER7LBNVKOCCWN7" }
58
57
  account { "GALPCCZN4YXA3YMJHKL6CVIECKPLJJCTVMSNYWBTKJW4K5HQLYLDMZTB" }
59
58
  end
60
-
61
59
  end
@@ -0,0 +1,21 @@
1
+ module Stellar
2
+ class FeeBumpTransaction
3
+ include Stellar::Concerns::Transaction
4
+
5
+ def to_envelope(*key_pairs)
6
+ signatures = (key_pairs || []).map(&method(:sign_decorated))
7
+
8
+ TransactionEnvelope.fee_bump(signatures: signatures, tx: self)
9
+ end
10
+
11
+ def signature_base_prefix
12
+ val = Stellar::EnvelopeType.envelope_type_tx_v0
13
+
14
+ Stellar.current_network_id + Stellar::EnvelopeType.to_xdr(val)
15
+ end
16
+
17
+ def source_account
18
+ source_account_ed25519
19
+ end
20
+ end
21
+ end
@@ -36,7 +36,7 @@ module Stellar
36
36
  from_raw_seed(Stellar.current_network_id)
37
37
  end
38
38
 
39
- def initialize(public_key, secret_key=nil)
39
+ def initialize(public_key, secret_key = nil)
40
40
  @public_key = public_key
41
41
  @secret_key = secret_key
42
42
  end
@@ -45,6 +45,10 @@ module Stellar
45
45
  Stellar::AccountID.new :public_key_type_ed25519, raw_public_key
46
46
  end
47
47
 
48
+ def muxed_account
49
+ Stellar::MuxedAccount.new :key_type_ed25519, raw_public_key
50
+ end
51
+
48
52
  def public_key
49
53
  Stellar::PublicKey.new :public_key_type_ed25519, raw_public_key
50
54
  end
@@ -81,9 +85,9 @@ module Stellar
81
85
 
82
86
  def seed
83
87
  raise "no private key" if @secret_key.nil?
84
- #TODO: improve the error class above
88
+ # TODO: improve the error class above
85
89
  seed_bytes = raw_seed
86
- encoder = Util::StrKey.check_encode(:seed, seed_bytes)
90
+ Util::StrKey.check_encode(:seed, seed_bytes)
87
91
  end
88
92
 
89
93
  def sign?
@@ -92,14 +96,14 @@ module Stellar
92
96
 
93
97
  def sign(message)
94
98
  raise "no private key" if @secret_key.nil?
95
- #TODO: improve the error class above
99
+ # TODO: improve the error class above
96
100
  @secret_key.sign(message)
97
101
  end
98
102
 
99
103
  def sign_decorated(message)
100
104
  raw_signature = sign(message)
101
105
  Stellar::DecoratedSignature.new({
102
- hint: signature_hint,
106
+ hint: signature_hint,
103
107
  signature: raw_signature
104
108
  })
105
109
  end
@@ -111,6 +115,5 @@ module Stellar
111
115
  rescue RbNaCl::BadSignatureError
112
116
  false
113
117
  end
114
-
115
118
  end
116
119
  end
@@ -1,10 +1,8 @@
1
1
  module Stellar
2
2
  # Provides a container for well-known network passphrases, such as the main network and SDF test network
3
3
  module Networks
4
-
5
- PUBLIC = "Public Global Stellar Network ; September 2015"
4
+ PUBLIC = "Public Global Stellar Network ; September 2015"
6
5
  TESTNET = "Test SDF Network ; September 2015"
7
-
8
6
  end
9
7
 
10
8
  # Configures the default stellar network passphrase for the current process. Unless otherwise
@@ -23,15 +21,15 @@ module Stellar
23
21
  # Returns the passphrase for the currently-configured network, as set by Stellar.default_network
24
22
  # or Stellar.on_network
25
23
  def self.current_network
26
- Thread.current["stellar_network_passphrase"] ||
27
- @default_network ||
28
- Stellar::Networks::TESTNET
24
+ Thread.current["stellar_network_passphrase"] ||
25
+ @default_network ||
26
+ Stellar::Networks::TESTNET
29
27
  end
30
28
 
31
29
  # Returns the id for the currently configured network, suitable for use in generating
32
30
  # a signature base string or making the root account's keypair.
33
31
  def self.current_network_id
34
- Digest::SHA256.digest(self.current_network)
32
+ Digest::SHA256.digest(current_network)
35
33
  end
36
34
 
37
35
  # Executes the provided block in the context of the provided network.
@@ -1,473 +1,478 @@
1
- require 'bigdecimal'
1
+ require "bigdecimal"
2
2
 
3
3
  module Stellar
4
4
  class Operation
5
-
6
5
  MAX_INT64 = 2**63 - 1
7
6
 
8
- #
9
- # Construct a new Stellar::Operation from the provided
10
- # source account and body
11
- #
12
- # @param [Hash] attributes the attributes to create the operation with
13
- # @option attributes [Stellar::KeyPair] :source_account
14
- # @option attributes [Stellar::Operation::Body] :body
15
- #
16
- # @return [Stellar::Operation] the built operation
17
- def self.make(attributes={})
18
- source_account = attributes[:source_account]
19
- body = Stellar::Operation::Body.new(*attributes[:body])
20
-
21
- op = Stellar::Operation.new(body:body)
22
-
23
- if source_account
24
- raise ArgumentError, "Bad :source_account" unless source_account.is_a?(Stellar::KeyPair)
25
- op.source_account = source_account.account_id
26
- end
27
-
28
- return op
29
- end
30
-
7
+ class << self
8
+ #
9
+ # Construct a new Stellar::Operation from the provided
10
+ # source account and body
11
+ #
12
+ # @param [Hash] attributes the attributes to create the operation with
13
+ # @option attributes [Stellar::KeyPair] :source_account
14
+ # @option attributes [Stellar::Operation::Body] :body
15
+ #
16
+ # @return [Stellar::Operation] the built operation
17
+ def make(attributes = {})
18
+ source_account = attributes[:source_account]
19
+ body = Stellar::Operation::Body.new(*attributes[:body])
20
+
21
+ op = Stellar::Operation.new(body: body)
22
+
23
+ if source_account
24
+ raise ArgumentError, "Bad :source_account" unless source_account.is_a?(Stellar::KeyPair)
25
+ op.source_account = source_account.muxed_account
26
+ end
31
27
 
32
- #
33
- # Helper method to create a valid PaymentOp, wrapped
34
- # in the necessary XDR structs to be included within a
35
- # transactions `operations` array.
36
- #
37
- # @see Stellar::Asset
38
- #
39
- # @param [Hash] attributes the attributes to create the operation with
40
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
41
- # @option attributes [Array] :amount the amount to pay
42
- # @return [Stellar::Operation] the built operation, containing a
43
- # Stellar::PaymentOp body
44
- def self.payment(attributes={})
45
- destination = attributes[:destination]
46
- asset, amount = get_asset_amount(attributes[:amount])
47
-
48
- raise ArgumentError unless destination.is_a?(KeyPair)
49
-
50
-
51
- op = PaymentOp.new
52
- op.asset = asset
53
- op.amount = amount
54
- op.destination = destination.account_id
55
-
56
- return make(attributes.merge({
57
- body:[:payment, op]
58
- }))
59
- end
28
+ op
29
+ end
60
30
 
61
- #
62
- # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
63
- # in the necessary XDR structs to be included within a
64
- # transactions `operations` array.
65
- #
66
- # @deprecated Please use Operation.path_payment_strict_receive
67
- #
68
- # @see Stellar::Asset
69
- #
70
- # @param [Hash] attributes the attributes to create the operation with
71
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
72
- # @option attributes [Array] :amount the destination asset and the amount to pay
73
- # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
74
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
75
- #
76
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
77
- #
78
- def self.path_payment(attributes={})
79
- path_payment_strict_receive(attributes)
80
- end
31
+ #
32
+ # Helper method to create a valid PaymentOp, wrapped
33
+ # in the necessary XDR structs to be included within a
34
+ # transactions `operations` array.
35
+ #
36
+ # @see Stellar::Asset
37
+ #
38
+ # @param [Hash] attributes the attributes to create the operation with
39
+ # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
40
+ # @option attributes [Array] :amount the amount to pay
41
+ # @return [Stellar::Operation] the built operation, containing a
42
+ # Stellar::PaymentOp body
43
+ def payment(attributes = {})
44
+ destination = attributes[:destination]
45
+ asset, amount = get_asset_amount(attributes[:amount])
46
+
47
+ raise ArgumentError unless destination.is_a?(KeyPair)
48
+
49
+ op = PaymentOp.new
50
+ op.asset = asset
51
+ op.amount = amount
52
+ op.destination = destination.muxed_account
53
+
54
+ make(attributes.merge({
55
+ body: [:payment, op]
56
+ }))
57
+ end
81
58
 
82
- #
83
- # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
84
- # in the necessary XDR structs to be included within a
85
- # transactions `operations` array.
86
- #
87
- # @see Stellar::Asset
88
- #
89
- # @param [Hash] attributes the attributes to create the operation with
90
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
91
- # @option attributes [Array] :amount the destination asset and the amount to pay
92
- # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
93
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
94
- #
95
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
96
- #
97
- def self.path_payment_strict_receive(attributes={})
98
- destination = attributes[:destination]
99
- asset, amount = get_asset_amount(attributes[:amount])
100
- send_asset, send_max = get_asset_amount(attributes[:with])
101
- path = (attributes[:path] || []).map{
102
- |p| p.is_a?(Array) ? Stellar::Asset.send(*p) : p
103
- }
104
-
105
- raise ArgumentError unless destination.is_a?(KeyPair)
106
-
107
- op = PathPaymentStrictReceiveOp.new
108
- op.send_asset = send_asset
109
- op.send_max = send_max
110
- op.destination = destination.account_id
111
- op.dest_asset = asset
112
- op.dest_amount = amount
113
- op.path = path
114
-
115
- return make(attributes.merge({
116
- body:[:path_payment_strict_receive, op]
117
- }))
118
- end
59
+ #
60
+ # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
61
+ # in the necessary XDR structs to be included within a
62
+ # transactions `operations` array.
63
+ #
64
+ # @deprecated Please use Operation.path_payment_strict_receive
65
+ #
66
+ # @see Stellar::Asset
67
+ #
68
+ # @param [Hash] attributes the attributes to create the operation with
69
+ # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
70
+ # @option attributes [Array] :amount the destination asset and the amount to pay
71
+ # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
72
+ # @option attributes [Array<Stellar::Asset>] :path the payment path to use
73
+ #
74
+ # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
75
+ #
76
+ def path_payment(attributes = {})
77
+ path_payment_strict_receive(attributes)
78
+ end
119
79
 
120
- #
121
- # Helper method to create a valid PathPaymentStrictSendOp, wrapped
122
- # in the necessary XDR structs to be included within a
123
- # transactions `operations` array.
124
- #
125
- # @see Stellar::Asset
126
- #
127
- # @param [Hash] attributes the attributes to create the operation with
128
- # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
129
- # @option attributes [Array] :amount the destination asset and the minimum amount of destination asset to be received
130
- # @option attributes [Array] :with the source asset and amount to pay with
131
- # @option attributes [Array<Stellar::Asset>] :path the payment path to use
132
- #
133
- # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
134
- #
135
- def self.path_payment_strict_send(attributes={})
136
- destination = attributes[:destination]
137
- asset, dest_min = get_asset_amount(attributes[:amount])
138
- send_asset, send_amount = get_asset_amount(attributes[:with])
139
- path = (attributes[:path] || []).map{
140
- |p| p.is_a?(Array) ? Stellar::Asset.send(*p) : p
141
- }
142
-
143
- raise ArgumentError unless destination.is_a?(KeyPair)
144
-
145
- op = PathPaymentStrictSendOp.new
146
- op.send_asset = send_asset
147
- op.send_amount = send_amount
148
- op.destination = destination.account_id
149
- op.dest_asset = asset
150
- op.dest_min = dest_min
151
- op.path = path
152
-
153
- return make(attributes.merge({
154
- body:[:path_payment_strict_send, op]
155
- }))
156
- end
80
+ #
81
+ # Helper method to create a valid PathPaymentStrictReceiveOp, wrapped
82
+ # in the necessary XDR structs to be included within a
83
+ # transactions `operations` array.
84
+ #
85
+ # @see Stellar::Asset
86
+ #
87
+ # @param [Hash] attributes the attributes to create the operation with
88
+ # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
89
+ # @option attributes [Array] :amount the destination asset and the amount to pay
90
+ # @option attributes [Array] :with the source asset and maximum allowed source amount to pay with
91
+ # @option attributes [Array<Stellar::Asset>] :path the payment path to use
92
+ #
93
+ # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
94
+ #
95
+ def path_payment_strict_receive(attributes = {})
96
+ destination = attributes[:destination]
97
+ asset, amount = get_asset_amount(attributes[:amount])
98
+ send_asset, send_max = get_asset_amount(attributes[:with])
99
+ path = (attributes[:path] || []).map { |p|
100
+ p.is_a?(Array) ? Stellar::Asset.send(*p) : p
101
+ }
102
+
103
+ raise ArgumentError unless destination.is_a?(KeyPair)
104
+
105
+ op = PathPaymentStrictReceiveOp.new
106
+ op.send_asset = send_asset
107
+ op.send_max = send_max
108
+ op.destination = destination.muxed_account
109
+ op.dest_asset = asset
110
+ op.dest_amount = amount
111
+ op.path = path
112
+
113
+ make(attributes.merge({
114
+ body: [:path_payment_strict_receive, op]
115
+ }))
116
+ end
157
117
 
158
- def self.create_account(attributes={})
159
- destination = attributes[:destination]
160
- starting_balance = interpret_amount(attributes[:starting_balance])
118
+ #
119
+ # Helper method to create a valid PathPaymentStrictSendOp, wrapped
120
+ # in the necessary XDR structs to be included within a
121
+ # transactions `operations` array.
122
+ #
123
+ # @see Stellar::Asset
124
+ #
125
+ # @param [Hash] attributes the attributes to create the operation with
126
+ # @option attributes [Stellar::KeyPair] :destination the receiver of the payment
127
+ # @option attributes [Array] :amount the destination asset and the minimum amount of destination asset to be received
128
+ # @option attributes [Array] :with the source asset and amount to pay with
129
+ # @option attributes [Array<Stellar::Asset>] :path the payment path to use
130
+ #
131
+ # @return [Stellar::Operation] the built operation, containing a Stellar::PaymentOp body
132
+ #
133
+ def path_payment_strict_send(attributes = {})
134
+ destination = attributes[:destination]
135
+ asset, dest_min = get_asset_amount(attributes[:amount])
136
+ send_asset, send_amount = get_asset_amount(attributes[:with])
137
+ path = (attributes[:path] || []).map { |p|
138
+ p.is_a?(Array) ? Stellar::Asset.send(*p) : p
139
+ }
140
+
141
+ raise ArgumentError unless destination.is_a?(KeyPair)
142
+
143
+ op = PathPaymentStrictSendOp.new
144
+ op.send_asset = send_asset
145
+ op.send_amount = send_amount
146
+ op.destination = destination.muxed_account
147
+ op.dest_asset = asset
148
+ op.dest_min = dest_min
149
+ op.path = path
150
+
151
+ make(attributes.merge({
152
+ body: [:path_payment_strict_send, op]
153
+ }))
154
+ end
161
155
 
162
- raise ArgumentError unless destination.is_a?(KeyPair)
156
+ def create_account(attributes = {})
157
+ destination = attributes[:destination]
158
+ starting_balance = interpret_amount(attributes[:starting_balance])
163
159
 
164
- op = CreateAccountOp.new()
165
- op.destination = destination.account_id
166
- op.starting_balance = starting_balance
160
+ raise ArgumentError unless destination.is_a?(KeyPair)
167
161
 
168
- return make(attributes.merge({
169
- body:[:create_account, op]
170
- }))
171
- end
162
+ op = CreateAccountOp.new
163
+ op.destination = destination.account_id
164
+ op.starting_balance = starting_balance
172
165
 
173
- #
174
- # Helper method to create a valid ChangeTrustOp, wrapped
175
- # in the necessary XDR structs to be included within a
176
- # transactions `operations` array.
177
- #
178
- # @param [Hash] attributes the attributes to create the operation with
179
- # @option attributes [Stellar::Asset] :line the asset to trust
180
- # @option attributes [Fixnum] :limit the maximum amount to trust, defaults to max int64,
181
- # if the limit is set to 0 it deletes the trustline.
182
- #
183
- # @return [Stellar::Operation] the built operation, containing a
184
- # Stellar::ChangeTrustOp body
185
- def self.change_trust(attributes={})
186
- line = attributes[:line]
187
- if !line.is_a?(Asset)
188
- if !Asset::TYPES.include?(line[0])
189
- fail ArgumentError, "must be one of #{Asset::TYPES}"
190
- end
191
- line = Asset.send(*line)
166
+ make(attributes.merge({
167
+ body: [:create_account, op]
168
+ }))
192
169
  end
193
170
 
194
- limit = attributes.key?(:limit) ? interpret_amount(attributes[:limit]) : MAX_INT64
171
+ #
172
+ # Helper method to create a valid ChangeTrustOp, wrapped
173
+ # in the necessary XDR structs to be included within a
174
+ # transactions `operations` array.
175
+ #
176
+ # @param [Hash] attributes the attributes to create the operation with
177
+ # @option attributes [Stellar::Asset] :line the asset to trust
178
+ # @option attributes [Fixnum] :limit the maximum amount to trust, defaults to max int64,
179
+ # if the limit is set to 0 it deletes the trustline.
180
+ #
181
+ # @return [Stellar::Operation] the built operation, containing a
182
+ # Stellar::ChangeTrustOp body
183
+ def change_trust(attributes = {})
184
+ line = attributes[:line]
185
+ unless line.is_a?(Asset)
186
+ unless Asset::TYPES.include?(line[0])
187
+ fail ArgumentError, "must be one of #{Asset::TYPES}"
188
+ end
189
+ line = Asset.send(*line)
190
+ end
195
191
 
196
- raise ArgumentError, "Bad :limit #{limit}" unless limit.is_a?(Integer)
192
+ limit = attributes.key?(:limit) ? interpret_amount(attributes[:limit]) : MAX_INT64
197
193
 
198
- op = ChangeTrustOp.new(line: line, limit: limit)
194
+ raise ArgumentError, "Bad :limit #{limit}" unless limit.is_a?(Integer)
199
195
 
200
- return make(attributes.merge({
201
- body:[:change_trust, op]
202
- }))
203
- end
196
+ op = ChangeTrustOp.new(line: line, limit: limit)
204
197
 
205
- def self.manage_sell_offer(attributes={})
206
- buying = attributes[:buying]
207
- if buying.is_a?(Array)
208
- buying = Asset.send(*buying)
209
- end
210
- selling = attributes[:selling]
211
- if selling.is_a?(Array)
212
- selling = Asset.send(*selling)
198
+ make(attributes.merge({
199
+ body: [:change_trust, op]
200
+ }))
213
201
  end
214
- amount = interpret_amount(attributes[:amount])
215
- offer_id = attributes[:offer_id] || 0
216
- price = interpret_price(attributes[:price])
217
-
218
- op = ManageSellOfferOp.new({
219
- buying: buying,
220
- selling: selling,
221
- amount: amount,
222
- price: price,
223
- offer_id: offer_id
224
- })
225
-
226
- return make(attributes.merge({
227
- body:[:manage_sell_offer, op]
228
- }))
229
- end
230
202
 
231
- def self.manage_buy_offer(attributes={})
232
- buying = attributes[:buying]
233
- if buying.is_a?(Array)
234
- buying = Asset.send(*buying)
235
- end
236
- selling = attributes[:selling]
237
- if selling.is_a?(Array)
238
- selling = Asset.send(*selling)
203
+ def manage_sell_offer(attributes = {})
204
+ buying = attributes[:buying]
205
+ if buying.is_a?(Array)
206
+ buying = Asset.send(*buying)
207
+ end
208
+ selling = attributes[:selling]
209
+ if selling.is_a?(Array)
210
+ selling = Asset.send(*selling)
211
+ end
212
+ amount = interpret_amount(attributes[:amount])
213
+ offer_id = attributes[:offer_id] || 0
214
+ price = interpret_price(attributes[:price])
215
+
216
+ op = ManageSellOfferOp.new({
217
+ buying: buying,
218
+ selling: selling,
219
+ amount: amount,
220
+ price: price,
221
+ offer_id: offer_id
222
+ })
223
+
224
+ make(attributes.merge({
225
+ body: [:manage_sell_offer, op]
226
+ }))
239
227
  end
240
- amount = interpret_amount(attributes[:amount])
241
- offer_id = attributes[:offer_id] || 0
242
- price = interpret_price(attributes[:price])
243
-
244
- op = ManageBuyOfferOp.new({
245
- buying: buying,
246
- selling: selling,
247
- amount: amount,
248
- price: price,
249
- offer_id: offer_id
250
- })
251
-
252
- return make(attributes.merge({
253
- body:[:manage_buy_offer, op]
254
- }))
255
- end
256
228
 
257
- def self.create_passive_sell_offer(attributes={})
258
- buying = attributes[:buying]
259
- if buying.is_a?(Array)
260
- buying = Asset.send(*buying)
261
- end
262
- selling = attributes[:selling]
263
- if selling.is_a?(Array)
264
- selling = Asset.send(*selling)
229
+ def manage_buy_offer(attributes = {})
230
+ buying = attributes[:buying]
231
+ if buying.is_a?(Array)
232
+ buying = Asset.send(*buying)
233
+ end
234
+ selling = attributes[:selling]
235
+ if selling.is_a?(Array)
236
+ selling = Asset.send(*selling)
237
+ end
238
+ amount = interpret_amount(attributes[:amount])
239
+ offer_id = attributes[:offer_id] || 0
240
+ price = interpret_price(attributes[:price])
241
+
242
+ op = ManageBuyOfferOp.new({
243
+ buying: buying,
244
+ selling: selling,
245
+ amount: amount,
246
+ price: price,
247
+ offer_id: offer_id
248
+ })
249
+
250
+ make(attributes.merge({
251
+ body: [:manage_buy_offer, op]
252
+ }))
265
253
  end
266
- amount = interpret_amount(attributes[:amount])
267
- price = interpret_price(attributes[:price])
268
-
269
- op = CreatePassiveSellOfferOp.new({
270
- buying: buying,
271
- selling: selling,
272
- amount: amount,
273
- price: price,
274
- })
275
-
276
- return make(attributes.merge({
277
- body:[:create_passive_sell_offer, op]
278
- }))
279
- end
280
254
 
281
- #
282
- # Helper method to create a valid SetOptionsOp, wrapped
283
- # in the necessary XDR structs to be included within a
284
- # transactions `operations` array.
285
- #
286
- # @param [Hash] attributes the attributes to create the operation with
287
- # @option attributes [Stellar::KeyPair] :inflation_dest
288
- # @option attributes [Array<Stellar::AccountFlags>] :set flags to set
289
- # @option attributes [Array<Stellar::AccountFlags>] :clear flags to clear
290
- # @option attributes [String] :thresholds
291
- # @option attributes [Stellar::Signer] :signer
292
- #
293
- # @return [Stellar::Operation] the built operation, containing a
294
- # Stellar::SetOptionsOp body
295
- def self.set_options(attributes={})
296
- op = SetOptionsOp.new()
297
- op.set_flags = Stellar::AccountFlags.make_mask attributes[:set]
298
- op.clear_flags = Stellar::AccountFlags.make_mask attributes[:clear]
299
- op.master_weight = attributes[:master_weight]
300
- op.low_threshold = attributes[:low_threshold]
301
- op.med_threshold = attributes[:med_threshold]
302
- op.high_threshold = attributes[:high_threshold]
303
-
304
- op.signer = attributes[:signer]
305
- op.home_domain = attributes[:home_domain]
306
-
307
-
308
- inflation_dest = attributes[:inflation_dest]
309
- if inflation_dest
310
- raise ArgumentError, "Bad :inflation_dest" unless inflation_dest.is_a?(Stellar::KeyPair)
311
- op.inflation_dest = inflation_dest.account_id
255
+ def create_passive_sell_offer(attributes = {})
256
+ buying = attributes[:buying]
257
+ if buying.is_a?(Array)
258
+ buying = Asset.send(*buying)
259
+ end
260
+ selling = attributes[:selling]
261
+ if selling.is_a?(Array)
262
+ selling = Asset.send(*selling)
263
+ end
264
+ amount = interpret_amount(attributes[:amount])
265
+ price = interpret_price(attributes[:price])
266
+
267
+ op = CreatePassiveSellOfferOp.new({
268
+ buying: buying,
269
+ selling: selling,
270
+ amount: amount,
271
+ price: price
272
+ })
273
+
274
+ make(attributes.merge({
275
+ body: [:create_passive_sell_offer, op]
276
+ }))
312
277
  end
313
278
 
279
+ #
280
+ # Helper method to create a valid SetOptionsOp, wrapped
281
+ # in the necessary XDR structs to be included within a
282
+ # transactions `operations` array.
283
+ #
284
+ # @param [Hash] attributes the attributes to create the operation with
285
+ # @option attributes [Stellar::KeyPair] :inflation_dest
286
+ # @option attributes [Array<Stellar::AccountFlags>] :set flags to set
287
+ # @option attributes [Array<Stellar::AccountFlags>] :clear flags to clear
288
+ # @option attributes [String] :thresholds
289
+ # @option attributes [Stellar::Signer] :signer
290
+ #
291
+ # @return [Stellar::Operation] the built operation, containing a
292
+ # Stellar::SetOptionsOp body
293
+ def set_options(attributes = {})
294
+ op = SetOptionsOp.new
295
+ op.set_flags = Stellar::AccountFlags.make_mask attributes[:set]
296
+ op.clear_flags = Stellar::AccountFlags.make_mask attributes[:clear]
297
+ op.master_weight = attributes[:master_weight]
298
+ op.low_threshold = attributes[:low_threshold]
299
+ op.med_threshold = attributes[:med_threshold]
300
+ op.high_threshold = attributes[:high_threshold]
301
+
302
+ op.signer = attributes[:signer]
303
+ op.home_domain = attributes[:home_domain]
304
+
305
+ inflation_dest = attributes[:inflation_dest]
306
+ if inflation_dest
307
+ raise ArgumentError, "Bad :inflation_dest" unless inflation_dest.is_a?(Stellar::KeyPair)
308
+ op.inflation_dest = inflation_dest.account_id
309
+ end
314
310
 
315
- return make(attributes.merge({
316
- body:[:set_options, op]
317
- }))
318
- end
319
-
320
- #
321
- # Helper method to create a valid AllowTrustOp, wrapped
322
- # in the necessary XDR structs to be included within a
323
- # transactions `operations` array.
324
- #
325
- # @param [Hash] attributes the attributes to create the operation with
326
- # @option attributes [Stellar::KeyPair] :trustor
327
- # @option attributes [Stellar::Asset] :asset
328
- #
329
- # @return [Stellar::Operation] the built operation, containing a
330
- # Stellar::AllowTrustOp body
331
- def self.allow_trust(attributes={})
332
- op = AllowTrustOp.new()
333
-
334
- trustor = attributes[:trustor]
335
- authorize = attributes[:authorize]
336
- asset = attributes[:asset]
337
- if asset.is_a?(Array)
338
- asset = Asset.send(*asset)
311
+ make(attributes.merge({
312
+ body: [:set_options, op]
313
+ }))
339
314
  end
340
315
 
341
- raise ArgumentError, "Bad :trustor" unless trustor.is_a?(Stellar::KeyPair)
342
- raise ArgumentError, "Bad :authorize" unless authorize == !!authorize # check boolean
343
- raise ArgumentError, "Bad :asset" unless asset.type == Stellar::AssetType.asset_type_credit_alphanum4
344
-
345
- atc = AllowTrustOp::Asset.new(:asset_type_credit_alphanum4, asset.code)
316
+ #
317
+ # Helper method to create a valid AllowTrustOp, wrapped
318
+ # in the necessary XDR structs to be included within a
319
+ # transactions `operations` array.
320
+ #
321
+ # @param [Hash] attributes the attributes to create the operation with
322
+ # @option attributes [Stellar::KeyPair] :trustor
323
+ # @option attributes [Stellar::Asset] :asset
324
+ # @option attributes [Symbol, Boolean] :authorize :full, maintain_liabilities or :none
325
+ #
326
+ # @return [Stellar::Operation] the built operation, containing a
327
+ # Stellar::AllowTrustOp body
328
+ def allow_trust(attributes = {})
329
+ op = AllowTrustOp.new
330
+
331
+ trustor = attributes[:trustor]
332
+ authorize = attributes[:authorize]
333
+ asset = attributes[:asset]
334
+ if asset.is_a?(Array)
335
+ asset = Asset.send(*asset)
336
+ end
346
337
 
347
- op.trustor = trustor.account_id
348
- op.authorize = authorize
349
- op.asset = atc
338
+ raise ArgumentError, "Bad :trustor" unless trustor.is_a?(Stellar::KeyPair)
350
339
 
351
- return make(attributes.merge({
352
- body:[:allow_trust, op]
353
- }))
354
- end
340
+ op.authorize = case authorize
341
+ when :none, false then 0 # we handle booleans here for the backward compatibility
342
+ when :full, true then TrustLineFlags.authorized_flag.value
343
+ when :maintain_liabilities then TrustLineFlags.authorized_to_maintain_liabilities_flag.value
344
+ else
345
+ raise ArgumentError, "Bad :authorize, supported values: :full, :maintain_liabilities, :none"
346
+ end
355
347
 
356
- #
357
- # Helper method to create an account merge operation
358
- #
359
- # @param [Hash] attributes the attributes to create the operation with
360
- # @option attributes [Stellar::KeyPair] :destination
361
- #
362
- # @return [Stellar::Operation] the built operation
363
- def self.account_merge(attributes={})
364
- destination = attributes[:destination]
365
-
366
- raise ArgumentError, "Bad :destination" unless destination.is_a?(KeyPair)
367
-
368
- # TODO: add source_account support
369
- return make(attributes.merge({
370
- body:[:account_merge, destination.account_id]
371
- }))
372
- end
348
+ raise ArgumentError, "Bad :asset" unless asset.type == Stellar::AssetType.asset_type_credit_alphanum4
373
349
 
374
- #
375
- # Helper method to create an inflation operation
376
- #
377
- # @param [Hash] attributes the attributes to create the operation with
378
- # @option attributes [Integer] :sequence
379
- #
380
- # @return [Stellar::Operation] the built operation
381
- def self.inflation(attributes={})
382
- sequence = attributes[:sequence]
383
-
384
- raise ArgumentError, "Bad :sequence #{sequence}" unless sequence.is_a?(Integer)
385
-
386
- # TODO: add source_account support
387
- return make(attributes.merge({
388
- body:[:inflation]
389
- }))
390
- end
350
+ atc = AllowTrustOp::Asset.new(:asset_type_credit_alphanum4, asset.code)
391
351
 
392
- #
393
- # Helper method to create an manage data operation
394
- #
395
- # @param [Hash] attributes the attributes to create the operation with
396
- # @option attributes [Integer] :sequence
397
- #
398
- # @return [Stellar::Operation] the built operation
399
- def self.manage_data(attributes={})
400
- op = ManageDataOp.new()
352
+ op.trustor = trustor.account_id
353
+ op.asset = atc
401
354
 
402
- name = attributes[:name]
403
- value = attributes[:value]
355
+ make(attributes.merge({
356
+ body: [:allow_trust, op]
357
+ }))
358
+ end
404
359
 
405
- raise ArgumentError, "Invalid :name" unless name.is_a?(String)
406
- raise ArgumentError, ":name too long" unless name.bytesize <= 64
360
+ #
361
+ # Helper method to create an account merge operation
362
+ #
363
+ # @param [Hash] attributes the attributes to create the operation with
364
+ # @option attributes [Stellar::KeyPair] :destination
365
+ #
366
+ # @return [Stellar::Operation] the built operation
367
+ def account_merge(attributes = {})
368
+ destination = attributes[:destination]
369
+
370
+ raise ArgumentError, "Bad :destination" unless destination.is_a?(KeyPair)
371
+
372
+ # TODO: add source_account support
373
+ make(attributes.merge({
374
+ body: [:account_merge, destination.muxed_account]
375
+ }))
376
+ end
407
377
 
408
- if value.present?
409
- raise ArgumentError, ":value too long" unless value.bytesize <= 64
378
+ #
379
+ # Helper method to create an inflation operation
380
+ #
381
+ # @param [Hash] attributes the attributes to create the operation with
382
+ # @option attributes [Integer] :sequence
383
+ #
384
+ # @return [Stellar::Operation] the built operation
385
+ def inflation(attributes = {})
386
+ sequence = attributes[:sequence]
387
+
388
+ raise ArgumentError, "Bad :sequence #{sequence}" unless sequence.is_a?(Integer)
389
+
390
+ # TODO: add source_account support
391
+ make(attributes.merge({
392
+ body: [:inflation]
393
+ }))
410
394
  end
411
395
 
412
- op.data_name = name
413
- op.data_value = value
396
+ #
397
+ # Helper method to create an manage data operation
398
+ #
399
+ # @param [Hash] attributes the attributes to create the operation with
400
+ # @option attributes [Integer] :sequence
401
+ #
402
+ # @return [Stellar::Operation] the built operation
403
+ def manage_data(attributes = {})
404
+ op = ManageDataOp.new
414
405
 
415
- return make(attributes.merge({
416
- body:[:manage_data, op]
417
- }))
418
- end
406
+ name = attributes[:name]
407
+ value = attributes[:value]
419
408
 
420
- def self.bump_sequence(attributes={})
421
- op = BumpSequenceOp.new()
409
+ raise ArgumentError, "Invalid :name" unless name.is_a?(String)
410
+ raise ArgumentError, ":name too long" unless name.bytesize <= 64
422
411
 
423
- bump_to = attributes[:bump_to]
412
+ if value.present?
413
+ raise ArgumentError, ":value too long" unless value.bytesize <= 64
414
+ end
424
415
 
425
- raise ArgumentError, ":bump_to too big" unless bump_to <= MAX_INT64
416
+ op.data_name = name
417
+ op.data_value = value
426
418
 
427
- op.bump_to = bump_to
419
+ make(attributes.merge({
420
+ body: [:manage_data, op]
421
+ }))
422
+ end
428
423
 
429
- return make(attributes.merge({
430
- body:[:bump_sequence, op]
431
- }))
432
- end
424
+ def bump_sequence(attributes = {})
425
+ op = BumpSequenceOp.new
426
+
427
+ bump_to = attributes[:bump_to]
428
+
429
+ raise ArgumentError, ":bump_to too big" unless bump_to <= MAX_INT64
430
+
431
+ op.bump_to = bump_to
433
432
 
434
- private
435
- def self.get_asset_amount(values)
436
- amount = interpret_amount(values.last)
437
- if values[0].is_a?(Stellar::Asset)
438
- asset = values.first
439
- else
440
- asset = Stellar::Asset.send(*values[0...-1])
433
+ make(attributes.merge({
434
+ body: [:bump_sequence, op]
435
+ }))
441
436
  end
442
437
 
443
- return asset, amount
444
- end
438
+ private
439
+
440
+ def get_asset_amount(values)
441
+ amount = interpret_amount(values.last)
442
+ asset = if values[0].is_a?(Stellar::Asset)
443
+ values.first
444
+ else
445
+ Stellar::Asset.send(*values[0...-1])
446
+ end
445
447
 
446
- def self.interpret_amount(amount)
447
- case amount
448
- when String
449
- (BigDecimal(amount) * Stellar::ONE).floor
450
- when Integer
451
- amount * Stellar::ONE
452
- when Numeric
453
- (amount * Stellar::ONE).floor
454
- else
455
- raise ArgumentError, "Invalid amount type: #{amount.class}. Must be String or Numeric"
448
+ [asset, amount]
456
449
  end
457
- end
458
450
 
451
+ def interpret_amount(amount)
452
+ case amount
453
+ when String
454
+ (BigDecimal(amount) * Stellar::ONE).floor
455
+ when Integer
456
+ amount * Stellar::ONE
457
+ when Numeric
458
+ (amount * Stellar::ONE).floor
459
+ else
460
+ raise ArgumentError, "Invalid amount type: #{amount.class}. Must be String or Numeric"
461
+ end
462
+ end
459
463
 
460
- def self.interpret_price(price)
461
- case price
462
- when String
463
- bd = BigDecimal.new(price)
464
- Price.from_f(bd)
465
- when Numeric
466
- Price.from_f(price)
467
- when Stellar::Price
468
- price
469
- else
470
- raise ArgumentError, "Invalid price type: #{price.class}. Must be String, Numeric, or Stellar::Price"
464
+ def interpret_price(price)
465
+ case price
466
+ when String
467
+ bd = BigDecimal(price)
468
+ Price.from_f(bd)
469
+ when Numeric
470
+ Price.from_f(price)
471
+ when Stellar::Price
472
+ price
473
+ else
474
+ raise ArgumentError, "Invalid price type: #{price.class}. Must be String, Numeric, or Stellar::Price"
475
+ end
471
476
  end
472
477
  end
473
478
  end