abiparser 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 77899a7da00b8be7b61c97d2f1ebad297a6d33f74bd081c59b17f8b66bca78f1
4
+ data.tar.gz: 15a102dc8505eb359fcb5d117de026e9308641e714ea50096895ee15fb4d655e
5
+ SHA512:
6
+ metadata.gz: 2bf5a3d5928df6f9d5a650f50ca05df22edb82f0d305a5ef66c552b36fee9b33d6166b63dfd4e878c8a32f7a86e042517159cc6b0155cf96734b36a0ab596817
7
+ data.tar.gz: 8181ddd11ad89481204f1796ef4eebc854d10ec83fb8cd6d3fd45ce8da830cff2fd1273c726c507853843442c174c603bd66fcb735ae4aabf433141827befebb
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.0.1 / 2022-12-26
2
+
3
+ * Everything is new. First release
data/Manifest.txt ADDED
@@ -0,0 +1,11 @@
1
+ CHANGELOG.md
2
+ Manifest.txt
3
+ README.md
4
+ Rakefile
5
+ lib/abiparser.rb
6
+ lib/abiparser/constructor.rb
7
+ lib/abiparser/contract.rb
8
+ lib/abiparser/export/interface.rb
9
+ lib/abiparser/function.rb
10
+ lib/abiparser/param.rb
11
+ lib/abiparser/version.rb
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # Application Binary Inteface (ABI) Parser For Ethereum & Co.
2
+
3
+ abiparser - application binary interface (abi) parser machinery / helper for Ethereum & Co. (blockchain) contracts
4
+
5
+
6
+ * home :: [github.com/rubycocos/blockchain](https://github.com/rubycocos/blockchain)
7
+ * bugs :: [github.com/rubycocos/blockchain/issues](https://github.com/rubycocos/blockchain/issues)
8
+ * gem :: [rubygems.org/gems/abiparser](https://rubygems.org/gems/abiparser)
9
+ * rdoc :: [rubydoc.info/gems/abiparser](http://rubydoc.info/gems/abiparser)
10
+
11
+
12
+
13
+ ## Usage
14
+
15
+
16
+
17
+
18
+ ## License
19
+
20
+ The scripts are dedicated to the public domain.
21
+ Use it as you please with no restrictions whatsoever.
22
+
23
+
24
+ ## Questions? Comments?
25
+
26
+
27
+ Post them on the [D.I.Y. Punk (Pixel) Art reddit](https://old.reddit.com/r/DIYPunkArt). Thanks.
28
+
29
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'hoe'
2
+ require './lib/abiparser/version.rb'
3
+
4
+
5
+ Hoe.spec 'abiparser' do
6
+
7
+ self.version = ABIParser::VERSION
8
+
9
+ self.summary = "abiparser - application binary interface (abi) parser machinery / helper for Ethereum & Co. (blockchain) contracts"
10
+ self.description = summary
11
+
12
+ self.urls = { home: 'https://github.com/rubycocos/blockchain' }
13
+
14
+ self.author = 'Gerald Bauer'
15
+ self.email = 'wwwmake@googlegroups.com'
16
+
17
+ # switch extension to .markdown for gihub formatting
18
+ self.readme_file = 'README.md'
19
+ self.history_file = 'CHANGELOG.md'
20
+
21
+ self.extra_deps = [
22
+ ['cocos'],
23
+ ['bytes'],
24
+ ['digest-lite'],
25
+ ]
26
+
27
+ self.licenses = ['Public Domain']
28
+
29
+ self.spec_extras = {
30
+ required_ruby_version: '>= 2.3'
31
+ }
32
+
33
+ end
34
+
@@ -0,0 +1,109 @@
1
+ module ABI
2
+ class Constructor
3
+
4
+ def self.parse( o )
5
+ ## note:
6
+ ## - has no name
7
+ ## - has no ouptputs
8
+ ## e.g.
9
+ ## {"inputs":[],
10
+ ## "stateMutability":"nonpayable",
11
+ ## "type":"constructor"}
12
+
13
+ inputs = o['inputs'].map {|param| Param.parse( param ) }
14
+ payable = nil
15
+
16
+ ## old soliditity before v0.6
17
+ ## newer version uses stateMutability
18
+ if o.has_key?( 'stateMutability' )
19
+ case o[ 'stateMutability' ]
20
+ when 'nonpayable' ## default
21
+ payable = false
22
+ when 'payable'
23
+ payable = true
24
+ else
25
+ pp o
26
+ ## todo/fix: change to ParseError
27
+ raise ArgumentError, "unexpected stateMutability (constructor) value ; got: #{ o[ 'stateMutability' ]}"
28
+ end
29
+ end
30
+
31
+ ## check - assert "strict" abi version keys - why? why not?
32
+ if o.has_key?( 'stateMutability' ) && (o.has_key?( 'payable') || o.has_key?( 'constant'))
33
+ pp o
34
+ puts "!! WARN: ABI version mismatch? got stateMutability AND payable OR constant"
35
+ exit 1
36
+ end
37
+
38
+ if o.has_key?( 'constant')
39
+ pp o
40
+ puts "!! WARN: constant for constructor possible?"
41
+ exit 1
42
+ end
43
+
44
+ payable = o['payable'] if o.has_key?( 'payable')
45
+
46
+ new( inputs: inputs, payable: payable )
47
+ end
48
+
49
+
50
+ attr_reader :inputs
51
+
52
+ def initialize( inputs: [],
53
+ payable: false )
54
+ @inputs = inputs
55
+ @payable = payable
56
+ end
57
+
58
+ ## add - why? why not?
59
+ ## def constant?() false; end
60
+ ## alias_method :readonly?, :constant?
61
+
62
+ def payable?() @payable; end
63
+
64
+ def sig
65
+ ## note: signature
66
+ ## only includes name and inputs
67
+ ## excludes / drops outputs!!!
68
+
69
+ buf = "constructor"
70
+ if @inputs.empty?
71
+ buf << "()"
72
+ else
73
+ buf2 = @inputs.map {|param| param.sig }
74
+ buf << "(#{buf2.join(',')})"
75
+ end
76
+ buf
77
+ end
78
+
79
+
80
+ def doc
81
+ buf = "constructor"
82
+ if @inputs.empty?
83
+ buf << "()"
84
+ else
85
+ buf2 = @inputs.map {|param| param.doc }
86
+ buf << "(#{buf2.join(', ')})"
87
+ end
88
+ buf
89
+ end
90
+
91
+ def decl
92
+ buf = "constructor"
93
+ if @inputs.empty?
94
+ buf << "()"
95
+ else
96
+ buf2 = @inputs.map {|param| param.decl }
97
+ buf << "(#{buf2.join(', ')})"
98
+ end
99
+ buf << ";"
100
+ buf
101
+ end
102
+
103
+
104
+
105
+
106
+ end # class Constructor
107
+ end # module ABI
108
+
109
+
@@ -0,0 +1,91 @@
1
+ module ABI
2
+ class Contract
3
+
4
+ def self.read( path )
5
+ data = read_json( path )
6
+ ## pp data
7
+ parse( data )
8
+ end
9
+
10
+ def self.parse( data )
11
+ ## note: auto-convert (parse) from json if string passed-in
12
+ data = JSON.parse( data ) if data.is_a?( String )
13
+
14
+ ctor = nil
15
+ funcs = []
16
+ has_fallback = false
17
+ has_receive = true
18
+
19
+ data.each do |o|
20
+ if o['type'] == 'function'
21
+ funcs << Function.parse( o )
22
+ elsif o['type'] == 'constructor'
23
+ raise ArgumentError, "constructor already defined; only one declaration allowed" if ctor
24
+ ctor = Constructor.parse( o )
25
+ elsif o['type'] == 'event'
26
+ elsif o['type'] == 'receive'
27
+ ## skip for now
28
+ ## e.g.
29
+ ## {"stateMutability": "payable",
30
+ ## "type": "receive"}
31
+ elsif o['type'] == 'fallback'
32
+ ## skip for now
33
+ ## e.g.
34
+ ## {"stateMutability"=>"nonpayable",
35
+ ## "type"=>"fallback"}
36
+ elsif o['type'] == 'error'
37
+ ## skip for now
38
+ ## e.g.
39
+ ## {"inputs":[],
40
+ ## "name":"ApprovalCallerNotOwnerNorApproved",
41
+ ## "type":"error"}
42
+ else
43
+ pp o
44
+ raise TypeError, "expected function or event; sorry: got #{o['type']}"
45
+ end
46
+ end
47
+ new( constructor: ctor,
48
+ functions: funcs,
49
+ events: [],
50
+ has_receive: has_receive,
51
+ has_fallback: has_fallback )
52
+ end
53
+
54
+
55
+
56
+ def initialize( constructor: nil,
57
+ functions: [],
58
+ events: [],
59
+ has_receive: false,
60
+ has_fallback: false )
61
+ @ctor = constructor
62
+ @funcs = functions
63
+ @events = events
64
+ @has_receive = has_receive
65
+ @has_fallback = has_fallback
66
+ end
67
+
68
+ def constructor() @ctor; end
69
+ def functions() @funcs; end
70
+
71
+ ###
72
+ ## how to name functions categories ???
73
+ ## - use pay, writer, reader, helper - why? why not?
74
+ def payable_functions
75
+ @funcs.select { |func| func.payable? }
76
+ end
77
+
78
+ def transact_functions ## add write funcs alias - why? why not?
79
+ @funcs.select { |func| !func.payable? && !func.constant? }
80
+ end
81
+
82
+ def query_functions ## add read funcs alias - why? why not?
83
+ @funcs.select { |func| !func.payable? && !func.pure? && func.constant? }
84
+ end
85
+
86
+ def helper_functions ## add pure ?? funcs alias - why? why not?
87
+ @funcs.select { |func| func.pure? }
88
+ end
89
+
90
+ end # class Contract
91
+ end # module ABI
@@ -0,0 +1,53 @@
1
+ module ABI
2
+ class Contract
3
+
4
+
5
+ def generate_interface( name: ) ## interface declarations
6
+ buf = ''
7
+ buf << "interface #{name} {"
8
+
9
+ if @ctor
10
+ buf << "\n"
11
+ buf << "// Constructor\n"
12
+ buf << "#{@ctor.decl}\n"
13
+ end
14
+
15
+ if payable_functions.size > 0
16
+ buf << "\n"
17
+ buf << "// #{payable_functions.size} Payable Function(s)\n"
18
+ payable_functions.each do |func|
19
+ buf << "#{func.decl}\n"
20
+ end
21
+ end
22
+
23
+ if transact_functions.size > 0
24
+ buf << "\n"
25
+ buf << "// #{transact_functions.size} Transact Functions(s)\n"
26
+ transact_functions.each do |func|
27
+ buf << "#{func.decl}\n"
28
+ end
29
+ end
30
+
31
+ if query_functions.size > 0
32
+ buf << "\n"
33
+ buf << "// #{query_functions.size} Query Functions(s)\n"
34
+ query_functions.each do |func|
35
+ buf << "#{func.decl}\n"
36
+ end
37
+ end
38
+
39
+ if helper_functions.size > 0
40
+ buf << "\n"
41
+ buf << "// #{helper_functions.size} Helper Functions(s)\n\n"
42
+ helper_functions.each do |func|
43
+ buf << "#{func.decl}\n"
44
+ end
45
+ end
46
+
47
+ buf << "}\n"
48
+ buf
49
+ end
50
+
51
+
52
+ end ## class Contract
53
+ end ## module ABI
@@ -0,0 +1,148 @@
1
+ module ABI
2
+ class Function
3
+
4
+ def self.parse( o )
5
+ ## todo/fix: assert type function (or contructor) ??
6
+ name = o['name']
7
+ inputs = o['inputs'].map {|param| Param.parse( param ) }
8
+ outputs = o['outputs'].map {|param| Param.parse( param ) }
9
+
10
+ payable = nil
11
+ contant = nil
12
+ pure = nil
13
+
14
+ ## old soliditity before v0.6
15
+ ## newer version uses stateMutability
16
+ if o.has_key?( 'stateMutability' )
17
+ case o[ 'stateMutability' ]
18
+ when 'nonpayable' ## default
19
+ payable = false
20
+ constant = false
21
+ when 'payable'
22
+ payable = true
23
+ constant = false
24
+ when 'view'
25
+ payable = false
26
+ constant = true
27
+ when 'pure'
28
+ payable = false
29
+ constant = true
30
+ pure = true
31
+ else
32
+ pp o
33
+ ## todo/fix: change to ParseError
34
+ raise ArgumentError, "unexpected stateMutability value; got: #{ o[ 'stateMutability' ]}"
35
+ end
36
+ end
37
+
38
+ ## check - assert "strict" abi version keys - why? why not?
39
+ if o.has_key?( 'stateMutability' ) && (o.has_key?( 'payable') || o.has_key?( 'constant'))
40
+ pp o
41
+ puts "!! WARN: ABI version mismatch? got stateMutability AND payable OR constant"
42
+ exit 1
43
+ end
44
+
45
+ payable = o['payable'] if o.has_key?( 'payable')
46
+ constant = o['constant'] if o.has_key?( 'constant')
47
+
48
+
49
+ new( name, inputs: inputs, outputs: outputs,
50
+ payable: payable,
51
+ constant: constant,
52
+ pure: pure )
53
+ end
54
+
55
+
56
+ attr_reader :name,
57
+ :inputs, :outputs
58
+
59
+ def initialize( name,
60
+ inputs: [],
61
+ outputs: [],
62
+ payable: false,
63
+ constant: false,
64
+ pure: false )
65
+ @name = name
66
+ @inputs = inputs
67
+ @outputs = outputs
68
+
69
+ @payable = payable
70
+ @constant = constant
71
+ @pure = pure
72
+ end
73
+
74
+
75
+ def constant?() @constant; end
76
+ alias_method :readonly?, :constant?
77
+
78
+ def payable?() @payable; end
79
+ def pure?() @pure; end
80
+
81
+
82
+ def sig
83
+ ## note: signature
84
+ ## only includes name and inputs
85
+ ## excludes / drops outputs!!!
86
+
87
+ buf = "#{@name}"
88
+ if @inputs.empty?
89
+ buf << "()"
90
+ else
91
+ buf2 = @inputs.map {|param| param.sig }
92
+ buf << "(#{buf2.join(',')})"
93
+ end
94
+ buf
95
+ end
96
+
97
+
98
+ def doc
99
+ buf = "function #{@name}"
100
+ if @inputs.empty?
101
+ buf << "()"
102
+ else
103
+ buf2 = @inputs.map {|param| param.doc }
104
+ buf << "(#{buf2.join(', ')})"
105
+ end
106
+ if @outputs.empty?
107
+ ## do nothing
108
+ else
109
+ buf << " ⇒ "
110
+ buf2 = @outputs.map {|param| param.doc }
111
+ buf << "(#{buf2.join(', ')})"
112
+ end
113
+ buf
114
+ end
115
+
116
+ def decl
117
+ buf = "function #{@name}"
118
+ if @inputs.empty?
119
+ buf << "()"
120
+ else
121
+ buf2 = @inputs.map {|param| param.decl }
122
+ buf << "(#{buf2.join(', ')})"
123
+ end
124
+ buf << " payable " if @payable
125
+ buf << " view " if @constant && !@pure
126
+ buf << " pure " if @constant && @pure
127
+
128
+ if @outputs.empty?
129
+ ## do nothing
130
+ else
131
+ buf << " returns "
132
+ buf2 = @outputs.map {|param| param.decl }
133
+ buf << "(#{buf2.join(', ')})"
134
+ end
135
+ buf << ";"
136
+ buf
137
+ end
138
+
139
+
140
+ def types
141
+ ## for debugging / analytics return all used types (input+output)
142
+ @inputs.map {|param| param.type } +
143
+ @outputs.map {|param| param.type }
144
+ end
145
+
146
+ end ## class Function
147
+ end ## module ABI
148
+
@@ -0,0 +1,36 @@
1
+ module ABI
2
+ class Param
3
+
4
+ attr_reader :type, :name
5
+
6
+ def self.parse( o )
7
+ type = o['type']
8
+ name = o['name']
9
+ new( type, name )
10
+ end
11
+
12
+ def initialize( type, name ) ## note: type goes first!!!
13
+ @type = type
14
+ @name = name
15
+ end
16
+
17
+ def sig
18
+ buf = "#{@type}"
19
+ buf
20
+ end
21
+
22
+ def doc
23
+ buf = ''
24
+ buf << "#{@type} "
25
+ buf << (@name.empty? ? '_' : @name)
26
+ buf
27
+ end
28
+
29
+ def decl
30
+ buf = ''
31
+ buf << "#{@type} "
32
+ buf << (@name.empty? ? '_' : @name)
33
+ buf
34
+ end
35
+ end ## class Param
36
+ end ## module ABI
@@ -0,0 +1,25 @@
1
+
2
+ module ABIParser
3
+
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ PATCH = 1
7
+ VERSION = [MAJOR,MINOR,PATCH].join('.')
8
+
9
+ def self.version
10
+ VERSION
11
+ end
12
+
13
+ def self.banner
14
+ "abiparser/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
15
+ end
16
+
17
+ def self.root
18
+ File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
19
+ end
20
+
21
+ end # module ABIParser
22
+
23
+ ## add convenience alternate spellings - why? why not?
24
+ AbiParser = ABIParser
25
+
data/lib/abiparser.rb ADDED
@@ -0,0 +1,45 @@
1
+ require 'cocos'
2
+ require 'bytes'
3
+ require 'digest-lite'
4
+
5
+
6
+ ## extend String
7
+ class String
8
+ alias_method :hexdigest, :bin_to_hex ## note: bin_to_hex added via Bytes!!!
9
+ end # class String
10
+
11
+
12
+ def keccak256( bin )
13
+ Digest::KeccakLite.new( 256 ).digest( bin )
14
+ end
15
+
16
+ def sig( bin )
17
+ keccak256( bin )[0,4]
18
+ end
19
+
20
+
21
+
22
+ ## our own code
23
+ require_relative 'abiparser/version' # note: let version always go first
24
+ require_relative 'abiparser/param'
25
+ require_relative 'abiparser/constructor'
26
+ require_relative 'abiparser/function'
27
+ require_relative 'abiparser/contract'
28
+
29
+ require_relative 'abiparser/export/interface.rb'
30
+
31
+
32
+
33
+ module ABI
34
+ def self.read( path ) Contract.read( path ); end
35
+
36
+ def self.parse( data ) Contract.parse( data ); end
37
+ end # module ABI
38
+
39
+
40
+ ## add convenience alternate spellings - why? why not?
41
+ Abi = ABI
42
+
43
+
44
+ puts AbiParser.banner
45
+
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: abiparser
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Gerald Bauer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-12-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cocos
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bytes
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: digest-lite
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rdoc
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '7'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '4.0'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '7'
75
+ - !ruby/object:Gem::Dependency
76
+ name: hoe
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '3.23'
82
+ type: :development
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '3.23'
89
+ description: abiparser - application binary interface (abi) parser machinery / helper
90
+ for Ethereum & Co. (blockchain) contracts
91
+ email: wwwmake@googlegroups.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files:
95
+ - CHANGELOG.md
96
+ - Manifest.txt
97
+ - README.md
98
+ files:
99
+ - CHANGELOG.md
100
+ - Manifest.txt
101
+ - README.md
102
+ - Rakefile
103
+ - lib/abiparser.rb
104
+ - lib/abiparser/constructor.rb
105
+ - lib/abiparser/contract.rb
106
+ - lib/abiparser/export/interface.rb
107
+ - lib/abiparser/function.rb
108
+ - lib/abiparser/param.rb
109
+ - lib/abiparser/version.rb
110
+ homepage: https://github.com/rubycocos/blockchain
111
+ licenses:
112
+ - Public Domain
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options:
116
+ - "--main"
117
+ - README.md
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '2.3'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubygems_version: 3.3.7
132
+ signing_key:
133
+ specification_version: 4
134
+ summary: abiparser - application binary interface (abi) parser machinery / helper
135
+ for Ethereum & Co. (blockchain) contracts
136
+ test_files: []