stellar-base 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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