File Coverage

blib/lib/Blockchain/Contract/Solidity/ABI/Encoder.pm
Criterion Covered Total %
statement 56 56 100.0
branch 2 4 50.0
condition 3 5 60.0
subroutine 17 17 100.0
pod 5 7 71.4
total 83 89 93.2


line stmt bran cond sub pod time code
1             package Blockchain::Contract::Solidity::ABI::Encoder;
2              
3 4     4   267928 use v5.26;
  4         43  
4 4     4   31 use strict;
  4         10  
  4         80  
5 4     4   31 use warnings;
  4         18  
  4         125  
6 4     4   1908 no indirect;
  4         4388  
  4         35  
7              
8 4     4   222 use Carp;
  4         9  
  4         286  
9 4     4   1640 use Digest::Keccak qw(keccak_256_hex);
  4         5551  
  4         283  
10              
11 4     4   1773 use Blockchain::Contract::Solidity::ABI::Type;
  4         13  
  4         175  
12 4     4   1849 use Blockchain::Contract::Solidity::ABI::Type::Tuple;
  4         13  
  4         2657  
13              
14             sub new {
15 4     4 0 1850 my ($class, %params) = @_;
16              
17 4         14 my $self = {};
18 4         12 bless $self, $class;
19 4         15 return $self;
20             }
21              
22             sub _instances {
23 50     50   94 my $self = shift;
24 50   100     299 return $self->{instances} //= [];
25             }
26              
27             sub function_name {
28 24     24 0 37 my $self = shift;
29 24         85 return $self->{function_name};
30             }
31              
32             sub append {
33 28     28 1 6323 my ($self, %param) = @_;
34              
35 28         99 for my $type_signature (keys %param) {
36             push(
37             $self->_instances->@*,
38             Blockchain::Contract::Solidity::ABI::Type::new_type(
39             signature => $type_signature,
40 28         78 data => $param{$type_signature}));
41             }
42              
43 27         150 return $self;
44             }
45              
46             sub function {
47 8     8 1 16757 my ($self, $function_name) = @_;
48 8         33 $self->{function_name} = $function_name;
49 8         50 return $self;
50             }
51              
52             sub generate_function_signature {
53 8     8 1 20 my $self = shift;
54 8 50       20 croak "Missing function name e.g. ->function('name')" unless $self->function_name;
55 8         24 my $signature = $self->function_name . '(';
56 8         26 $signature .= sprintf("%s,", $_->signature) for $self->_instances->@*;
57 8         24 chop $signature;
58 8         125 return $signature . ')';
59             }
60              
61             sub encode_function_signature {
62 8     8 1 22 my ($self, $signature) = @_;
63 8   33     36 return sprintf("0x%.8s", keccak_256_hex($signature // $self->generate_function_signature));
64             }
65              
66             sub encode {
67 14     14 1 34 my $self = shift;
68              
69 14         66 my $tuple = Blockchain::Contract::Solidity::ABI::Type::Tuple->new;
70 14         41 $tuple->{instances} = $self->_instances;
71 14         48 my @data = $tuple->encode->@*;
72 8 50       31 unshift @data, $self->encode_function_signature if $self->function_name;
73              
74 8         35 $self->_clean;
75              
76 8         264 return join('', @data);
77             }
78              
79             sub _clean {
80 15     15   5544 my $self = shift;
81 15         69 delete $self->{instances};
82 15         47 undef $self->{function_name};
83             }
84              
85             1;
86              
87             __END__
88              
89             =pod
90              
91             =encoding UTF-8
92              
93             =head1 NAME
94              
95             Blockchain::Contract::Solidity::ABI::Encoder - Contract ABI argument encoder
96              
97             =head1 SYNOPSIS
98              
99             Allows you to encode contract ABI arguments
100              
101             my $encoder = Blockchain::Contract::Solidity::ABI::Encoder->new();
102             $encoder->function('test')
103             # string
104             ->append(string => 'Hello, World!')
105             # bytes
106             ->append(bytes => unpack("H*", 'Hello, World!'))
107             # tuple
108             ->append('(uint256,address)' => [75000000000000, '0x0000000000000000000000000000000000000000'])
109             # arrays
110             ->append('bool[]', [1, 0, 1, 0])
111             # multidimensional arrays
112             ->append('uint256[][][2]', [[[1]], [[2]]])
113             # tuples arrays and tuples inside tuples
114             ->append('((int256)[2])' => [[[1], [2]]])->encode();
115             ...
116              
117             =head1 METHODS
118              
119             =head2 append
120              
121             Appends type signature and the respective values to the encoder.
122              
123             Usage:
124              
125             append(signature => value) -> L<Blockchain::Contract::Solidity::ABI::Encoder>
126              
127             =over 4
128              
129             =item * C<%param> key is the respective type signature followed by the value e.g. uint256 => 10
130              
131             =back
132              
133             Returns C<$self>
134              
135             =head2 function
136              
137             Appends the function name to the encoder, this is optional for when you want the
138             function signature added to the encoded string or only the function name encoded.
139              
140             Usage:
141              
142             function(string) -> L<Blockchain::Contract::Solidity::ABI::Encoder>
143              
144             =over 4
145              
146             =item * C<$function_name> solidity function name e.g. for `transfer(address,uint256)` will be `transfer`
147              
148             =back
149              
150             Returns C<$self>
151              
152             =head2 generate_function_signature
153              
154             Based on the given function name and type signatures create the complete function
155             signature.
156              
157             Usage:
158              
159             generate_function_signature() -> string
160              
161             =over 4
162              
163             =back
164              
165             Returns the function signature string
166              
167             =head2 encode_function_signature
168              
169             Encode function signature keccak_256/sha3
170              
171             Usage:
172              
173             encode_function_signature('transfer(address,uint)') -> encoded string
174              
175             =over 4
176              
177             =item * C<$signature> (Optional) function signature, if not given, will try to use the appended function name
178              
179             =back
180              
181             Returns the encoded string 0x prefixed
182              
183             =head2 encode
184              
185             Encodes appended signatures and the function name (when given)
186              
187             Usage:
188              
189             encode() -> encoded string
190              
191             =over 4
192              
193             =back
194              
195             Returns the encoded string, if function name was given will be 0x prefixed
196              
197             =head1 AUTHOR
198              
199             Reginaldo Costa, C<< <refeco at cpan.org> >>
200              
201             =head1 BUGS
202              
203             Please report any bugs or feature requests to L<https://github.com/refeco/perl-ABI>
204              
205             =head1 SUPPORT
206              
207             You can find documentation for this module with the perldoc command.
208              
209             perldoc Blockchain::Contract::Solidity::ABI::Encoder
210              
211             =head1 LICENSE AND COPYRIGHT
212              
213             This software is Copyright (c) 2022 by REFECO.
214              
215             This is free software, licensed under:
216              
217             The MIT License
218              
219             =cut