Class: Stellar::TransactionBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/stellar/transaction_builder.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source_account:, sequence_number:, base_fee: 100, time_bounds: nil, memo: nil, **_) ⇒ TransactionBuilder

Returns a new instance of TransactionBuilder.

Raises:

  • (ArgumentError)

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/stellar/transaction_builder.rb', line 26

def initialize(
  source_account:,
  sequence_number:,
  base_fee: 100,
  time_bounds: nil,
  memo: nil,
  **_ # ignore any additional parameters without errors
)
  raise ArgumentError, "Bad :source_account" unless .is_a?(Stellar::KeyPair)
  raise ArgumentError, "Bad :sequence_number" unless sequence_number.is_a?(Integer) && sequence_number >= 0
  raise ArgumentError, "Bad :time_bounds" unless time_bounds.is_a?(Stellar::TimeBounds) || time_bounds.nil?
  raise ArgumentError, "Bad :base_fee" unless base_fee.is_a?(Integer) && base_fee >= 100

  @source_account = 
  @sequence_number = sequence_number
  @base_fee = base_fee
  @time_bounds = time_bounds

  if time_bounds.nil?
    set_timeout(0)
  end

  @memo = make_memo(memo)
  @operations = []
end

Instance Attribute Details

#base_feeObject (readonly)

Returns the value of attribute base_fee


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def base_fee
  @base_fee
end

#memoObject (readonly)

Returns the value of attribute memo


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def memo
  @memo
end

#operationsObject (readonly)

Returns the value of attribute operations


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def operations
  @operations
end

#sequence_numberObject (readonly)

Returns the value of attribute sequence_number


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def sequence_number
  @sequence_number
end

#source_accountObject (readonly)

Returns the value of attribute source_account


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def 
  @source_account
end

#time_boundsObject (readonly)

Returns the value of attribute time_bounds


3
4
5
# File 'lib/stellar/transaction_builder.rb', line 3

def time_bounds
  @time_bounds
end

Class Method Details

.method_missing(method_name, *args, **kwargs) ⇒ Object

This enable user to call shortcut methods, like TransactionBuilder.payment(…), TransactionBuilder.manage_data(…) and etc. It reduces the boilerplate, when you just need to shoot a single operation in transaction


11
12
13
14
15
16
17
18
19
# File 'lib/stellar/transaction_builder.rb', line 11

def method_missing(method_name, *args, **kwargs)
  unless Stellar::Operation.respond_to?(method_name)
    return super
  end

  op = Stellar::Operation.send(method_name, **kwargs)

  new(**kwargs).add_operation(op).build
end

.respond_to_missing?(method_name, include_private = false) ⇒ Boolean

Returns:

  • (Boolean)

21
22
23
# File 'lib/stellar/transaction_builder.rb', line 21

def respond_to_missing?(method_name, include_private = false)
  Stellar::Operation.respond_to?(method_name) || super
end

Instance Method Details

#add_operation(operation) ⇒ Object

Raises:

  • (ArgumentError)

100
101
102
103
104
# File 'lib/stellar/transaction_builder.rb', line 100

def add_operation(operation)
  raise ArgumentError, "Bad operation" unless operation.is_a? Stellar::Operation
  @operations.push(operation)
  self
end

#buildObject


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/stellar/transaction_builder.rb', line 52

def build
  if @time_bounds.nil?
    raise "TransactionBuilder.time_bounds must be set during initialization or by calling set_timeout"
  elsif !@time_bounds.min_time.is_a?(Integer) || !@time_bounds.max_time.is_a?(Integer)
    raise "TimeBounds.min_time and max_time must be Integers"
  elsif @time_bounds.max_time != 0 && @time_bounds.min_time > @time_bounds.max_time
    raise "Timebounds.max_time must be greater than min_time"
  end

  attrs = {
    source_account: @source_account.,
    fee: @base_fee * @operations.length,
    seq_num: @sequence_number,
    time_bounds: @time_bounds,
    memo: @memo,
    operations: @operations,
    ext: Stellar::Transaction::Ext.new(0)
  }

  @sequence_number += 1

  Stellar::Transaction.new(attrs)
end

#build_fee_bump(inner_txe:) ⇒ Object


76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/stellar/transaction_builder.rb', line 76

def build_fee_bump(inner_txe:)
  if inner_txe.switch == Stellar::EnvelopeType.envelope_type_tx_v0
    inner_txe = Stellar::TransactionEnvelope.v1(tx: inner_txe.tx.to_v1, signatures: inner_txe.signatures)
  elsif inner_txe.switch != Stellar::EnvelopeType.envelope_type_tx
    raise ArgumentError, "Invalid inner transaction type #{inner_txe.switch}"
  end

  inner_tx = inner_txe.tx
  inner_ops = inner_tx.operations
  inner_base_fee_rate = inner_tx.fee.fdiv(inner_ops.length)

  # The fee rate for fee bump is at least the fee rate of the inner transaction
  if @base_fee < inner_base_fee_rate
    raise "Insufficient base_fee, it should be at least #{inner_base_fee_rate} stroops."
  end

  Stellar::FeeBumpTransaction.new(
    fee_source: @source_account.,
    fee: @base_fee * (inner_ops.length + 1),
    inner_tx: Stellar::FeeBumpTransaction::InnerTx.new(:envelope_type_tx, inner_txe.v1!),
    ext: Stellar::FeeBumpTransaction::Ext.new(0)
  )
end

#clear_operationsObject


106
107
108
109
# File 'lib/stellar/transaction_builder.rb', line 106

def clear_operations
  @operations.clear
  self
end

#make_memo(memo) ⇒ Object


148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/stellar/transaction_builder.rb', line 148

def make_memo(memo)
  case memo
  when Stellar::Memo
    memo
  when nil
    Memo.new(:memo_none)
  when Integer
    Memo.new(:memo_id, memo)
  when String
    Memo.new(:memo_text, memo)
  when Array
    t, val = *memo
    Memo.new(:"memo_#{t}", val)
  else
    raise ArgumentError, "Bad :memo"
  end
end

#set_base_fee(base_fee) ⇒ Object

Raises:

  • (ArgumentError)

142
143
144
145
146
# File 'lib/stellar/transaction_builder.rb', line 142

def set_base_fee(base_fee)
  raise ArgumentError, "Bad base fee" unless base_fee.is_a?(Integer) && base_fee >= 100
  @base_fee = base_fee
  self
end

#set_memo(memo) ⇒ Object


137
138
139
140
# File 'lib/stellar/transaction_builder.rb', line 137

def set_memo(memo)
  @memo = make_memo(memo)
  self
end

#set_sequence_number(seq_num) ⇒ Object

Raises:

  • (ArgumentError)

117
118
119
120
121
# File 'lib/stellar/transaction_builder.rb', line 117

def set_sequence_number(seq_num)
  raise ArgumentError, "Bad sequence number" unless seq_num.is_a?(Integer) && seq_num >= 0
  @sequence_number = seq_num
  self
end

#set_source_account(account_kp) ⇒ Object

Raises:

  • (ArgumentError)

111
112
113
114
115
# File 'lib/stellar/transaction_builder.rb', line 111

def ()
  raise ArgumentError, "Bad source account" unless .is_a?(Stellar::KeyPair)
  @source_account = 
  self
end

#set_timeout(timeout) ⇒ Object


123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/stellar/transaction_builder.rb', line 123

def set_timeout(timeout)
  if !timeout.is_a?(Integer) || timeout < 0
    raise ArgumentError, "Timeout must be a non-negative integer"
  end

  if @time_bounds.nil?
    @time_bounds = Stellar::TimeBounds.new(min_time: 0, max_time: nil)
  end

  @time_bounds.max_time = timeout == 0 ? timeout : Time.now.to_i + timeout

  self
end