abibase 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 +7 -0
- data/CHANGELOG.md +3 -0
- data/Manifest.txt +5 -0
- data/README.md +31 -0
- data/Rakefile +43 -0
- data/lib/abibase.rb +390 -0
- metadata +158 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 892b874b015e3b8aa49f47fbd86e11a36811b25a9b2dc96f8653ac6cac0ebed8
|
4
|
+
data.tar.gz: 245236223c5506416834085bf1999a4253380fbb5c2169e434b309154d574387
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2ea4084b2b2ad686bc18aa789772934ee7ea44d02947d48d4965ec3048963636b08c9e6f46893ae7a5e8d87a0db75b9632b1cf0b1d1abfcd8397e05e6d327943
|
7
|
+
data.tar.gz: 6ee51891fc973dc08c1fa373a6c50027a054212aa8ea2fdac116684b3551b141840a251bc2275f549609e92db13c6791a7834f6bca355d16c68412a25e118096
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Application Binary Inteface (ABI) Command Line Tool For Ethereum & Co.
|
2
|
+
|
3
|
+
abibase - command line tool / helper to manage application binary interfaces (abis)
|
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/abibase](https://rubygems.org/gems/abibase)
|
9
|
+
* rdoc :: [rubydoc.info/gems/abibase](http://rubydoc.info/gems/abibase)
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
## Usage
|
14
|
+
|
15
|
+
to be done
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
## License
|
21
|
+
|
22
|
+
The scripts are dedicated to the public domain.
|
23
|
+
Use it as you please with no restrictions whatsoever.
|
24
|
+
|
25
|
+
|
26
|
+
## Questions? Comments?
|
27
|
+
|
28
|
+
|
29
|
+
Post them on the [D.I.Y. Punk (Pixel) Art reddit](https://old.reddit.com/r/DIYPunkArt). Thanks.
|
30
|
+
|
31
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
|
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
|
+
|
11
|
+
Hoe.spec 'abibase' do
|
12
|
+
|
13
|
+
self.version = '0.0.1'
|
14
|
+
|
15
|
+
self.summary = "abibase - command line tool / helper to manage application binary interfaces (abis)"
|
16
|
+
self.description = summary
|
17
|
+
|
18
|
+
self.urls = { home: 'https://github.com/rubycocos/blockchain' }
|
19
|
+
|
20
|
+
self.author = 'Gerald Bauer'
|
21
|
+
self.email = 'wwwmake@googlegroups.com'
|
22
|
+
|
23
|
+
# switch extension to .markdown for gihub formatting
|
24
|
+
self.readme_file = 'README.md'
|
25
|
+
self.history_file = 'CHANGELOG.md'
|
26
|
+
|
27
|
+
self.extra_deps = [
|
28
|
+
## ['ethlite'],
|
29
|
+
['etherscan-lite'],
|
30
|
+
['abiparser'],
|
31
|
+
['natspec'],
|
32
|
+
['abidoc'],
|
33
|
+
['abigen'],
|
34
|
+
]
|
35
|
+
|
36
|
+
self.licenses = ['Public Domain']
|
37
|
+
|
38
|
+
self.spec_extras = {
|
39
|
+
required_ruby_version: '>= 2.3'
|
40
|
+
}
|
41
|
+
|
42
|
+
end
|
43
|
+
|
data/lib/abibase.rb
ADDED
@@ -0,0 +1,390 @@
|
|
1
|
+
################
|
2
|
+
# download ABIs via Etherscan
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
|
7
|
+
require 'etherscan-lite'
|
8
|
+
require 'abidoc'
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
def format_code( txt )
|
13
|
+
## {{ to {
|
14
|
+
## and }} to }
|
15
|
+
txt = txt.strip.sub( /\A\{\{/, '{').sub( /\}\}\z/, '}' )
|
16
|
+
|
17
|
+
data = JSON.parse( txt )
|
18
|
+
## pp data
|
19
|
+
|
20
|
+
language = data['language']
|
21
|
+
pp language
|
22
|
+
if language != 'Solidity'
|
23
|
+
puts "!! ERROR - expected Solidity for language; got: #{language}"
|
24
|
+
exit 1
|
25
|
+
end
|
26
|
+
|
27
|
+
sources = data['sources']
|
28
|
+
puts " #{sources.size} source(s)"
|
29
|
+
|
30
|
+
buf = ''
|
31
|
+
sources.each do |name, h|
|
32
|
+
buf << "///////////////////////////////////////////\n"
|
33
|
+
buf << "// File: #{name}\n\n"
|
34
|
+
buf << h['content']
|
35
|
+
buf << "\n\n"
|
36
|
+
end
|
37
|
+
buf
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
class ContractDetailsCache
|
45
|
+
|
46
|
+
def initialize( path )
|
47
|
+
@path = path
|
48
|
+
@table = if File.exist?( path )
|
49
|
+
build_table( read_csv( path ) )
|
50
|
+
else
|
51
|
+
{}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def [](addr)
|
56
|
+
if @table.has_key?( addr )
|
57
|
+
@table[ addr ]
|
58
|
+
else ## fetch missing data
|
59
|
+
data = Etherscan.getcontractdetails( contractaddress: addr )
|
60
|
+
## note: add new data to cache
|
61
|
+
@table[ addr ] = data
|
62
|
+
data
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
def build_table( recs )
|
69
|
+
h = {}
|
70
|
+
recs.each do |rec|
|
71
|
+
## (re)use contractdetails format / hash keys
|
72
|
+
h[ rec['address'] ] = {
|
73
|
+
'contractAddress' => rec['address'],
|
74
|
+
'contractCreator' => rec['creator'],
|
75
|
+
'txHash' => rec['txid'],
|
76
|
+
'blockNumber' => rec['blocknumber'],
|
77
|
+
'timestamp' => rec['timestamp']
|
78
|
+
}
|
79
|
+
end
|
80
|
+
h
|
81
|
+
end
|
82
|
+
|
83
|
+
def save
|
84
|
+
##############
|
85
|
+
## save cache - sort by blocknumber
|
86
|
+
entries = @table.values.sort { |l,r| l['blockNumber'].to_i(16) <=> r['blockNumber'].to_i(16) }
|
87
|
+
buf = ''
|
88
|
+
buf << ['blocknumber', 'timestamp', 'address', 'creator', 'txid'].join( ', ' )
|
89
|
+
buf << "\n"
|
90
|
+
entries.each do |entry|
|
91
|
+
buf << [entry['blockNumber'],
|
92
|
+
entry['timestamp'],
|
93
|
+
entry['contractAddress'],
|
94
|
+
entry['contractCreator'],
|
95
|
+
entry['txHash']
|
96
|
+
].join( ', ' )
|
97
|
+
buf << "\n"
|
98
|
+
end
|
99
|
+
write_text( @path, buf )
|
100
|
+
end
|
101
|
+
end # class ContractDetailsCache
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
module Abi
|
110
|
+
|
111
|
+
class Tool
|
112
|
+
|
113
|
+
def self.main( args=ARGV )
|
114
|
+
puts "==> welcome to abibase tool with args:"
|
115
|
+
pp args
|
116
|
+
|
117
|
+
options = {}
|
118
|
+
|
119
|
+
parser = OptionParser.new do |opts|
|
120
|
+
opts.on("-h", "--help", "Prints this help") do
|
121
|
+
puts opts
|
122
|
+
exit
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
parser.parse!( args )
|
127
|
+
puts "options:"
|
128
|
+
pp options
|
129
|
+
|
130
|
+
puts "args:"
|
131
|
+
pp args
|
132
|
+
|
133
|
+
command = args[0] || 'download'
|
134
|
+
|
135
|
+
if ['d', 'dl', 'download'].include?( command )
|
136
|
+
do_download_abis
|
137
|
+
elsif ['code'].include?( command )
|
138
|
+
do_download_code
|
139
|
+
elsif ['doc', 'docs'].include?( command )
|
140
|
+
do_generate_docs
|
141
|
+
elsif ['t', 'time', 'timeline'].include?( command )
|
142
|
+
do_generate_timeline # & download contract details (txid,timestamp,etc.)
|
143
|
+
else
|
144
|
+
puts "!! ERROR - unknown command >#{command}<, sorry"
|
145
|
+
end
|
146
|
+
|
147
|
+
puts "bye"
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
|
154
|
+
def self.do_download_abis
|
155
|
+
puts "==> download abis..."
|
156
|
+
|
157
|
+
recs = read_csv( "./contracts.csv" )
|
158
|
+
puts " #{recs.size} record(s)"
|
159
|
+
|
160
|
+
delay_in_s = 1
|
161
|
+
|
162
|
+
recs.each_with_index do |rec,i|
|
163
|
+
addr = rec['address'].downcase
|
164
|
+
names = rec['names']
|
165
|
+
puts "==> [#{i+1}/#{recs.size}] #{names} @ #{addr}..."
|
166
|
+
|
167
|
+
outpath = "./address/#{addr}/abi.json"
|
168
|
+
|
169
|
+
if File.exist?( outpath )
|
170
|
+
# already download / found in cache
|
171
|
+
else
|
172
|
+
puts " sleeping in #{delay_in_s} sec(s)..."
|
173
|
+
sleep( delay_in_s )
|
174
|
+
data = Etherscan.getabi( address: addr )
|
175
|
+
pp data ## note: returns abi data as a json string (parse again!!)
|
176
|
+
abi = JSON.parse( data )
|
177
|
+
pp abi
|
178
|
+
|
179
|
+
write_json( outpath, abi )
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
def self.do_download_code
|
188
|
+
puts "==> download (source) code..."
|
189
|
+
|
190
|
+
recs = read_csv( "./contracts.csv" )
|
191
|
+
puts " #{recs.size} record(s)"
|
192
|
+
|
193
|
+
delay_in_s = 1
|
194
|
+
|
195
|
+
recs.each_with_index do |rec,i|
|
196
|
+
addr = rec['address'].downcase
|
197
|
+
names = rec['names']
|
198
|
+
puts "==> [#{i+1}/#{recs.size}] #{names} @ #{addr}..."
|
199
|
+
|
200
|
+
outpath_code = "./address/#{addr}/contract.sol"
|
201
|
+
outpath_meta = "./address/#{addr}/contract.yml"
|
202
|
+
|
203
|
+
if File.exist?( outpath_code )
|
204
|
+
# already download / found in cache
|
205
|
+
else
|
206
|
+
puts " sleeping in #{delay_in_s} sec(s)..."
|
207
|
+
sleep( delay_in_s )
|
208
|
+
|
209
|
+
data = Etherscan.getsourcecode( address: addr )
|
210
|
+
pp data ## note: returns abi data as a json string (parse again!!)
|
211
|
+
|
212
|
+
## note: returns an array
|
213
|
+
if data.size != 1
|
214
|
+
puts "!! ERROR - expected array of size 1; got #{data.size}"
|
215
|
+
exit 1
|
216
|
+
end
|
217
|
+
|
218
|
+
code = data[0]['SourceCode']
|
219
|
+
|
220
|
+
## note: unroll multi-file format if present (starts with {{ .. }})
|
221
|
+
code = format_code( code ) if code.start_with?( /[ \t\n\r]*\{\{/ )
|
222
|
+
|
223
|
+
|
224
|
+
## fix: use "universal new line or such ?? - why lines get duplicated??"
|
225
|
+
## hack: use write_blob
|
226
|
+
write_blob( outpath_code, code )
|
227
|
+
|
228
|
+
## remove SourceCode & ABI entries
|
229
|
+
data[0].delete('SourceCode')
|
230
|
+
data[0].delete('ABI')
|
231
|
+
puts "meta:"
|
232
|
+
pp data[0]
|
233
|
+
|
234
|
+
## save rest (remaining) as yml
|
235
|
+
write_text( outpath_meta, YAML.dump( data[0] ))
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
|
242
|
+
def self.do_generate_docs
|
243
|
+
puts "==> generate docs..."
|
244
|
+
|
245
|
+
paths = Dir.glob( "./address/**/abi.json" )
|
246
|
+
## paths = paths[0..2]
|
247
|
+
paths.each do |path|
|
248
|
+
basename = File.basename( File.dirname( path ))
|
249
|
+
|
250
|
+
abi = ABI.read( path )
|
251
|
+
|
252
|
+
natspec = if File.exist?( "./address/#{basename}/contract.md" )
|
253
|
+
Natspec.read( "./address/#{basename}/contract.md" )
|
254
|
+
else
|
255
|
+
nil
|
256
|
+
end
|
257
|
+
|
258
|
+
buf = abi.generate_doc( title: "Contract ABI - #{basename}",
|
259
|
+
natspec: natspec )
|
260
|
+
puts buf
|
261
|
+
write_text( "./address/#{basename}/README.md", buf )
|
262
|
+
|
263
|
+
buf = abi.generate_interface( name: '' ) # solidity interface declarations (source code)
|
264
|
+
write_text( "./address/#{basename}/interface.sol", buf )
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
|
269
|
+
def self.do_generate_timeline
|
270
|
+
puts "==> generate timeline..."
|
271
|
+
|
272
|
+
## collection all addresses
|
273
|
+
addresses = []
|
274
|
+
paths = Dir.glob( "./address/**/abi.json" )
|
275
|
+
## paths = paths[0..2]
|
276
|
+
paths.each do |path|
|
277
|
+
basename = File.basename( File.dirname( path ))
|
278
|
+
|
279
|
+
addresses << basename.downcase
|
280
|
+
end
|
281
|
+
|
282
|
+
pp addresses
|
283
|
+
puts " #{addresses.size} record(s)"
|
284
|
+
|
285
|
+
## update contractdetails.csv
|
286
|
+
## build cache
|
287
|
+
cache = ContractDetailsCache.new( './contractdetails.csv' )
|
288
|
+
|
289
|
+
recs = []
|
290
|
+
addresses.each_with_index do |addr,i|
|
291
|
+
rec = cache[ addr ]
|
292
|
+
recs << rec
|
293
|
+
end
|
294
|
+
### note: save back contractdetails cache
|
295
|
+
cache.save
|
296
|
+
|
297
|
+
############
|
298
|
+
## sort by blocknumber (reverse chronological)
|
299
|
+
recs = recs.sort do |l,r|
|
300
|
+
l['blockNumber'].to_i(16) <=> r['blockNumber'].to_i(16)
|
301
|
+
end
|
302
|
+
|
303
|
+
pp recs
|
304
|
+
|
305
|
+
## create report / page
|
306
|
+
buf = <<TXT
|
307
|
+
# Awesome (Ethereum) Contracts / Blockchain Services
|
308
|
+
|
309
|
+
Cache of (ethereum) contract ABIs (application binary interfaces)
|
310
|
+
and open source code (if verified / available)
|
311
|
+
|
312
|
+
|
313
|
+
TXT
|
314
|
+
|
315
|
+
meta = read_csv( './contracts.csv')
|
316
|
+
## build name lookup by address
|
317
|
+
contracts = meta.reduce( {} ) {|h,rec| h[rec['address']]=rec['names']; h }
|
318
|
+
pp contracts
|
319
|
+
|
320
|
+
recs.each_with_index do |rec,i|
|
321
|
+
addr = rec['contractAddress'].downcase
|
322
|
+
timestamp = rec['timestamp'].to_i(16)
|
323
|
+
date = Time.at( timestamp).utc
|
324
|
+
|
325
|
+
tooltip = date.strftime('%b %-d, %Y')
|
326
|
+
|
327
|
+
names = contracts[addr]
|
328
|
+
if names.nil?
|
329
|
+
puts "!! ERROR: no name found for contract; sorry:"
|
330
|
+
pp rec
|
331
|
+
exit 1
|
332
|
+
end
|
333
|
+
|
334
|
+
names = names.split( '|' )
|
335
|
+
names = names.map { |name| name.gsub( /[ \t]+/, ' ' ).strip }
|
336
|
+
name = names[0]
|
337
|
+
|
338
|
+
buf << " · " if i > 0
|
339
|
+
buf << %Q{[#{name}](address/#{addr} "#{tooltip}")}
|
340
|
+
buf << "\n"
|
341
|
+
end
|
342
|
+
|
343
|
+
|
344
|
+
buf << "\n"
|
345
|
+
buf << "## Timeline\n\n"
|
346
|
+
|
347
|
+
recs.each do |rec|
|
348
|
+
|
349
|
+
addr = rec['contractAddress']
|
350
|
+
creator = rec['contractCreator']
|
351
|
+
txid = rec['txHash']
|
352
|
+
blocknumber = rec['blockNumber'].to_i(16)
|
353
|
+
timestamp = rec['timestamp'].to_i(16)
|
354
|
+
date = Time.at( timestamp).utc
|
355
|
+
|
356
|
+
names = contracts[addr]
|
357
|
+
if names.nil?
|
358
|
+
puts "!! ERROR: no name found for contract; sorry:"
|
359
|
+
pp rec
|
360
|
+
exit 1
|
361
|
+
end
|
362
|
+
|
363
|
+
names = names.split( '|' )
|
364
|
+
names = names.map { |name| name.gsub( /[ \t]+/, ' ' ).strip }
|
365
|
+
name = names[0]
|
366
|
+
|
367
|
+
buf << "### #{names.join( ' | ')} - #{date.strftime('%b %-d, %Y')}\n\n"
|
368
|
+
|
369
|
+
buf << "contract @ [**#{addr}**](address/#{addr})"
|
370
|
+
buf << " - [Etherscan](https://etherscan.io/address/#{addr})"
|
371
|
+
buf << ", [Bloxy](https://bloxy.info/address/#{addr})"
|
372
|
+
## buf << ", [ABIDocs](https://abidocs.dev/contracts/#{addr})"
|
373
|
+
buf << "\n\n"
|
374
|
+
|
375
|
+
# buf << "created by [#{creator}](https://etherscan.io/address/#{creator}))"
|
376
|
+
# buf << " at block no. #{blocknumber} (#{date})"
|
377
|
+
# buf << " - txid [#{txid}](https://etherscan.io/tx/#{txid})"
|
378
|
+
# buf << "\n\n"
|
379
|
+
end
|
380
|
+
|
381
|
+
|
382
|
+
write_text( './README.md', buf )
|
383
|
+
|
384
|
+
|
385
|
+
|
386
|
+
|
387
|
+
|
388
|
+
end
|
389
|
+
end # class Tool
|
390
|
+
end # module Abi
|
metadata
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abibase
|
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: 2023-01-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: etherscan-lite
|
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: abiparser
|
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: natspec
|
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: abidoc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: abigen
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rdoc
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.0'
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '7'
|
93
|
+
type: :development
|
94
|
+
prerelease: false
|
95
|
+
version_requirements: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '4.0'
|
100
|
+
- - "<"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '7'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: hoe
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '3.23'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '3.23'
|
117
|
+
description: abibase - command line tool / helper to manage application binary interfaces
|
118
|
+
(abis)
|
119
|
+
email: wwwmake@googlegroups.com
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files:
|
123
|
+
- CHANGELOG.md
|
124
|
+
- Manifest.txt
|
125
|
+
- README.md
|
126
|
+
files:
|
127
|
+
- CHANGELOG.md
|
128
|
+
- Manifest.txt
|
129
|
+
- README.md
|
130
|
+
- Rakefile
|
131
|
+
- lib/abibase.rb
|
132
|
+
homepage: https://github.com/rubycocos/blockchain
|
133
|
+
licenses:
|
134
|
+
- Public Domain
|
135
|
+
metadata: {}
|
136
|
+
post_install_message:
|
137
|
+
rdoc_options:
|
138
|
+
- "--main"
|
139
|
+
- README.md
|
140
|
+
require_paths:
|
141
|
+
- lib
|
142
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: '2.3'
|
147
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
requirements: []
|
153
|
+
rubygems_version: 3.3.7
|
154
|
+
signing_key:
|
155
|
+
specification_version: 4
|
156
|
+
summary: abibase - command line tool / helper to manage application binary interfaces
|
157
|
+
(abis)
|
158
|
+
test_files: []
|