abibase 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|