Class: Neb::Transaction

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

Constant Summary collapse

MAX_GAS_PRICE =
1_000_000_000_000
MAX_GAS =
50_000_000_000
GAS_PRICE =
1_000_000
GAS_LIMIT =
20_000
PAYLOAD_BINARY_TYPE =
"binary".freeze
PAYLOAD_DEPLOY_TYPE =
"deploy".freeze
PAYLOAD_CALL_TYPE =
"call".freeze
CHAIN_ID_LIST =
{
  1    => { name: "Mainnet",     url: "https://mainnet.nebulas.io" },
  1001 => { name: "Testnet",     url: "https://testnet.nebulas.io" },
  100  => { name: "Local Nodes", url: "http://127.0.0.1:8685" }
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(chain_id:, from_account:, to_address:, value:, nonce:, gas_price: GAS_PRICE, gas_limit: GAS_LIMIT, contract: {}) ⇒ Transaction

Returns a new instance of Transaction.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/neb/transaction.rb', line 26

def initialize(chain_id:, from_account:, to_address:, value:, nonce:,
               gas_price: GAS_PRICE, gas_limit: GAS_LIMIT, contract: {})
  @chain_id     = chain_id
  @from_account = 
  @to_address   = Address.new(to_address)
  @value        = value
  @nonce        = nonce
  @gas_price    = gas_price >= 0 ? gas_price : GAS_PRICE
  @gas_limit    = gas_limit >= 0 ? gas_limit : GAS_LIMIT
  @data         = parse_contract(contract)
  @timestamp    = Time.now.to_i

  validate_args!
end

Instance Attribute Details

#chain_idObject (readonly)

Returns the value of attribute chain_id.



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

def chain_id
  @chain_id
end

#dataObject (readonly)

Returns the value of attribute data.



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

def data
  @data
end

#from_accountObject (readonly)

Returns the value of attribute from_account.



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

def 
  @from_account
end

#gas_limitObject (readonly)

Returns the value of attribute gas_limit.



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

def gas_limit
  @gas_limit
end

#gas_priceObject (readonly)

Returns the value of attribute gas_price.



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

def gas_price
  @gas_price
end

#hashObject (readonly)

Returns the value of attribute hash.



24
25
26
# File 'lib/neb/transaction.rb', line 24

def hash
  @hash
end

#nonceObject (readonly)

Returns the value of attribute nonce.



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

def nonce
  @nonce
end

#signObject (readonly)

Returns the value of attribute sign.



24
25
26
# File 'lib/neb/transaction.rb', line 24

def sign
  @sign
end

#timestampObject (readonly)

Returns the value of attribute timestamp.



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

def timestamp
  @timestamp
end

#to_addressObject (readonly)

Returns the value of attribute to_address.



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

def to_address
  @to_address
end

#valueObject (readonly)

Returns the value of attribute value.



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

def value
  @value
end

Instance Method Details

#calculate_hashObject



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/neb/transaction.rb', line 100

def calculate_hash
  buffer = [
    .address_obj.encode(:bin_extended),
    to_address.encode(:bin_extended),
    Utils.zpad(Utils.int_to_big_endian(value), 16),
    Utils.zpad(Utils.int_to_big_endian(nonce), 8),
    Utils.zpad(Utils.int_to_big_endian(timestamp), 8),
    Corepb::Data.new(data).to_proto,
    Utils.zpad(Utils.int_to_big_endian(chain_id), 4),
    Utils.zpad(Utils.int_to_big_endian(gas_price), 16),
    Utils.zpad(Utils.int_to_big_endian(gas_limit), 16)
  ].join

  Utils.keccak256(buffer)
end

#parse_contract(contract) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/neb/transaction.rb', line 41

def parse_contract(contract)
  payload_type, payload = nil, nil
  contract.deep_symbolize_keys!

  if contract[:source].present?
    payload_type = PAYLOAD_DEPLOY_TYPE
    payload = {
      source_type: contract[:source_type],
      source: contract[:source],
      args: contract[:args]
    }
  elsif contract[:function].present?
    payload_type = PAYLOAD_CALL_TYPE
    payload = {
      function: contract[:function],
      args: contract[:args]
    }
  else
    payload_type = PAYLOAD_BINARY_TYPE
    if contract.present?
      payload = {
        data: BaseConvert.decode(contract[:binary], 256)
      }
    end
  end

  if payload.present?
    payload = String.new(JSON.dump(payload.deep_camelize_keys(:upper)).html_safe)
    { type: payload_type, payload: payload }
  else
    { type: payload_type }
  end
end

#sign_hashObject



116
117
118
119
# File 'lib/neb/transaction.rb', line 116

def sign_hash
  @hash = calculate_hash
  @sign = Secp256k1.sign(@hash, .private_key)
end

#to_protoObject

Raises:



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/neb/transaction.rb', line 75

def to_proto
  raise UnsignError.new("Must sign_hash first") if sign.blank?

  tx = Corepb::Transaction.new(
    hash:      hash,
    from:      .address_obj.encode(:bin_extended),
    to:        to_address.encode(:bin_extended),
    value:     Utils.zpad(Utils.int_to_big_endian(value), 16),
    nonce:     nonce,
    timestamp: timestamp,
    data:      Corepb::Data.new(data),
    chain_id:  chain_id,
    gas_price: Utils.zpad(Utils.int_to_big_endian(gas_price), 16),
    gas_limit: Utils.zpad(Utils.int_to_big_endian(gas_limit), 16),
    alg:       Secp256k1::SECP256K1,
    sign:      sign
  )

  tx.to_proto
end

#to_proto_strObject



96
97
98
# File 'lib/neb/transaction.rb', line 96

def to_proto_str
  Utils.encode64(to_proto)
end