class Neb::Transaction

Constants

CHAIN_ID_LIST
GAS_LIMIT
GAS_PRICE
MAX_GAS
MAX_GAS_PRICE
PAYLOAD_BINARY_TYPE
PAYLOAD_CALL_TYPE
PAYLOAD_DEPLOY_TYPE

Attributes

chain_id[R]
data[R]
from_account[R]
gas_limit[R]
gas_price[R]
hash[R]
nonce[R]
sign[R]
timestamp[R]
to_address[R]
value[R]

Public Class Methods

new(chain_id:, from_account:, to_address:, value:, nonce:, gas_price: GAS_PRICE, gas_limit: GAS_LIMIT, contract: {}) click to toggle source
# 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 = 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

Public Instance Methods

calculate_hash() click to toggle source
# File lib/neb/transaction.rb, line 100
def calculate_hash
  buffer = [
    from_account.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) click to toggle source
# 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_hash() click to toggle source
# File lib/neb/transaction.rb, line 116
def sign_hash
  @hash = calculate_hash
  @sign = Secp256k1.sign(@hash, from_account.private_key)
end
to_proto() click to toggle source
# 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:      from_account.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_str() click to toggle source
# File lib/neb/transaction.rb, line 96
def to_proto_str
  Utils.encode64(to_proto)
end

Private Instance Methods

validate_args!() click to toggle source
# File lib/neb/transaction.rb, line 123
def validate_args!
  if !CHAIN_ID_LIST.keys.include?(chain_id) || value < 0 || nonce < 0
    raise InvalidTransaction
  end
end