artq 0.1.0 → 0.2.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.
- checksums.yaml +4 -4
- data/Manifest.txt +1 -0
- data/README.md +169 -9
- data/lib/artq/contract.rb +73 -0
- data/lib/artq/version.rb +1 -1
- data/lib/artq.rb +100 -22
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0f00a597b6533cbdce4aa3286531d8533f9d3c0cf57b8147b7160d4b1d206d3
|
4
|
+
data.tar.gz: e192cfb230111adb5dd69a1213a1446a9dc629fc853cacb8b10e5d80ac723e8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bf4be0a1990ce7c1d6d6e2c30b936cc0a145401b2992b32e4f2c83153881746fdaab77de434a38409bc17c6c0cbb93ee4673a589767197b314b11b935078426
|
7
|
+
data.tar.gz: 65db2f2e2d112926111cb05398dd992a28d64f793a6f5d955b01a4cf03f1f25d9334d998b16088302479a07e6a3191712bc41d932c1b87d821f5d68b3e7b9974
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -31,13 +31,14 @@ set INFURA_URI=https://mainnet.infura.io/v3/<YOUR_KEY_HERE>
|
|
31
31
|
To use the artq command line tool pass in the art collection contract address in the hex (string) format.
|
32
32
|
|
33
33
|
|
34
|
-
#### "Off-Blockchain" Token Metadata
|
34
|
+
#### Case No. 1 - "Off-Blockchain" Token Metadata
|
35
35
|
|
36
|
-
Let's try Moonbirds - an
|
36
|
+
Let's try Moonbirds - an "off-blockchain" pixel art collection -
|
37
37
|
with the token contract / service at [0x23581767a106ae21c074b2276d25e5c3e136a68b](https://etherscan.io/address/0x23581767a106ae21c074b2276d25e5c3e136a68b):
|
38
38
|
|
39
39
|
```
|
40
|
-
$ artq 0x23581767a106ae21c074b2276d25e5c3e136a68b
|
40
|
+
$ artq 0x23581767a106ae21c074b2276d25e5c3e136a68b # or
|
41
|
+
$ artq 0x23581767a106ae21c074b2276d25e5c3e136a68b info
|
41
42
|
```
|
42
43
|
|
43
44
|
resulting in:
|
@@ -48,11 +49,11 @@ symbol: >MOONBIRD<
|
|
48
49
|
totalSupply: >10000<
|
49
50
|
|
50
51
|
tokenURIs 0..2:
|
51
|
-
tokenId
|
52
|
+
tokenId 0:
|
52
53
|
https://live---metadata-5covpqijaa-uc.a.run.app/metadata/0
|
53
|
-
tokenId
|
54
|
+
tokenId 1:
|
54
55
|
https://live---metadata-5covpqijaa-uc.a.run.app/metadata/1
|
55
|
-
tokenId
|
56
|
+
tokenId 2:
|
56
57
|
https://live---metadata-5covpqijaa-uc.a.run.app/metadata/2
|
57
58
|
```
|
58
59
|
|
@@ -83,15 +84,16 @@ For example if you request <https://live---metadata-5covpqijaa-uc.a.run.app/met
|
|
83
84
|
|
84
85
|
|
85
86
|
|
86
|
-
#### "On-Blockchain" Token Metadata (With Inline Image)
|
87
|
+
#### Case No. 2 - "On-Blockchain" Token Metadata (With Inline Image)
|
87
88
|
|
88
89
|
|
89
90
|
|
90
|
-
Let's try The Saudis - an
|
91
|
+
Let's try The Saudis - an "on-blockchain" pixel art collection -
|
91
92
|
with the token contract / service at [0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1](https://etherscan.io/address/0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1):
|
92
93
|
|
93
94
|
```
|
94
|
-
$ artq 0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1
|
95
|
+
$ artq 0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1 # or
|
96
|
+
$ artq 0xe21ebcd28d37a67757b9bc7b290f4c4928a430b1 info
|
95
97
|
```
|
96
98
|
|
97
99
|
resulting in:
|
@@ -182,6 +184,164 @@ and inline svg images in the base64 format get "cut" from the metadata and "past
|
|
182
184
|
```
|
183
185
|
|
184
186
|
|
187
|
+
#### Bonus - Case No. 3 - "On-Blockchain" Layers (Incl. Metadata & Images)
|
188
|
+
|
189
|
+
|
190
|
+
Note: Some "on-blockchain" pixel art collections
|
191
|
+
include all layers, that is, metadata and images
|
192
|
+
to compose / make-up "on-blockchain" token images "on-demand / on-the-fly" from "trait" building blocks from scratch.
|
193
|
+
|
194
|
+
|
195
|
+
If the contract uses / supports:
|
196
|
+
|
197
|
+
- `traitDetails(uint256 _layerIndex, uint256 _traitIndex) returns (string _name, string _mimetype, bool _hide)` and
|
198
|
+
- `traitData(uint256 _layerIndex, uint256 _traitIndex) returns string`
|
199
|
+
|
200
|
+
than you can "auto-magically" download all "on-blockchain" layers, that is, all metadata triplets by repeatedly calling `traitDetails` starting
|
201
|
+
with index `0/0`, `0/1`, ..., `1/0`, `1/1`, ... and so on e.g.
|
202
|
+
|
203
|
+
- `traitDetails( 0, 0 )` => `["Rainbow Puke", "image/png", false]`
|
204
|
+
- `traitDetails( 0, 1 )` => `["Bubble Gum", "image/png", false]`
|
205
|
+
- ...
|
206
|
+
- `traitDetails( 1, 0 )` => `["Gold Chain", "image/png", false]`
|
207
|
+
- `traitDetails( 2, 1 )` => `["Bowtie", "image/png", false]`
|
208
|
+
- ...
|
209
|
+
|
210
|
+
|
211
|
+
and all images (as binary blobs) by calling `traitData` e.g.
|
212
|
+
|
213
|
+
- `traitData( 0, 0 )` => `"\x89PNG..."`
|
214
|
+
- `traitData( 0, 1 )` => `"\x89PNG..."`
|
215
|
+
- ...
|
216
|
+
|
217
|
+
and so on.
|
218
|
+
|
219
|
+
|
220
|
+
|
221
|
+
Let's try Mad Camels - an "on-blockchain" pixel art collection -
|
222
|
+
with the token contract / service at [0xad8474ba5a7f6abc52708f171f57fefc5cdc8c1c](https://etherscan.io/address/0xad8474ba5a7f6abc52708f171f57fefc5cdc8c1c):
|
223
|
+
|
224
|
+
|
225
|
+
```
|
226
|
+
$ artq 0xad8474ba5a7f6abc52708f171f57fefc5cdc8c1c layers
|
227
|
+
```
|
228
|
+
|
229
|
+
resulting in a temp(orary) directory holding
|
230
|
+
all images:
|
231
|
+
|
232
|
+
```
|
233
|
+
/0_0.png
|
234
|
+
0_1.png
|
235
|
+
...
|
236
|
+
1_0.png
|
237
|
+
1_1.png
|
238
|
+
...
|
239
|
+
```
|
240
|
+
|
241
|
+

|
242
|
+
|
243
|
+
|
244
|
+
and a datafile with all metadata in the comma-separated values (csv) format, that is, `layers.csv` e.g:
|
245
|
+
|
246
|
+
```
|
247
|
+
index, name, type, hide
|
248
|
+
0/0, Rainbow Puke, image/png, false
|
249
|
+
0/1, Bubble Gum, image/png, false
|
250
|
+
0/2, Vape, image/png, false
|
251
|
+
0/3, None, image/png, false
|
252
|
+
0/4, Cigarette, image/png, false
|
253
|
+
0/5, Pipe, image/png, false
|
254
|
+
1/0, Gold Chain, image/png, false
|
255
|
+
1/1, Bowtie, image/png, false
|
256
|
+
1/2, Gold Necklace, image/png, false
|
257
|
+
1/3, None, image/png, false
|
258
|
+
2/0, Eye Patch, image/png, false
|
259
|
+
2/1, Nerd Glasses, image/png, false
|
260
|
+
2/2, Blue Beams, image/png, false
|
261
|
+
2/3, Purple Eye Shadow, image/png, false
|
262
|
+
2/4, Gold Glasses, image/png, false
|
263
|
+
2/5, Holographic, image/png, false
|
264
|
+
2/6, Clown Eyes Red, image/png, false
|
265
|
+
2/7, Clown Eyes Green, image/png, false
|
266
|
+
2/8, Eye Mask, image/png, false
|
267
|
+
2/9, Laser Eye, image/png, false
|
268
|
+
2/10, VR, image/png, false
|
269
|
+
2/11, 3D Glasses, image/png, false
|
270
|
+
2/12, None, image/png, false
|
271
|
+
2/13, Yellow Glasses, image/png, false
|
272
|
+
2/14, Cool Glasses, image/png, false
|
273
|
+
2/15, Purple Glasses, image/png, false
|
274
|
+
2/16, Green Glasses, image/png, false
|
275
|
+
3/0, Diamond, image/png, false
|
276
|
+
3/1, Silver, image/png, false
|
277
|
+
3/2, Gold, image/png, false
|
278
|
+
3/3, None, image/png, false
|
279
|
+
4/0, Crown, image/png, false
|
280
|
+
4/1, Wireless Earphone, image/png, false
|
281
|
+
4/2, Flower, image/png, false
|
282
|
+
4/3, Fez, image/png, false
|
283
|
+
4/4, Fire, image/png, false
|
284
|
+
4/5, Beanie, image/png, false
|
285
|
+
4/6, Headphone, image/png, false
|
286
|
+
4/7, White Shemagh, image/png, false
|
287
|
+
4/8, Red And White Shemagh, image/png, false
|
288
|
+
4/9, Angle Ring, image/png, false
|
289
|
+
4/10, Blue Mohawk, image/png, false
|
290
|
+
4/11, Sombrero, image/png, false
|
291
|
+
4/12, Red Mohawk, image/png, false
|
292
|
+
4/13, Blue Bandana, image/png, false
|
293
|
+
4/14, Viking, image/png, false
|
294
|
+
4/15, Pilot Helmet, image/png, false
|
295
|
+
4/16, Top Hat, image/png, false
|
296
|
+
4/17, Captain Hat, image/png, false
|
297
|
+
4/18, Thief Hat, image/png, false
|
298
|
+
4/19, Orange Cap, image/png, false
|
299
|
+
4/20, Pirate Bandana, image/png, false
|
300
|
+
4/21, Knitted Cap, image/png, false
|
301
|
+
4/22, Purple Cap, image/png, false
|
302
|
+
4/23, Black Cap, image/png, false
|
303
|
+
4/24, Pirate Hat, image/png, false
|
304
|
+
4/25, None, image/png, false
|
305
|
+
4/26, Red Cap, image/png, false
|
306
|
+
4/27, Cop Hat, image/png, false
|
307
|
+
4/28, Cowboy Hat, image/png, false
|
308
|
+
4/29, Fedora, image/png, false
|
309
|
+
5/0, Mole, image/png, false
|
310
|
+
5/1, Pimple, image/png, false
|
311
|
+
5/2, None, image/png, false
|
312
|
+
6/0, Gold, image/png, false
|
313
|
+
6/1, Cyborg, image/png, false
|
314
|
+
6/2, Skeleton, image/png, false
|
315
|
+
6/3, Female, image/png, false
|
316
|
+
6/4, Robot, image/png, false
|
317
|
+
6/5, Zombie, image/png, false
|
318
|
+
6/6, Alien, image/png, false
|
319
|
+
6/7, Default, image/png, false
|
320
|
+
7/0, Desert, image/png, false
|
321
|
+
7/1, Cream, image/png, false
|
322
|
+
7/2, Pink, image/png, false
|
323
|
+
7/3, Purple, image/png, false
|
324
|
+
7/4, Green, image/png, false
|
325
|
+
7/5, Blue, image/png, false
|
326
|
+
```
|
327
|
+
|
328
|
+
|
329
|
+
Try some more art collections with "on-blockchain" layers
|
330
|
+
such as
|
331
|
+
[Long Live Kevin](https://etherscan.io/address/0x8ae5523f76a5711fb6bdca1566df3f4707aec1c4),
|
332
|
+
[Aliens vs Punks](https://etherscan.io/address/0x2612c0375c47ee510a1663169288f2e9eb912947),
|
333
|
+
[Chi Chis](https://etherscan.io/address/0x2204a94f96d39df3b6bc0298cf068c8c82dc8d61),
|
334
|
+
[Chopper](https://etherscan.io/address/0x090c8034e6706994945049e0ede1bbdf21498e6e),
|
335
|
+
[Inverse Punks](https://etherscan.io/address/0xf3a1befc9643f94551c24a766afb87383ef64dd4),
|
336
|
+
[Marcs](https://etherscan.io/address/0xe9b91d537c3aa5a3fa87275fbd2e4feaaed69bd0),
|
337
|
+
[Phunk Ape Origins](https://etherscan.io/address/0x9b66d03fc1eee61a512341058e95f1a68dc3a913),
|
338
|
+
[Punkin Spicies](https://etherscan.io/address/0x34625ecaa75c0ea33733a05c584f4cf112c10b6b),
|
339
|
+
and many more.
|
340
|
+
|
341
|
+
|
342
|
+
Tip: See the [**Art Factory Sandbox**](https://github.com/pixelartexchange/artfactory.sandbox) for more art collections with "on-blockchain" layers.
|
343
|
+
|
344
|
+
|
185
345
|
|
186
346
|
|
187
347
|
## License
|
@@ -0,0 +1,73 @@
|
|
1
|
+
|
2
|
+
module ArtQ
|
3
|
+
|
4
|
+
|
5
|
+
class Contract
|
6
|
+
|
7
|
+
## auto-add "well-known" methods for contract methods - why? why not?
|
8
|
+
METHODS = {
|
9
|
+
name: { inputs: [],
|
10
|
+
outputs: ['string'] },
|
11
|
+
symbol: { inputs: [],
|
12
|
+
outputs: ['string'] },
|
13
|
+
totalSupply: { inputs: [],
|
14
|
+
outputs: ['uint256'] },
|
15
|
+
tokenURI: { inputs: ['uint256'],
|
16
|
+
outputs: ['string'] },
|
17
|
+
|
18
|
+
traitData: { inputs: ['uint256', 'uint256'],
|
19
|
+
outputs: ['string'] },
|
20
|
+
traitDetails: { inputs: ['uint256', 'uint256'],
|
21
|
+
outputs: ['(string,string,bool)'] },
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
METHODS.each do |name, m|
|
26
|
+
eth = Ethlite::ContractMethod.new( name.to_s,
|
27
|
+
inputs: m[:inputs],
|
28
|
+
outputs: m[:outputs] )
|
29
|
+
|
30
|
+
arity = m[:inputs].size
|
31
|
+
if arity == 0
|
32
|
+
define_method( name ) do
|
33
|
+
args = []
|
34
|
+
_do_call( eth, args )
|
35
|
+
end
|
36
|
+
elsif arity == 1
|
37
|
+
define_method( name ) do |arg0|
|
38
|
+
args = [arg0]
|
39
|
+
_do_call( eth, args )
|
40
|
+
end
|
41
|
+
elsif arity == 2
|
42
|
+
define_method( name ) do |arg0,arg1|
|
43
|
+
args = [arg0, arg1]
|
44
|
+
_do_call( eth, args )
|
45
|
+
end
|
46
|
+
else
|
47
|
+
raise ArgumentError, "unsupported no. of arguments #{m[:inputs]} (arity); sorry"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
|
53
|
+
def self.rpc
|
54
|
+
@rpc ||= JsonRpc.new( ENV['INFURA_URI'] )
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.rpc=(value)
|
58
|
+
@rpc = value.is_a?( String ) ? JsonRpc.new( value ) : value
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def initialize( contract_address )
|
63
|
+
@contract_address = contract_address
|
64
|
+
end
|
65
|
+
|
66
|
+
######
|
67
|
+
# private helper to call method
|
68
|
+
def _do_call( eth, args )
|
69
|
+
eth.do_call( self.class.rpc, @contract_address, args )
|
70
|
+
end
|
71
|
+
|
72
|
+
end # class Contract
|
73
|
+
end # module ArtQ
|
data/lib/artq/version.rb
CHANGED
data/lib/artq.rb
CHANGED
@@ -4,11 +4,16 @@ require 'optparse'
|
|
4
4
|
|
5
5
|
## our own code
|
6
6
|
require_relative 'artq/version' # let version go first
|
7
|
+
require_relative 'artq/contract'
|
7
8
|
|
8
9
|
|
9
10
|
|
10
11
|
module ArtQ
|
11
12
|
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
12
17
|
class Tool
|
13
18
|
|
14
19
|
def self.main( args=ARGV )
|
@@ -50,6 +55,8 @@ class Tool
|
|
50
55
|
|
51
56
|
if ['i','inf','info'].include?( command )
|
52
57
|
do_info( contract_address )
|
58
|
+
elsif ['l', 'layer', 'layers'].include?( command )
|
59
|
+
do_layers( contract_address )
|
53
60
|
else
|
54
61
|
puts "!! ERROR - unknown command >#{command}<, sorry"
|
55
62
|
end
|
@@ -58,37 +65,22 @@ class Tool
|
|
58
65
|
end
|
59
66
|
|
60
67
|
|
61
|
-
ETH_name = Ethlite::ContractMethod.new( 'name',
|
62
|
-
inputs: [],
|
63
|
-
outputs: ['string'] )
|
64
|
-
|
65
|
-
ETH_symbol = Ethlite::ContractMethod.new( 'symbol',
|
66
|
-
inputs: [],
|
67
|
-
outputs: ['string'] )
|
68
|
-
|
69
|
-
ETH_totalSupply = Ethlite::ContractMethod.new( 'totalSupply',
|
70
|
-
inputs: [],
|
71
|
-
outputs: ['uint256'] )
|
72
|
-
|
73
|
-
ETH_tokenURI = Ethlite::ContractMethod.new( 'tokenURI',
|
74
|
-
inputs: ['uint256'],
|
75
|
-
outputs: ['string'] )
|
76
68
|
|
77
69
|
|
78
70
|
|
79
71
|
def self.do_info( contract_address )
|
80
|
-
puts "==> query art collection contract
|
72
|
+
puts "==> query info for art collection contract @ >#{contract_address}<:"
|
81
73
|
|
82
|
-
|
74
|
+
c = Contract.new( contract_address )
|
83
75
|
|
84
|
-
name =
|
85
|
-
symbol =
|
86
|
-
totalSupply =
|
76
|
+
name = c.name
|
77
|
+
symbol = c.symbol
|
78
|
+
totalSupply = c.totalSupply
|
87
79
|
|
88
80
|
meta = []
|
89
81
|
tokenIds = (0..2)
|
90
82
|
tokenIds.each do |tokenId|
|
91
|
-
tokenURI =
|
83
|
+
tokenURI = c.tokenURI( tokenId )
|
92
84
|
meta << [tokenId, tokenURI]
|
93
85
|
end
|
94
86
|
|
@@ -126,9 +118,95 @@ class Tool
|
|
126
118
|
end
|
127
119
|
end
|
128
120
|
end
|
129
|
-
end # class Tool
|
130
121
|
|
131
122
|
|
123
|
+
|
124
|
+
JPGSIG = "\xFF\xD8\xFF".force_encoding( Encoding::ASCII_8BIT )
|
125
|
+
PNGSIG = "\x89PNG".force_encoding( Encoding::ASCII_8BIT )
|
126
|
+
GIF87SIG = "GIF87".force_encoding( Encoding::ASCII_8BIT )
|
127
|
+
GIF89SIG = "GIF89".force_encoding( Encoding::ASCII_8BIT )
|
128
|
+
|
129
|
+
|
130
|
+
def self.do_layers( contract_address )
|
131
|
+
puts "==> query layers for art collection contract @ >#{contract_address}<:"
|
132
|
+
|
133
|
+
c = Contract.new( contract_address )
|
134
|
+
|
135
|
+
name = c.name
|
136
|
+
symbol = c.symbol
|
137
|
+
totalSupply = c.totalSupply
|
138
|
+
|
139
|
+
|
140
|
+
traitDetails = []
|
141
|
+
n=0
|
142
|
+
loop do
|
143
|
+
m=0
|
144
|
+
loop do
|
145
|
+
rec = c.traitDetails( n, m )
|
146
|
+
break if rec == ['','',false]
|
147
|
+
|
148
|
+
traitDetails << [[n,m], rec ]
|
149
|
+
m += 1
|
150
|
+
sleep( 0.5 )
|
151
|
+
end
|
152
|
+
break if m==0
|
153
|
+
n += 1
|
154
|
+
end
|
155
|
+
|
156
|
+
headers = ['index', 'name', 'type', 'hide']
|
157
|
+
recs = []
|
158
|
+
traitDetails.each do |t|
|
159
|
+
recs << [ t[0].join('/'),
|
160
|
+
t[1][0],
|
161
|
+
t[1][1],
|
162
|
+
t[1][2].to_s]
|
163
|
+
end
|
164
|
+
|
165
|
+
buf = String.new('')
|
166
|
+
buf << headers.join( ', ' )
|
167
|
+
buf << "\n"
|
168
|
+
recs.each do |rec|
|
169
|
+
buf << rec.join( ', ' )
|
170
|
+
buf << "\n"
|
171
|
+
end
|
172
|
+
|
173
|
+
outdir = "./tmp/#{contract_address}"
|
174
|
+
write_text( "#{outdir}/layers.csv", buf )
|
175
|
+
|
176
|
+
#####
|
177
|
+
# try to download all images
|
178
|
+
traitDetails.each do |t|
|
179
|
+
n,m = t[0]
|
180
|
+
data = c.traitData( n, m )
|
181
|
+
|
182
|
+
basename = "#{n}_#{m}"
|
183
|
+
if data.start_with?( PNGSIG )
|
184
|
+
puts "BINGO!! it's a png blob"
|
185
|
+
write_blob( "#{outdir}/#{basename}.png", data )
|
186
|
+
elsif data.start_with?( GIF87SIG ) || data.start_with?( GIF89SIG )
|
187
|
+
puts "BINGO!! it's a gif blob"
|
188
|
+
write_blob( "#{outdir}/#{basename}.gif", data )
|
189
|
+
elsif data.start_with?( JPGSIG )
|
190
|
+
puts "BINGO!! it's a jpg blob"
|
191
|
+
write_blob( "#{outdir}/#{basename}.jpg", data )
|
192
|
+
else
|
193
|
+
puts "!! ERROR - unknown image format; sorry"
|
194
|
+
exit 1
|
195
|
+
end
|
196
|
+
sleep( 0.5 )
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
puts " name: >#{name}<"
|
201
|
+
puts " symbol: >#{symbol}<"
|
202
|
+
puts " totalSupply: >#{totalSupply}<"
|
203
|
+
puts
|
204
|
+
puts " traitDetails:"
|
205
|
+
pp traitDetails
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
end # class Tool
|
132
210
|
end # module ArtQ
|
133
211
|
|
134
212
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: artq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.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: 2022-11-
|
11
|
+
date: 2022-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ethlite
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- Rakefile
|
76
76
|
- bin/artq
|
77
77
|
- lib/artq.rb
|
78
|
+
- lib/artq/contract.rb
|
78
79
|
- lib/artq/version.rb
|
79
80
|
homepage: https://github.com/pixelartexchange/artbase
|
80
81
|
licenses:
|