File Coverage

blib/lib/Blockchain/Ethereum/Transaction.pm
Criterion Covered Total %
statement 64 65 98.4
branch 12 14 85.7
condition 14 22 63.6
subroutine 26 27 96.3
pod 3 17 17.6
total 119 145 82.0


line stmt bran cond sub pod time code
1             package Blockchain::Ethereum::Transaction;
2              
3 10     10   242986 use v5.26;
  10         44  
4 10     10   76 use strict;
  10         29  
  10         408  
5 10     10   50 use warnings;
  10         21  
  10         881  
6              
7             # ABSTRACT: Ethereum transaction abstraction
8             our $AUTHORITY = 'cpan:REFECO'; # AUTHORITY
9             our $VERSION = '0.021'; # VERSION
10              
11 10     10   145 use Carp;
  10         27  
  10         1062  
12 10     10   5186 use Crypt::Digest::Keccak256 qw(keccak256);
  10         65658  
  10         867  
13 10     10   83 use Scalar::Util qw(blessed looks_like_number);
  10         19  
  10         538  
14 10     10   16264 use Math::BigInt;
  10         482287  
  10         56  
15              
16 10     10   293639 use Blockchain::Ethereum::RLP;
  10         30  
  10         8162  
17              
18             sub new {
19 13     13 0 96 my ($class, %args) = @_;
20              
21 13         45 my $self = bless {}, $class;
22              
23 13         46 foreach (qw(chain_id nonce gas_limit to value data v r s)) {
24 117 100       448 $self->{$_} = $args{$_} if exists $args{$_};
25             }
26              
27 13         67 return $self;
28             }
29              
30             sub rlp {
31 20     20 0 37 my $self = shift;
32              
33 20   66     146 return $self->{rlp} //= Blockchain::Ethereum::RLP->new;
34             }
35              
36             sub chain_id {
37 20     20 0 120 return shift->{chain_id};
38             }
39              
40             sub nonce {
41 20     20 0 104 return shift->{nonce};
42             }
43              
44             sub gas_limit {
45 20     20 0 68 return shift->{gas_limit};
46             }
47              
48             sub to {
49 20   100 20 0 95 return shift->{to} // '';
50             }
51              
52             sub value {
53 20   50 20 0 124 return shift->{value} // '0x0';
54             }
55              
56             sub data {
57 20   100 20 0 127 return shift->{data} // '';
58             }
59              
60             sub v {
61 30     30 0 131 return shift->{v};
62             }
63              
64             sub set_v {
65 8     8 0 19 my ($self, $v) = @_;
66 8         28 $self->{v} = $v;
67             }
68              
69             sub r {
70 20     20 0 82 return shift->{r};
71             }
72              
73             sub set_r {
74 8     8 0 23 my ($self, $r) = @_;
75 8         44 $self->{r} = $r;
76             }
77              
78             sub s {
79 20     20 0 33 my $self = shift;
80 20         115 return $self->{s};
81             }
82              
83             sub set_s {
84 8     8 0 21 my ($self, $s) = @_;
85 8         25 $self->{s} = $s;
86             }
87              
88             sub serialize {
89 0     0 1 0 croak "serialize method not implemented";
90             }
91              
92             sub hash {
93 10     10 1 1626 my $self = shift;
94              
95 10         41 return keccak256($self->serialize);
96             }
97              
98             # Hex conversion
99             sub _normalize_params {
100 20     20   50 my ($self, $params) = @_;
101              
102             return [
103             map {
104 20 50 66     59 !defined $_
  182 100 66     6106  
    100 33        
    100          
    50          
105             ? $_ # undefined
106             : blessed $_ && $_->isa('Math::BigInt') ? $_->as_hex # BigInt
107             : /^0x/i ? $_ # hex string
108             : looks_like_number($_) && $_ == int($_) ? Math::BigInt->new($_)->as_hex # integer/numeric string
109             : blessed $_ && $_->isa('Blockchain::Ethereum::Address') ? $_->to_string # Ethereum Address object
110             : $_ # anything else
111             } @$params
112             ];
113             }
114              
115             sub _encode_access_list {
116 21     21   59 my $self = shift;
117              
118 21         90 my $access_list = $self->access_list();
119              
120             # If no access list, return empty array
121 21 100       97 return [] unless @$access_list;
122              
123 9         19 my @encoded_list;
124              
125 9         29 for my $entry (@$access_list) {
126 13   50     37 my $address = $entry->{address} // '';
127 13   50     37 my $storage_keys = $entry->{storage_keys} // [];
128              
129 13         51 push @encoded_list, [$address, $storage_keys];
130             }
131              
132 9         31 return \@encoded_list;
133             }
134              
135             sub generate_v {
136 7     7 1 35 my ($self, $y_parity) = @_;
137              
138             # eip-1559 and eip-2930 uses y-parity directly as the v value
139 7         46 my $v = sprintf("0x%x", $y_parity);
140 7         35 $self->set_v($v);
141 7         14 return $v;
142             }
143              
144             1;
145              
146             __END__