Class: Zilliqa::Account::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/zilliqa/account/transaction.rb

Overview

Transaction

Transaction is a functor. Its purpose is to encode the possible states a Transaction can be in: Confirmed, Rejected, Pending, or Initialised (i.e., not broadcasted).

Defined Under Namespace

Classes: StandardLengthError, TrackTxError, TransactionError

Constant Summary collapse

ATTRIBUTES =
%i[id version nonce amount gas_price gas_limit signature receipt sender_pub_key to_addr code data to_ds].freeze
GET_TX_ATTEMPTS =
33
MAX_BIGINT_BYTES =
2**128 - 1
TX_STATUSES =
{
  initialized: 0,
  pending: 1,
  confirmed: 2,
  rejected: 3
}.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(tx_params, provider, status = TX_STATUSES[:initialized], to_ds = false) ⇒ Transaction

Returns a new instance of Transaction.



33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/zilliqa/account/transaction.rb', line 33

def initialize(tx_params, provider, status = TX_STATUSES[:initialized], to_ds = false)
  unless tx_params.nil?
    tx_params.each do |key, value|
      next unless ATTRIBUTES.include?(key)
      instance_variable_set("@#{key}", value)
    end
  end

  @provider = provider
  @status = status
  @to_ds = to_ds
end

Instance Attribute Details

#providerObject

Returns the value of attribute provider.



22
23
24
# File 'lib/zilliqa/account/transaction.rb', line 22

def provider
  @provider
end

#statusObject

Returns the value of attribute status.



22
23
24
# File 'lib/zilliqa/account/transaction.rb', line 22

def status
  @status
end

Class Method Details

.confirm(tx_params, provider) ⇒ Object

constructs an already-confirmed transaction.



47
48
49
# File 'lib/zilliqa/account/transaction.rb', line 47

def self.confirm(tx_params, provider)
  Transaction.new(tx_params, provider, TX_STATUSES[:confirmed])
end

.reject(tx_params, provider) ⇒ Object

constructs an already-rejected transaction.



52
53
54
# File 'lib/zilliqa/account/transaction.rb', line 52

def self.reject(tx_params, provider)
  Transaction.new(tx_params, provider, TX_STATUSES[:rejected])
end

Instance Method Details

#bytesObject



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/zilliqa/account/transaction.rb', line 56

def bytes
  protocol = Zilliqa::Proto::ProtoTransactionCoreInfo.new
  protocol.version = version.to_i
  protocol.nonce = nonce.to_i
  protocol.toaddr = Util.decode_hex(Util::Bech32.to_checksum_address(to_addr).downcase.sub('0x', ''))
  protocol.senderpubkey = Zilliqa::Proto::ByteArray.new(data: Util.decode_hex(sender_pub_key))

  raise StandardLengthError if amount.to_i > MAX_BIGINT_BYTES

  protocol.amount = Zilliqa::Proto::ByteArray.new(data: bigint_to_bytes(amount.to_i))
  protocol.gasprice = Zilliqa::Proto::ByteArray.new(data: bigint_to_bytes(gas_price.to_i))
  protocol.gaslimit = gas_limit.to_i
  protocol.code = code if code
  protocol.data = data if data

  Zilliqa::Proto::ProtoTransactionCoreInfo.encode(protocol)
end

#confirm(tx_hash, max_attempts = GET_TX_ATTEMPTS, interval = 1) ⇒ Object

This sets the Transaction instance to a state of pending. Calling this function kicks off a passive loop that polls the lookup node for confirmation on the txHash.

The polls are performed with a linear backoff:

This is a low-level method that you should generally not have to use directly.



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/zilliqa/account/transaction.rb', line 113

def confirm(tx_hash, max_attempts = GET_TX_ATTEMPTS, interval = 1)
  @status = TX_STATUSES[:pending]
  1.upto(max_attempts) do
    return self if track_tx(tx_hash)

    sleep(interval)
  end

  self.status = TX_STATUSES[:rejected]
  throw 'The transaction is still not confirmed after ${maxAttempts} attempts.'
end

#confirmed?Boolean

Returns:

  • (Boolean)


97
98
99
# File 'lib/zilliqa/account/transaction.rb', line 97

def confirmed?
  @status == TX_STATUSES[:confirmed]
end

#initialised?Boolean

Returns:

  • (Boolean)


93
94
95
# File 'lib/zilliqa/account/transaction.rb', line 93

def initialised?
  @status == TX_STATUSES[:initialized]
end

#pending?Boolean

Returns:

  • (Boolean)


89
90
91
# File 'lib/zilliqa/account/transaction.rb', line 89

def pending?
  @status == TX_STATUSES[:pending]
end

#rejected?Boolean

Returns:

  • (Boolean)


101
102
103
# File 'lib/zilliqa/account/transaction.rb', line 101

def rejected?
  @status == TX_STATUSES[:rejected]
end

#submit!Object



143
144
145
146
147
# File 'lib/zilliqa/account/transaction.rb', line 143

def submit!
  provider.CreateTransaction(to_payload)
rescue TransactionError => e
  { error: e }
end

#to_payloadObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/zilliqa/account/transaction.rb', line 74

def to_payload
  {
    version: version.to_i,
    nonce: nonce.to_i,
    toAddr: Util::Bech32.to_checksum_address(to_addr),
    amount: amount.to_s,
    pubKey: sender_pub_key,
    gasPrice: gas_price.to_s,
    gasLimit: gas_limit.to_i,
    code: code,
    data: data,
    signature: signature
  }
end

#track_tx(tx_hash) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/zilliqa/account/transaction.rb', line 125

def track_tx(tx_hash)
  begin
    response = @provider.GetTransaction(tx_hash)
  rescue TrackTxError
  end

  if response['error']
    return false
  end

  self.id = response['result']['ID']
  self.receipt = response['result']['receipt']
  receipt['cumulative_gas'] = response['result']['receipt']['cumulative_gas'].to_i
  self.status = receipt && receipt['success'] ? TX_STATUSES[:confirmed] : TX_STATUSES[:rejected]

  true
end