abigen 0.0.1 → 0.1.0

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.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +211 -1
  3. data/Rakefile +9 -1
  4. data/lib/abigen.rb +44 -14
  5. metadata +16 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2af88adfb037b066adbcdb376f41d9c7b22f90ac72832ed0804b6f14de2964e3
4
- data.tar.gz: f95aee9a46c98b9896d9c9c09587ddfe55b1ac1b81d4e6d1a9905b07b5e5d9a5
3
+ metadata.gz: 961de95760c3dc2b5b3f6c6eafc2e95bd10848a4d3a395256e85038dec22638e
4
+ data.tar.gz: 4bfc9edef80e2ffc854a9f81a9dae1a59d40554e5e44983cff827a74734dba07
5
5
  SHA512:
6
- metadata.gz: 3395ab689b6efc2b354287940f376567c5b7c0e34e6693662931150a7c19da0768c377ab1187a82563a5d33f667c1684d4aedc720b9a7da0fdfed484a5b33097
7
- data.tar.gz: 470b580d57671302f73b10abaebf83e1519096c6e93d4843626160a30b4dd268ad4f45c8ff5f9e895eb48f9973955e72ced6b434745e7027a0bc884f9bb0626f
6
+ metadata.gz: 9c9e9d95d7f029bb08cf58c93ff0c2fd7b7b1a0808086283b090484ae4fc182c81ca0cba26b1a9c78a294eb84f019d9a6f23022eb0b36b1ef78dd88617b5877b
7
+ data.tar.gz: c4535d75a502ea5a8a425328008bc1552e156dd33470546bb21c392ec5661f5fd3138574ad9c5e88c5cccb028899a4723a77470d39050e70aa638b9b8f9fdb73
data/README.md CHANGED
@@ -12,7 +12,217 @@ abigen - generate ready-to-use (blockchain) contract services / function calls f
12
12
 
13
13
  ## Usage
14
14
 
15
- To be done
15
+ Let's try to generate the contract "wrapper" code in ruby
16
+ from the application binary interface (abi) in json
17
+ for punk blocks (anno 2020) - plus let's add the optional "natspec" comments:
18
+
19
+ ``` ruby
20
+ require 'abigen'
21
+
22
+ punk_blocks = '0x58e90596c2065befd3060767736c829c18f3474c'
23
+
24
+ abi = ABI.read( "./abis/#{punk_blocks}.json" )
25
+ natspec = Natspec.read( "./abis/#{punk_blocks}.md" )
26
+
27
+ buf = abi.generate_code( name: 'PunkBlocks',
28
+ address: punk_blocks,
29
+ natspec: natspec )
30
+ write_text( "./punk_blocks.rb", buf )
31
+ ```
32
+
33
+ resulting in:
34
+
35
+
36
+ ---
37
+
38
+ ``` ruby
39
+ #########################
40
+ # PunkBlocks contract / (blockchain) services / function calls
41
+ # auto-generated via abigen (see https://rubygems.org/gems/abigen) on 2023-01-13 15:31:38 UTC
42
+ # - 8 query functions(s)
43
+ #
44
+ #
45
+ # - Author: tycoon.eth, thanks to @geraldb & @samwilsn on Github for inspiration!
46
+ # - Version: v0.0.2
47
+ # - Pragma: solidity ^0.8.17
48
+ #
49
+ #
50
+ # ███████████ █████
51
+ # ░░███░░░░░███ ░░███
52
+ # ░███ ░███ █████ ████ ████████ ░███ █████
53
+ # ░██████████ ░░███ ░███ ░░███░░███ ░███░░███
54
+ # ░███░░░░░░ ░███ ░███ ░███ ░███ ░██████░
55
+ # ░███ ░███ ░███ ░███ ░███ ░███░░███
56
+ # █████ ░░████████ ████ █████ ████ █████
57
+ # ░░░░░ ░░░░░░░░ ░░░░ ░░░░░ ░░░░ ░░░░░
58
+ #
59
+ #
60
+ #
61
+ # ███████████ ████ █████
62
+ # ░░███░░░░░███░░███ ░░███
63
+ # ░███ ░███ ░███ ██████ ██████ ░███ █████ █████
64
+ # ░██████████ ░███ ███░░███ ███░░███ ░███░░███ ███░░
65
+ # ░███░░░░░███ ░███ ░███ ░███░███ ░░░ ░██████░ ░░█████
66
+ # ░███ ░███ ░███ ░███ ░███░███ ███ ░███░░███ ░░░░███
67
+ # ███████████ █████░░██████ ░░██████ ████ █████ ██████
68
+ # ░░░░░░░░░░░ ░░░░░ ░░░░░░ ░░░░░░ ░░░░ ░░░░░ ░░░░░░
69
+ #
70
+ # A Registry of 24x24 png images
71
+ #
72
+ # This contract:
73
+ #
74
+ # 1. Stores all the classic traits of the CryptoPunks in
75
+ # individual png files, 100% on-chain. These are then used as
76
+ # blocks to construct CryptoPunk images. Outputted as SVGs.
77
+ #
78
+ # 2. Any of the 10,000 "classic" CryptoPunks can be generated
79
+ # by supplying desired arguments to a function, such as
80
+ # the id of a punk, or a list of the traits.
81
+ #
82
+ # 3. An unlimited number of new punk images can be generated from
83
+ # the existing classic set of traits, or even from new traits!
84
+ #
85
+ # 4. New traits (blocks) can be added to the contract by
86
+ # registering them with the `registerBlock` function.
87
+ #
88
+ # Further documentation:
89
+ # https://github.com/0xTycoon/punk-blocks
90
+ #
91
+ #
92
+ #
93
+ # **Data Structures**
94
+ #
95
+ # Layer is in the order of rendering
96
+ #
97
+ # enum Layer {
98
+ # Base, // 0 Base is the face. Determines if m or f version will be used to render the remaining layers
99
+ # Cheeks, // 1 (Rosy Cheeks)
100
+ # Blemish, // 2 (Mole, Spots)
101
+ # Hair, // 3 (Purple Hair, Shaved Head, Pigtails, ...)
102
+ # Beard, // 4 (Big Beard, Front Beard, Goat, ...)
103
+ # Eyes, // 5 (Clown Eyes Green, Green Eye Shadow, ...)
104
+ # Eyewear, // 6 (VR, 3D Glass, Eye Mask, Regular Shades, Welding Glasses, ...)
105
+ # Nose, // 7 (Clown Nose)
106
+ # Mouth, // 8 (Hot Lipstick, Smile, Buck Teeth, ...)
107
+ # MouthProp, // 9 (Medical Mask, Cigarette, ...)
108
+ # Earring, // 10 (Earring)
109
+ # Headgear, // 11 (Beanie, Fedora, Hoodie, Police Cap, Tiara, Headband, ...)
110
+ # Neck // 12 (Choker, Silver Chain, Gold Chain)
111
+ # }
112
+ #
113
+ # struct Block {
114
+ # Layer layer; // 13 possible layers
115
+ # bytes dataMale; // male version of this attribute
116
+ # bytes dataFemale;// female version of this attribute
117
+ # }
118
+ #
119
+ #
120
+ # **Events**
121
+ #
122
+ # event NewBlock(address, uint256, string)
123
+
124
+
125
+ class PunkBlocks < Ethlite::Contract
126
+
127
+ address "0x58e90596c2065befd3060767736c829c18f3474c"
128
+
129
+ # storage - mapping(bytes32 => Block) public blocks
130
+ #
131
+ # stores punk attributes as a png
132
+ sig "blocks", inputs: ["bytes32"], outputs: ["uint8","bytes","bytes"]
133
+ def blocks(arg0)
134
+ do_call("blocks", arg0)
135
+ end
136
+
137
+ # function getBlocks
138
+ #
139
+ # getBlocks returns a sequential list of blocks in a single call
140
+ # @param _fromID is which id to begin from
141
+ # @param _count how many items to retrieve.
142
+ # @return Block[] list of blocks, uint256 next id
143
+ sig "getBlocks", inputs: ["uint256","uint256"], outputs: ["(uint8,bytes,bytes)[]","uint256"]
144
+ def getBlocks(_fromID, _count)
145
+ do_call("getBlocks", _fromID, _count)
146
+ end
147
+
148
+ # storage - mapping(uint256 => bytes32) public index
149
+ #
150
+ # index of each block by its sequence
151
+ sig "index", inputs: ["uint256"], outputs: ["bytes32"]
152
+ def index(arg0)
153
+ do_call("index", arg0)
154
+ end
155
+
156
+ # storage - uint256 public nextId
157
+ #
158
+ # next id to use when adding a block
159
+ sig "nextId", outputs: ["uint256"]
160
+ def nextId()
161
+ do_call("nextId")
162
+ end
163
+
164
+ # function svgFromIDs
165
+ #
166
+ # svgFromIDs returns the svg data as a string
167
+ # e.g. [9,55,99]
168
+ # One of the elements must be must be a layer 0 block.
169
+ # This element decides what version of image to use for the higher layers
170
+ # (dataMale or dataFemale)
171
+ # @param _ids uint256 ids of an attribute, by it's index of creation
172
+ sig "svgFromIDs", inputs: ["uint256[]"], outputs: ["string"]
173
+ def svgFromIDs(_ids)
174
+ do_call("svgFromIDs", _ids)
175
+ end
176
+
177
+ # function svgFromKeys
178
+ #
179
+ # svgFromKeys returns the svg data as a string
180
+ # @param _attributeKeys a list of attribute names that have been hashed,
181
+ # eg keccak256("Male 1"), keccak256("Goat")
182
+ # must have at least 1 layer 0 attribute (eg. keccak256("Male 1")) which
183
+ # decides what version of image to use for the higher layers
184
+ # (dataMale or dataFemale)
185
+ # e.g. ["0x9039da071f773e85254cbd0f99efa70230c4c11d63fce84323db9eca8e8ef283",
186
+ # "0xd5de5c20969a9e22f93842ca4d65bac0c0387225cee45a944a14f03f9221fd4a"]
187
+ sig "svgFromKeys", inputs: ["bytes32[]"], outputs: ["string"]
188
+ def svgFromKeys(_attributeKeys)
189
+ do_call("svgFromKeys", _attributeKeys)
190
+ end
191
+
192
+ # function svgFromNames
193
+ #
194
+ # svgFromNames returns the svg data as a string
195
+ # @param _attributeNames a list of attribute names, eg "Male 1", "Goat"
196
+ # must have at least 1 layer 0 attribute (eg. Male, Female, Alien, Ape, Zombie)
197
+ # e.g. ["Male 1","Goat"]
198
+ # Where "Male 1" is a layer 0 attribute, that decides what version of
199
+ # image to use for the higher
200
+ # layers (dataMale or dataFemale)
201
+ sig "svgFromNames", inputs: ["string[]"], outputs: ["string"]
202
+ def svgFromNames(_attributeNames)
203
+ do_call("svgFromNames", _attributeNames)
204
+ end
205
+
206
+ # function svgFromPunkID
207
+ #
208
+ # svgFromPunkID returns the svg data as a string given a punk id
209
+ # @param _tokenID uint256 IDs a punk id, 0-9999
210
+ sig "svgFromPunkID", inputs: ["uint256"], outputs: ["string"]
211
+ def svgFromPunkID(_tokenID)
212
+ do_call("svgFromPunkID", _tokenID)
213
+ end
214
+
215
+ end ## class PunkBlocks
216
+ ```
217
+
218
+
219
+ That's it for now.
220
+
221
+
222
+ Tip: For some pre-packaged ready-to-use "out-of-the-gem" contracts,
223
+ see [**ethlite-contracts »**](../ethlite_contracts)
224
+
225
+
16
226
 
17
227
 
18
228
 
data/Rakefile CHANGED
@@ -1,9 +1,16 @@
1
1
  require 'hoe'
2
2
 
3
3
 
4
+ ###
5
+ # hack/ quick fix for broken intuit_values - overwrite with dummy
6
+ class Hoe
7
+ def intuit_values( input ); end
8
+ end
9
+
10
+
4
11
  Hoe.spec 'abigen' do
5
12
 
6
- self.version = '0.0.1'
13
+ self.version = '0.1.0'
7
14
  self.summary = "abigen - generate ready-to-use (blockchain) contract services / function calls for ethereum & co. via application binary inferfaces (abis)"
8
15
  self.description = summary
9
16
 
@@ -18,6 +25,7 @@ Hoe.spec 'abigen' do
18
25
 
19
26
  self.extra_deps = [
20
27
  ['abiparser'],
28
+ ['natspec'],
21
29
  ]
22
30
 
23
31
  self.licenses = ['Public Domain']
data/lib/abigen.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require 'abiparser'
2
+ require 'natspec'
2
3
 
3
4
 
4
5
  ## our own code
@@ -10,12 +11,23 @@ module ABI
10
11
  class Contract
11
12
 
12
13
 
13
- def generate_code( name: 'Contract', address: nil )
14
+ def generate_code( name: 'Contract',
15
+ address: nil,
16
+ natspec: nil )
14
17
  buf = ''
15
18
  buf << "#########################\n"
16
19
  buf << "# #{name} contract / (blockchain) services / function calls\n"
17
- buf << "# auto-generated via abigen (see https://rubygems.org/gems/abigen) on #{Time.now.utc}\n"
18
- buf << "# - #{query_functions.size} query functions(s)\n\n"
20
+ buf << "# auto-generated via abigen (see https://rubygems.org/gems/abigen) on #{Time.now.utc}\n"
21
+ buf << "# - #{query_functions.size} query functions(s)\n"
22
+
23
+ if natspec && natspec.head.size > 0
24
+ buf << "#\n#\n"
25
+ natspec.head.each do |line|
26
+ buf << (line.empty? ? "#\n" : "# #{line}\n")
27
+ end
28
+ end
29
+ buf << "\n\n"
30
+
19
31
 
20
32
 
21
33
  buf << "class #{name} < Ethlite::Contract\n\n"
@@ -30,20 +42,18 @@ def generate_code( name: 'Contract', address: nil )
30
42
  if query_functions.size > 0
31
43
  buf << "\n"
32
44
  query_functions.each do |func|
33
- buf << "# #{func.doc} _readonly_\n"
34
-
35
- buf << %Q{sig "#{func.name}"}
36
45
 
37
- if func.inputs.size > 0
38
- quoted_types = func.inputs.map {|param| %Q{"#{param.sig}"} }
39
- buf << ", inputs: [#{quoted_types.join(',')}]"
46
+ if natspec && (natspec.storage[ func.name] || natspec.functions[ func.name ])
47
+ sect = natspec.storage[ func.name ] || natspec.functions[ func.name ]
48
+ buf << "# #{sect[0]}\n#\n"
49
+ sect[1].each do |line|
50
+ buf << (line.empty? ? "#\n" : "# #{line}\n")
51
+ end
52
+ else
53
+ buf << "# #{func.doc} _readonly_\n"
40
54
  end
41
55
 
42
- if func.outputs.size > 0
43
- quoted_types = func.outputs.map {|param| %Q{"#{param.sig}"} }
44
- buf << ", outputs: [#{quoted_types.join(',')}]"
45
- end
46
- buf << "\n"
56
+
47
57
 
48
58
  buf << "def #{func.name}("
49
59
 
@@ -73,6 +83,26 @@ def generate_code( name: 'Contract', address: nil )
73
83
  buf << ")\n"
74
84
 
75
85
  buf << "end\n"
86
+
87
+ ## note: quick hack - for rdoc/yard doc generation
88
+ ## move sig method below method
89
+ buf << %Q{sig "#{func.name}"}
90
+
91
+ if func.inputs.size > 0
92
+ quoted_types = func.inputs.map {|param| %Q{"#{param.sig}"} }
93
+ buf << ", inputs: [#{quoted_types.join(',')}]"
94
+ end
95
+
96
+ if func.outputs.size > 0
97
+ quoted_types = func.outputs.map {|param| %Q{"#{param.sig}"} }
98
+ buf << ", outputs: [#{quoted_types.join(',')}]"
99
+ end
100
+ buf << "\n"
101
+
102
+
103
+
104
+
105
+
76
106
  buf << "\n"
77
107
  end
78
108
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abigen
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gerald Bauer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-01-10 00:00:00.000000000 Z
11
+ date: 2023-01-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: abiparser
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: natspec
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'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rdoc
29
43
  requirement: !ruby/object:Gem::Requirement