stellar-base 0.21.0 → 0.22.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.
@@ -11,6 +11,8 @@ require 'xdr'
11
11
  # OperationMeta operations<>;
12
12
  # case 1:
13
13
  # TransactionMetaV1 v1;
14
+ # case 2:
15
+ # TransactionMetaV2 v2;
14
16
  # };
15
17
  #
16
18
  # ===========================================================================
@@ -20,8 +22,10 @@ module Stellar
20
22
 
21
23
  switch 0, :operations
22
24
  switch 1, :v1
25
+ switch 2, :v2
23
26
 
24
27
  attribute :operations, XDR::VarArray[OperationMeta]
25
28
  attribute :v1, TransactionMetaV1
29
+ attribute :v2, TransactionMetaV2
26
30
  end
27
31
  end
@@ -0,0 +1,24 @@
1
+ # This code was automatically generated using xdrgen
2
+ # DO NOT EDIT or your changes may be overwritten
3
+
4
+ require 'xdr'
5
+
6
+ # === xdr source ============================================================
7
+ #
8
+ # struct TransactionMetaV2
9
+ # {
10
+ # LedgerEntryChanges txChangesBefore; // tx level changes before operations
11
+ # // are applied if any
12
+ # OperationMeta operations<>; // meta for each operation
13
+ # LedgerEntryChanges txChangesAfter; // tx level changes after operations are
14
+ # // applied if any
15
+ # };
16
+ #
17
+ # ===========================================================================
18
+ module Stellar
19
+ class TransactionMetaV2 < XDR::Struct
20
+ attribute :tx_changes_before, LedgerEntryChanges
21
+ attribute :operations, XDR::VarArray[OperationMeta]
22
+ attribute :tx_changes_after, LedgerEntryChanges
23
+ end
24
+ end
@@ -0,0 +1,22 @@
1
+ # This code was automatically generated using xdrgen
2
+ # DO NOT EDIT or your changes may be overwritten
3
+
4
+ require 'xdr'
5
+
6
+ # === xdr source ============================================================
7
+ #
8
+ # struct TransactionResultMeta
9
+ # {
10
+ # TransactionResultPair result;
11
+ # LedgerEntryChanges feeProcessing;
12
+ # TransactionMeta txApplyProcessing;
13
+ # };
14
+ #
15
+ # ===========================================================================
16
+ module Stellar
17
+ class TransactionResultMeta < XDR::Struct
18
+ attribute :result, TransactionResultPair
19
+ attribute :fee_processing, LedgerEntryChanges
20
+ attribute :tx_apply_processing, TransactionMeta
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ # This code was automatically generated using xdrgen
2
+ # DO NOT EDIT or your changes may be overwritten
3
+
4
+ require 'xdr'
5
+
6
+ # === xdr source ============================================================
7
+ #
8
+ # struct UpgradeEntryMeta
9
+ # {
10
+ # LedgerUpgrade upgrade;
11
+ # LedgerEntryChanges changes;
12
+ # };
13
+ #
14
+ # ===========================================================================
15
+ module Stellar
16
+ class UpgradeEntryMeta < XDR::Struct
17
+ attribute :upgrade, LedgerUpgrade
18
+ attribute :changes, LedgerEntryChanges
19
+ end
20
+ end
@@ -25,6 +25,7 @@ require_relative './stellar/price'
25
25
  require_relative './stellar/signer_key'
26
26
  require_relative './stellar/thresholds'
27
27
  require_relative './stellar/transaction'
28
+ require_relative './stellar/transaction_builder'
28
29
  require_relative './stellar/transaction_envelope'
29
30
  require_relative './stellar/util/strkey'
30
31
  require_relative './stellar/util/continued_fraction'
@@ -1,5 +1,5 @@
1
1
  module Stellar
2
2
  module Base
3
- VERSION = "0.21.0"
3
+ VERSION = "0.22.0"
4
4
  end
5
5
  end
@@ -43,7 +43,7 @@ module Stellar
43
43
  # Stellar::PaymentOp body
44
44
  def self.payment(attributes={})
45
45
  destination = attributes[:destination]
46
- asset, amount = extract_amount(attributes[:amount])
46
+ asset, amount = get_asset_amount(attributes[:amount])
47
47
 
48
48
  raise ArgumentError unless destination.is_a?(KeyPair)
49
49
 
@@ -96,9 +96,11 @@ module Stellar
96
96
  #
97
97
  def self.path_payment_strict_receive(attributes={})
98
98
  destination = attributes[:destination]
99
- asset, amount = extract_amount(attributes[:amount])
100
- send_asset, send_max = extract_amount(attributes[:with])
101
- path = (attributes[:path] || []).map{|p| Stellar::Asset.send(*p)}
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
+ }
102
104
 
103
105
  raise ArgumentError unless destination.is_a?(KeyPair)
104
106
 
@@ -132,9 +134,11 @@ module Stellar
132
134
  #
133
135
  def self.path_payment_strict_send(attributes={})
134
136
  destination = attributes[:destination]
135
- asset, dest_min = extract_amount(attributes[:amount])
136
- send_asset, send_amount = extract_amount(attributes[:with])
137
- path = (attributes[:path] || []).map{|p| Stellar::Asset.send(*p)}
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
+ }
138
142
 
139
143
  raise ArgumentError unless destination.is_a?(KeyPair)
140
144
 
@@ -199,11 +203,17 @@ module Stellar
199
203
  end
200
204
 
201
205
  def self.manage_sell_offer(attributes={})
202
- buying = Asset.send(*attributes[:buying])
203
- selling = Asset.send(*attributes[:selling])
204
- amount = interpret_amount(attributes[:amount])
205
- offer_id = attributes[:offer_id] || 0
206
- price = interpret_price(attributes[:price])
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)
213
+ end
214
+ amount = interpret_amount(attributes[:amount])
215
+ offer_id = attributes[:offer_id] || 0
216
+ price = interpret_price(attributes[:price])
207
217
 
208
218
  op = ManageSellOfferOp.new({
209
219
  buying: buying,
@@ -219,11 +229,17 @@ module Stellar
219
229
  end
220
230
 
221
231
  def self.manage_buy_offer(attributes={})
222
- buying = Asset.send(*attributes[:buying])
223
- selling = Asset.send(*attributes[:selling])
224
- amount = interpret_amount(attributes[:amount])
225
- offer_id = attributes[:offer_id] || 0
226
- price = interpret_price(attributes[:price])
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)
239
+ end
240
+ amount = interpret_amount(attributes[:amount])
241
+ offer_id = attributes[:offer_id] || 0
242
+ price = interpret_price(attributes[:price])
227
243
 
228
244
  op = ManageBuyOfferOp.new({
229
245
  buying: buying,
@@ -239,10 +255,16 @@ module Stellar
239
255
  end
240
256
 
241
257
  def self.create_passive_sell_offer(attributes={})
242
- buying = Asset.send(*attributes[:buying])
243
- selling = Asset.send(*attributes[:selling])
244
- amount = interpret_amount(attributes[:amount])
245
- price = interpret_price(attributes[:price])
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)
265
+ end
266
+ amount = interpret_amount(attributes[:amount])
267
+ price = interpret_price(attributes[:price])
246
268
 
247
269
  op = CreatePassiveSellOfferOp.new({
248
270
  buying: buying,
@@ -309,9 +331,12 @@ module Stellar
309
331
  def self.allow_trust(attributes={})
310
332
  op = AllowTrustOp.new()
311
333
 
312
- trustor = attributes[:trustor]
334
+ trustor = attributes[:trustor]
313
335
  authorize = attributes[:authorize]
314
- asset = Asset.send(*attributes[:asset])
336
+ asset = attributes[:asset]
337
+ if asset.is_a?(Array)
338
+ asset = Asset.send(*asset)
339
+ end
315
340
 
316
341
  raise ArgumentError, "Bad :trustor" unless trustor.is_a?(Stellar::KeyPair)
317
342
  raise ArgumentError, "Bad :authorize" unless authorize == !!authorize # check boolean
@@ -407,9 +432,13 @@ module Stellar
407
432
  end
408
433
 
409
434
  private
410
- def self.extract_amount(a)
411
- amount = interpret_amount(a.last)
412
- asset = Stellar::Asset.send(*a[0...-1])
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])
441
+ end
413
442
 
414
443
  return asset, amount
415
444
  end
@@ -91,6 +91,14 @@ module Stellar
91
91
  make :bump_sequence, attributes
92
92
  end
93
93
 
94
+ #
95
+ # DEPRECATED
96
+ #
97
+ # All methods calling make() have been deprecated in favor of Stellar::TransactionBuilder.
98
+ # These functions only create single-operation transactions and essentially duplicate the
99
+ # methods provided by Stellar::Operation. Stellar::TransactionBuilder enables the construction
100
+ # of multi-operation transactions and mirrors the functionality provided by the Python and
101
+ # JavaScript SDKs.
94
102
  #
95
103
  # Helper method to create a transaction with a single
96
104
  # operation of the provided type. See class methods
@@ -104,6 +112,9 @@ module Stellar
104
112
  #
105
113
  # @return [Stellar::Transaction] the resulting transaction
106
114
  def self.make(operation_type, attributes={})
115
+ Stellar::Deprecation.warn(
116
+ "Transaction.#{operation_type.to_s} is deprecated. Use Stellar::TransactionBuilder instead."
117
+ )
107
118
  for_account(attributes).tap do |result|
108
119
  result.operations << Operation.send(operation_type, attributes)
109
120
  end
@@ -0,0 +1,106 @@
1
+ module Stellar
2
+ class TransactionBuilder
3
+
4
+ attr_reader :source_account, :sequence_number, :base_fee, :time_bounds, :time_bounds, :memo, :operations
5
+
6
+ def initialize(
7
+ source_account:,
8
+ sequence_number:,
9
+ base_fee: 100,
10
+ time_bounds: nil,
11
+ memo: nil
12
+ )
13
+ raise ArgumentError, "Bad :source_account" unless source_account.is_a?(Stellar::KeyPair)
14
+ raise ArgumentError, "Bad :sequence_number" unless sequence_number.is_a?(Integer) && sequence_number >= 0
15
+ raise ArgumentError, "Bad :time_bounds" unless time_bounds.is_a?(Stellar::TimeBounds) || time_bounds.nil?
16
+ raise ArgumentError, "Bad :base_fee" unless base_fee.is_a?(Integer) && base_fee >= 100
17
+
18
+ @source_account = source_account
19
+ @sequence_number = sequence_number
20
+ @base_fee = base_fee
21
+ @time_bounds = time_bounds
22
+ @memo = self.make_memo(memo)
23
+ @operations = Array.new
24
+ end
25
+
26
+ def build
27
+ if @time_bounds.nil?
28
+ raise "TransactionBuilder.time_bounds must be set during initialization or by calling set_timeout"
29
+ elsif !@time_bounds.min_time.is_a?(Integer) || !@time_bounds.max_time.is_a?(Integer)
30
+ raise "TimeBounds.min_time and max_time must be Integers"
31
+ elsif @time_bounds.max_time != 0 && @time_bounds.min_time > @time_bounds.max_time
32
+ raise "Timebounds.max_time must be greater than min_time"
33
+ end
34
+ tx = Stellar::Transaction.new(
35
+ source_account: @source_account.account_id,
36
+ fee: @base_fee * @operations.length,
37
+ seq_num: @sequence_number,
38
+ time_bounds: @time_bounds,
39
+ memo: @memo,
40
+ operations: @operations,
41
+ ext: Stellar::Transaction::Ext.new(0)
42
+ )
43
+ @sequence_number += 1
44
+ tx
45
+ end
46
+
47
+ def add_operation(operation)
48
+ raise ArgumentError, "Bad operation" unless operation.is_a? Stellar::Operation
49
+ @operations.push(operation)
50
+ self
51
+ end
52
+
53
+ def clear_operations()
54
+ @operations.clear
55
+ self
56
+ end
57
+
58
+ def set_sequence_number(seq_num)
59
+ raise ArgumentError, "Bad sequence number" unless seq_num.is_a?(Integer) && seq_num >= 0
60
+ @sequence_number = seq_num
61
+ self
62
+ end
63
+
64
+ def set_timeout(timeout)
65
+ if !timeout.is_a?(Integer) || timeout < 0
66
+ raise ArgumentError, "Timeout must be a non-negative integer"
67
+ end
68
+
69
+ if @time_bounds.nil?
70
+ @time_bounds = Stellar::TimeBounds.new(min_time: 0, max_time: nil)
71
+ end
72
+
73
+ if timeout == 0
74
+ @time_bounds.max_time = timeout
75
+ else
76
+ @time_bounds.max_time = Time.now.to_i + timeout
77
+ end
78
+
79
+ self
80
+ end
81
+
82
+ def set_memo(memo)
83
+ @memo = make_memo(memo)
84
+ self
85
+ end
86
+
87
+ def make_memo(memo)
88
+ case memo
89
+ when Stellar::Memo ;
90
+ memo
91
+ when nil ;
92
+ Memo.new(:memo_none)
93
+ when Integer ;
94
+ Memo.new(:memo_id, memo)
95
+ when String ;
96
+ Memo.new(:memo_text, memo)
97
+ when Array ;
98
+ t, val = *memo
99
+ Memo.new(:"memo_#{t}", val)
100
+ else
101
+ raise ArgumentError, "Bad :memo"
102
+ end
103
+ end
104
+
105
+ end
106
+ end
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
7
7
  spec.authors = ["Scott Fleckenstein"]
8
8
  spec.email = ["scott@stellar.org"]
9
9
  spec.summary = %q{Stellar client library: XDR}
10
- spec.homepage = "https://github.com/bloom-solutions/ruby-stellar-base"
10
+ spec.homepage = "https://github.com/stellar/ruby-stellar-base"
11
11
  spec.license = "Apache 2.0"
12
12
 
13
13
  spec.files = `git ls-files -z`.split("\x0")
@@ -1,15 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Stellar::Operation, ".payment" do
4
-
5
-
6
4
  it "correctly translates the provided amount to the native representation" do
7
5
  op = Stellar::Operation.payment(destination: Stellar::KeyPair.random, amount: [:native, 20])
8
6
  expect(op.body.value.amount).to eql(20_0000000)
9
7
  op = Stellar::Operation.payment(destination: Stellar::KeyPair.random, amount: [:native, "20"])
10
8
  expect(op.body.value.amount).to eql(20_0000000)
11
9
  end
12
-
13
10
  end
14
11
 
15
12
  def pk_to_address(pk)
@@ -22,13 +19,14 @@ describe "path payment operations" do
22
19
  let(:send_asset){ Stellar::Asset.alphanum4("USD", send_asset_issuer) }
23
20
  let(:dest_asset_issuer){ Stellar::KeyPair.master }
24
21
  let(:dest_asset){ Stellar::Asset.alphanum4("EUR", dest_asset_issuer) }
25
- let(:amount){ [:alphanum4, dest_asset.code, dest_asset_issuer, 9.2] }
26
- let(:with){ [:alphanum4, send_asset.code, send_asset_issuer, 10] }
22
+ let(:amount){ [Stellar::Asset.alphanum4(dest_asset.code, dest_asset_issuer), 9.2] }
23
+ let(:with){ [Stellar::Asset.alphanum4(send_asset.code, send_asset_issuer), 10] }
27
24
 
28
25
  describe Stellar::Operation, ".path_payment" do
29
26
  it "works" do
30
27
  destination = Stellar::KeyPair.random
31
- amount = [:alphanum4, "USD", Stellar::KeyPair.master, 10]
28
+ # test both forms of arrays
29
+ amount = [Stellar::Asset.alphanum4("USD", Stellar::KeyPair.master), 10]
32
30
  with = [:alphanum4, "EUR", Stellar::KeyPair.master, 9.2]
33
31
 
34
32
  op = Stellar::Operation.path_payment(
@@ -98,7 +96,7 @@ describe Stellar::Operation, ".change_trust" do
98
96
  let(:asset) { Stellar::Asset.alphanum4("USD", issuer) }
99
97
 
100
98
  it "creates a ChangeTrustOp" do
101
- op = Stellar::Operation.change_trust(line: [:alphanum4, "USD", issuer])
99
+ op = Stellar::Operation.change_trust(line: Stellar::Asset.alphanum4("USD", issuer))
102
100
  expect(op.body.value).to be_an_instance_of(Stellar::ChangeTrustOp)
103
101
  expect(op.body.value.line).to eq(Stellar::Asset.alphanum4("USD", issuer))
104
102
  expect(op.body.value.limit).to eq(9223372036854775807)
@@ -119,7 +117,7 @@ describe Stellar::Operation, ".change_trust" do
119
117
  end
120
118
 
121
119
  it "creates a ChangeTrustOp with limit" do
122
- op = Stellar::Operation.change_trust(line: [:alphanum4, "USD", issuer], limit: 1234.75)
120
+ op = Stellar::Operation.change_trust(line: Stellar::Asset.alphanum4("USD", issuer), limit: 1234.75)
123
121
  expect(op.body.value).to be_an_instance_of(Stellar::ChangeTrustOp)
124
122
  expect(op.body.value.line).to eq(Stellar::Asset.alphanum4("USD", issuer))
125
123
  expect(op.body.value.limit).to eq(12347500000)
@@ -127,7 +125,7 @@ describe Stellar::Operation, ".change_trust" do
127
125
 
128
126
  it "throws ArgumentError for incorrect limit argument" do
129
127
  expect {
130
- Stellar::Operation.change_trust(line: [:alphanum4, "USD", issuer], limit: true)
128
+ Stellar::Operation.change_trust(line: Stellar::Asset.alphanum4("USD", issuer), limit: true)
131
129
  }.to raise_error(ArgumentError)
132
130
  end
133
131
  end
@@ -0,0 +1,263 @@
1
+ require "spec_helper"
2
+
3
+ describe Stellar::TransactionBuilder do
4
+ let(:key_pair){ Stellar::KeyPair.random }
5
+ builder = nil
6
+ before(:each) do
7
+ builder = Stellar::TransactionBuilder.new(
8
+ source_account: key_pair,
9
+ sequence_number: 1
10
+ )
11
+ end
12
+
13
+ describe ".initialize" do
14
+ it "bad source_account" do
15
+ expect {
16
+ Stellar::TransactionBuilder.new(
17
+ source_account: key_pair.account_id,
18
+ sequence_number: 1
19
+ )
20
+ }.to raise_error(
21
+ ArgumentError, "Bad :source_account"
22
+ )
23
+ end
24
+ it "bad sequence_number" do
25
+ expect {
26
+ Stellar::TransactionBuilder.new(
27
+ source_account: key_pair,
28
+ sequence_number: -1
29
+ )
30
+ }.to raise_error(
31
+ ArgumentError, "Bad :sequence_number"
32
+ )
33
+ end
34
+ it "bad timeout" do
35
+ expect {
36
+ Stellar::TransactionBuilder.new(
37
+ source_account: key_pair,
38
+ sequence_number: 1,
39
+ time_bounds: 600
40
+ )
41
+ }.to raise_error(
42
+ ArgumentError, "Bad :time_bounds"
43
+ )
44
+ end
45
+ it "bad base_fee" do
46
+ expect {
47
+ Stellar::TransactionBuilder.new(
48
+ source_account: key_pair,
49
+ sequence_number: 1,
50
+ base_fee: 0
51
+ )
52
+ }.to raise_error(
53
+ ArgumentError, "Bad :base_fee"
54
+ )
55
+ end
56
+ it "bad memo" do
57
+ expect {
58
+ Stellar::TransactionBuilder.new(
59
+ source_account: key_pair,
60
+ sequence_number: 1,
61
+ memo: {"data" => "Testing bad memo"}
62
+ )
63
+ }.to raise_error(
64
+ ArgumentError, "Bad :memo"
65
+ )
66
+ end
67
+ it "success" do
68
+ builder = Stellar::TransactionBuilder.new(
69
+ source_account: key_pair,
70
+ sequence_number: 1,
71
+ time_bounds: Stellar::TimeBounds.new(min_time: 0, max_time: 600),
72
+ base_fee: 200,
73
+ memo: "My test memo"
74
+ )
75
+ expect(builder.memo).to eql(Stellar::Memo.new(:memo_text, "My test memo"))
76
+ end
77
+ end
78
+
79
+ describe ".add_operation" do
80
+ it "bad operation" do
81
+ expect {
82
+ builder.add_operation(
83
+ [:bump_sequence, 1]
84
+ )
85
+ }.to raise_error(
86
+ ArgumentError, "Bad operation"
87
+ )
88
+ end
89
+
90
+ it "returns self" do
91
+ expect(builder.add_operation(
92
+ Stellar::Operation.bump_sequence({"bump_to": 1})
93
+ )).to be_an_instance_of(Stellar::TransactionBuilder)
94
+ end
95
+ end
96
+
97
+ describe ".clear_operations" do
98
+ it "can clear operations" do
99
+ builder = builder.add_operation(
100
+ Stellar::Operation.bump_sequence({"bump_to": 1})
101
+ ).clear_operations
102
+ expect(builder.operations).to eql([])
103
+ end
104
+
105
+ it "returns self" do
106
+ expect(builder.add_operation(
107
+ Stellar::Operation.bump_sequence({"bump_to": 1})
108
+ ).clear_operations).to be_an_instance_of(Stellar::TransactionBuilder)
109
+ end
110
+ end
111
+
112
+ describe ".set_sequence_number" do
113
+ it "allows sequence number to be updated" do
114
+ builder.set_sequence_number(5)
115
+ expect(builder.sequence_number).to eql(5)
116
+ end
117
+
118
+ it "returns self" do
119
+ expect(builder.set_sequence_number(3)).to be_an_instance_of(Stellar::TransactionBuilder)
120
+ end
121
+
122
+ it "raises an error for bad sequence number" do
123
+ expect {
124
+ builder.set_sequence_number(nil)
125
+ }.to raise_error(
126
+ ArgumentError, "Bad sequence number"
127
+ )
128
+ end
129
+ end
130
+
131
+ describe ".set_timeout" do
132
+ it "raises an error for non-integers" do
133
+ expect {
134
+ builder.set_timeout(nil)
135
+ }.to raise_error(
136
+ ArgumentError, "Timeout must be a non-negative integer"
137
+ )
138
+ end
139
+
140
+ it "raises an error for negative timeouts" do
141
+ expect {
142
+ builder.set_timeout(-1)
143
+ }.to raise_error(
144
+ ArgumentError, "Timeout must be a non-negative integer"
145
+ )
146
+ end
147
+
148
+ it "returns self" do
149
+ expect(builder.set_timeout(10)).to be_an_instance_of(Stellar::TransactionBuilder)
150
+ end
151
+ end
152
+
153
+ describe ".set_memo" do
154
+ it "raises an error for bad memos" do
155
+ expect {
156
+ builder.set_memo({"data" => "Testing bad memo"})
157
+ }.to raise_error(
158
+ ArgumentError, "Bad :memo"
159
+ )
160
+ end
161
+
162
+ it "works and returns self" do
163
+ expect(builder.set_memo("Hello").memo).to eql(Stellar::Memo.new(:memo_text, "Hello"))
164
+ end
165
+ end
166
+
167
+ describe ".build" do
168
+ it "raises error for time_bounds not set" do
169
+ expect {
170
+ tx = builder.add_operation(
171
+ Stellar::Operation.bump_sequence({"bump_to": 1})
172
+ ).build()
173
+ }.to raise_error(
174
+ RuntimeError,
175
+ "TransactionBuilder.time_bounds must be set during initialization or by calling set_timeout"
176
+ )
177
+ end
178
+
179
+ it "raises an error for non-integer timebounds" do
180
+ builder = Stellar::TransactionBuilder.new(
181
+ source_account: key_pair,
182
+ sequence_number: 1,
183
+ time_bounds: Stellar::TimeBounds.new(min_time: "not", max_time: "integers")
184
+ )
185
+ expect {
186
+ tx = builder.add_operation(
187
+ Stellar::Operation.bump_sequence({"bump_to": 1})
188
+ ).build()
189
+ }.to raise_error(
190
+ RuntimeError, "TimeBounds.min_time and max_time must be Integers"
191
+ )
192
+ end
193
+
194
+ it "raises an error for bad TimeBounds range" do
195
+ builder = Stellar::TransactionBuilder.new(
196
+ source_account: key_pair,
197
+ sequence_number: 1,
198
+ time_bounds: Stellar::TimeBounds.new(min_time: Time.now.to_i + 10, max_time: Time.now.to_i)
199
+ )
200
+ expect {
201
+ tx = builder.add_operation(
202
+ Stellar::Operation.bump_sequence({"bump_to": 1})
203
+ ).build()
204
+ }.to raise_error(
205
+ RuntimeError, "Timebounds.max_time must be greater than min_time"
206
+ )
207
+ end
208
+
209
+ it "allows max_time to be zero" do
210
+ tx = builder.add_operation(
211
+ Stellar::Operation.bump_sequence({"bump_to": 1})
212
+ ).set_timeout(0).build()
213
+ expect(builder.time_bounds.max_time).to eql(0)
214
+ end
215
+
216
+ it "updates sequence number by 1 per build" do
217
+ builder.add_operation(
218
+ Stellar::Operation.bump_sequence({"bump_to": 1})
219
+ ).set_timeout(0).build()
220
+ expect(builder.sequence_number).to eql(2)
221
+ end
222
+
223
+ it "creates transaction successfully" do
224
+ bump_op = Stellar::Operation.bump_sequence({"bump_to": 1})
225
+ builder.add_operation(
226
+ Stellar::Operation.bump_sequence({"bump_to": 1})
227
+ ).set_timeout(600).build()
228
+ expect(builder.operations).to eql([bump_op])
229
+ end
230
+
231
+ it "allows for multiple transactions to be created" do
232
+ first_max_time = Time.now.to_i + 1000
233
+ bump_op = Stellar::Operation.bump_sequence({"bump_to": 1})
234
+ builder = Stellar::TransactionBuilder.new(
235
+ source_account: key_pair,
236
+ sequence_number: 1,
237
+ time_bounds: Stellar::TimeBounds.new(min_time: 0, max_time: first_max_time)
238
+ )
239
+ tx1 = builder.add_operation(
240
+ Stellar::Operation.bump_sequence({"bump_to": 1})
241
+ ).build()
242
+ expect(tx1.seq_num).to eql(1)
243
+ expect(tx1.operations).to eql([
244
+ Stellar::Operation.bump_sequence({"bump_to": 1})
245
+ ])
246
+ expect(tx1.time_bounds.max_time).to eql(first_max_time)
247
+
248
+ tx2 = builder.clear_operations.add_operation(
249
+ Stellar::Operation.bump_sequence({"bump_to": 2})
250
+ ).set_timeout(0).build()
251
+ expect(tx2.seq_num).to eql(2)
252
+ expect(tx2.operations).to eql([
253
+ Stellar::Operation.bump_sequence({"bump_to": 2})
254
+ ])
255
+ expect(tx2.time_bounds.max_time).to eql(0)
256
+
257
+ expect(builder.sequence_number).to eql(3)
258
+ expect(builder.operations).to eql([
259
+ Stellar::Operation.bump_sequence({"bump_to": 2})
260
+ ])
261
+ end
262
+ end
263
+ end