kittyverse-api 1.0.0
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 +10 -0
- data/README.md +377 -0
- data/Rakefile +28 -0
- data/lib/kittyverse-api.rb +6 -0
- data/lib/kittyverse/api.rb +66 -0
- data/lib/kittyverse/api/client.rb +145 -0
- data/lib/kittyverse/api/service_v0.rb +21 -0
- data/lib/kittyverse/api/service_v1.rb +26 -0
- data/lib/kittyverse/api/version.rb +22 -0
- metadata +93 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e6828c0f838339784ed116260760a2cd0946e36c54b899b762915bd39861a5d6
|
4
|
+
data.tar.gz: a5fab7f2ea46851828a2f196f07221817b97954910d66d450f3874fa13402ea2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 420dfea935617104e0f95ecbcdf82694b8b5743ffe9e0a3ac3c430196be54e5694e34b7f361606b3127f94c375ddb837b6b693c9cbc6f3d3f3e3348c838578cb
|
7
|
+
data.tar.gz: 350712588cabd36589180e79e48164bf5ddb2bd61a344247b91bfac3abaa9c79a5ed0b3338fc1ebec156d026db9cd6b6893a1478442edb58f4195d6ba59c1f68
|
data/CHANGELOG.md
ADDED
data/Manifest.txt
ADDED
data/README.md
ADDED
@@ -0,0 +1,377 @@
|
|
1
|
+
# Kittyverse API
|
2
|
+
|
3
|
+
kittyverse-api - web client (helpers) for using the CryptoKitties unofficial (v0) and official (v1) public (HTTP JSON) APIs
|
4
|
+
|
5
|
+
|
6
|
+
* home :: [github.com/cryptocopycats/kittyverse](https://github.com/cryptocopycats/kittyverse)
|
7
|
+
* bugs :: [github.com/cryptocopycats/kittyverse/issues](https://github.com/cryptocopycats/kittyverse/issues)
|
8
|
+
* gem :: [rubygems.org/gems/kittyverse-api](https://rubygems.org/gems/kittyverse-api)
|
9
|
+
* rdoc :: [rubydoc.info/gems/kittyverse-api](http://rubydoc.info/gems/kittyverse-api)
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
CryptoKitties offers two
|
17
|
+
public HTTP (Web Service) APIs returning
|
18
|
+
data in the structured JSON (JavaScript Object Notation) format.
|
19
|
+
The "original" and unofficial version 0 (v0) service
|
20
|
+
requires no sign-up or API token
|
21
|
+
but is now rate limited (20 requests/minute)
|
22
|
+
and the "eternal closed-beta" official version 1 (v1)
|
23
|
+
service requires a sign-up to the Kittyverse Program
|
24
|
+
(see [`docs.api.cryptokitties.co`](https://docs.api.cryptokitties.co)) to get your API token
|
25
|
+
sent to your email inbox.
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
|
30
|
+
### The "Unofficial" Public API (v0) - No API Token Required
|
31
|
+
|
32
|
+
Let's start with the "classic" public HTTP (Web Service) JSON API.
|
33
|
+
Note: Because this API is "unofficial" you will NOT find
|
34
|
+
any official documentation on what services / endpoints you can call
|
35
|
+
and everything might change at anytime without notice.
|
36
|
+
|
37
|
+
|
38
|
+
|
39
|
+
#### Getting the Statistics for All Cattributes (incl. Purrstiges)
|
40
|
+
|
41
|
+
Use [`GET /cattributes`](https://api.cryptokitties.co/cattributes)
|
42
|
+
to get a list of all cattributes (including purrstiges)
|
43
|
+
with trait types and running totals.
|
44
|
+
|
45
|
+
``` ruby
|
46
|
+
require "kittyverse/api"
|
47
|
+
|
48
|
+
c = Kitties::V0::Client.new
|
49
|
+
c.get_cattributes ## same as get( '/cattributes' )
|
50
|
+
```
|
51
|
+
|
52
|
+
resulting in:
|
53
|
+
|
54
|
+
``` json
|
55
|
+
[{"description":"totesbasic", "type":"pattern", "gene":15, "total":"343048"},
|
56
|
+
{"description":"thicccbrowz", "type":"eyes", "gene":7, "total":"253225"},
|
57
|
+
{"description":"pouty", "type":"mouth", "gene":9, "total":"232226"},
|
58
|
+
{"description":"granitegrey", "type":"colortertiary", "gene":4, "total":"228702"},
|
59
|
+
{"description":"kittencream", "type":"colortertiary", "gene":6, "total":"225798"},
|
60
|
+
...
|
61
|
+
{"description":"hooked", "type":"prestige", "gene":null, "total":"165"},
|
62
|
+
{"description":"landlubber", "type":"prestige", "gene":null, "total":"144"},
|
63
|
+
{"description":"timbers", "type":"prestige", "gene":null, "total":"108"}]
|
64
|
+
```
|
65
|
+
|
66
|
+
Let's save the data in the JSON format pretty printed
|
67
|
+
into a file:
|
68
|
+
|
69
|
+
``` ruby
|
70
|
+
def save( name, data )
|
71
|
+
File.open( "./dl/#{name}.json", 'w:utf-8' ) do |f|
|
72
|
+
f.write JSON.pretty_generate( data )
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
data = c.get_cattributes ## same as get( '/cattributes' )
|
77
|
+
save( "cattributes", data )
|
78
|
+
```
|
79
|
+
|
80
|
+
(Source: [`script/fetch_v0.rb`](https://github.com/cryptocopycats/kittyverse/blob/master/kittyverse-api/script/fetch_v0.rb))
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
Tip: See the chapter 3 in the
|
85
|
+
"[Programming Crypto Collectibles Step-by-Step Book / Guide. Let's start with CryptoKitties & Copycats. Inside Unique Bits & Bytes on the Blockchain...](https://github.com/openblockchains/programming-cryptocollectibles/blob/master/03_cattributes.md)"
|
86
|
+
for how to create your own up-to-date
|
87
|
+
[Cattributes Rarity / Popularity Statistics / Cheatsheet](CATTRIBUTES.md) page.
|
88
|
+
|
89
|
+
|
90
|
+
#### Getting the Kitten #1, #2, #3, ...
|
91
|
+
|
92
|
+
|
93
|
+
Use [`GET /kitties/<id>`](https://api.cryptokitties.co/kitties/1)
|
94
|
+
to get all the kitten's data by id.
|
95
|
+
|
96
|
+
``` ruby
|
97
|
+
c.get_kitty( 1 ) ## same as get( '/kitties/1' )
|
98
|
+
```
|
99
|
+
|
100
|
+
resulting in:
|
101
|
+
|
102
|
+
``` json
|
103
|
+
{ "id": 1,
|
104
|
+
"name": "Genesis",
|
105
|
+
"generation": 0,
|
106
|
+
"created_at": "2017-11-23T06:19:59.000Z",
|
107
|
+
"birthday": "2017-11-23T00:00:00.000Z",
|
108
|
+
"image_url": "https://img.cryptokitties.co/0x06012c8cf97bead5deae237070f9587f8e7a266d/1.png",
|
109
|
+
"image_url_cdn": "https://img.cn.cryptokitties.co/0x06012c8cf97bead5deae237070f9587f8e7a266d/1.png",
|
110
|
+
"color": "sizzurp",
|
111
|
+
"bio": "Greetings, human. I am Genesis...",
|
112
|
+
"is_fancy": true,
|
113
|
+
"is_exclusive": true,
|
114
|
+
"is_special_edition": false,
|
115
|
+
"fancy_type": "Genesis",
|
116
|
+
"fancy_ranking": 1,
|
117
|
+
"language": "en",
|
118
|
+
"is_prestige": false,
|
119
|
+
...
|
120
|
+
}
|
121
|
+
```
|
122
|
+
|
123
|
+
Again let's save the data for kitten #1 and #2
|
124
|
+
in the JSON format pretty printed into files:
|
125
|
+
|
126
|
+
``` ruby
|
127
|
+
data = c.get_kitty( 1 ) ## same as get( '/kitties/1' )
|
128
|
+
save( "kitty1", data )
|
129
|
+
|
130
|
+
data = c.get_kitty( 2 ) ## same as get( '/kitties/2' )
|
131
|
+
save( "kitty2", data )
|
132
|
+
```
|
133
|
+
|
134
|
+
|
135
|
+
#### Getting All Kitties
|
136
|
+
|
137
|
+
Use [`GET /kitties`](https://api.cryptokitties.co/kitties?limit=10) to get all kitties.
|
138
|
+
Search query parameters include:
|
139
|
+
|
140
|
+
- `limit` = `1`-`100`
|
141
|
+
- `offset` = _Integer_
|
142
|
+
<!--
|
143
|
+
- `generation` = _Integer_ ## check if working?
|
144
|
+
-->
|
145
|
+
|
146
|
+
``` ruby
|
147
|
+
c.get_kitties( limit: 10 ) ## same as get( '/kitties?limit=10' )
|
148
|
+
```
|
149
|
+
|
150
|
+
|
151
|
+
#### Getting User Kitties
|
152
|
+
|
153
|
+
Use [`GET /kitties?owner_wallet_address=<0x...>`](https://api.cryptokitties.co/kitties?owner_wallet_address=0xc5e38233cc0d7cff9340e6139367aba498ec9b18&limit=10)
|
154
|
+
with the wallet address to get all the user's kitties.
|
155
|
+
Search query parameters include:
|
156
|
+
|
157
|
+
- `owner_wallet_address` = _Ethereum Address_ (all lowercase a-z)
|
158
|
+
- `limit` = `1`-`100`
|
159
|
+
- `offset` = _Integer_
|
160
|
+
|
161
|
+
``` ruby
|
162
|
+
c.get_kitties( owner_wallet_address: '0xc5e38233cc0d7cff9340e6139367aba498ec9b18', limit: 10 )
|
163
|
+
```
|
164
|
+
|
165
|
+
|
166
|
+
#### Getting User Info
|
167
|
+
|
168
|
+
Use [`GET /user/<0x...>`](https://api.cryptokitties.co/user/0xc5e38233cc0d7cff9340e6139367aba498ec9b18) to get the user info by the wallet address
|
169
|
+
(all lowercase a-z).
|
170
|
+
|
171
|
+
``` ruby
|
172
|
+
c.get_user( '0xc5e38233cc0d7cff9340e6139367aba498ec9b18' )
|
173
|
+
```
|
174
|
+
|
175
|
+
|
176
|
+
#### Getting Auctions - Going, Going, Gone!
|
177
|
+
|
178
|
+
Use [`GET /auctions`](https://api.cryptokitties.co/auctions)
|
179
|
+
to get all auctions. Search query parameters include:
|
180
|
+
|
181
|
+
- `type` = `sale` | `sire`
|
182
|
+
- `status` = `open` | `closed`
|
183
|
+
- `limit` = `1`-`100`
|
184
|
+
- `offset` = _Integer_
|
185
|
+
- `search` = _String_
|
186
|
+
- `orderBy` = `current_price` | ?
|
187
|
+
- `orderDirection` = `asc` | `desc` <!-- check if desc is an option? -->
|
188
|
+
|
189
|
+
<!--
|
190
|
+
- `parents` = `true` | `false` ## what for? working?
|
191
|
+
- `authenticated` = `true` | `false` ## what for
|
192
|
+
-->
|
193
|
+
|
194
|
+
|
195
|
+
``` ruby
|
196
|
+
c.get_auctions( limit: 10 )
|
197
|
+
## note: same as get( '/auctions?limit=2' )
|
198
|
+
c.get_auctions( type: 'sale', limit: 10 )
|
199
|
+
## note: same as get( '/auctions?type=sale&limit=10' )
|
200
|
+
c.get_auctions( type: 'sale', status: 'open', limit: 10 )
|
201
|
+
## note: same as get( '/auctions?type=sale&status=open&limit=10' )
|
202
|
+
```
|
203
|
+
|
204
|
+
|
205
|
+
|
206
|
+
### The Official Public API, Version 1 (v1) - API Token Required - Apply Here
|
207
|
+
|
208
|
+
Note: The Official Public API requires a token.
|
209
|
+
Sign up for the Kittyverse program
|
210
|
+
at [`docs.api.cryptokitties.co`](https://docs.api.cryptokitties.co)
|
211
|
+
to request an API token
|
212
|
+
and if all works out the CryptoKitties team will send you over
|
213
|
+
the API token via email to your inbox. Good luck.
|
214
|
+
|
215
|
+
|
216
|
+
Using the kittyverse library you can:
|
217
|
+
|
218
|
+
(1) Add the token to your computing environment (ENV):
|
219
|
+
|
220
|
+
```
|
221
|
+
SET KITTIES_TOKEN=<your_token_here>
|
222
|
+
```
|
223
|
+
|
224
|
+
(2) Or configure the kittyverse library with a code block:
|
225
|
+
|
226
|
+
``` ruby
|
227
|
+
Kitties.configure do |config|
|
228
|
+
config.token = "<your_token_here>"
|
229
|
+
end
|
230
|
+
```
|
231
|
+
|
232
|
+
(3) Or pass the token into the client:
|
233
|
+
|
234
|
+
``` ruby
|
235
|
+
c = Kitties::V1::Client.new( token: "<your_token_here>" )
|
236
|
+
```
|
237
|
+
|
238
|
+
|
239
|
+
|
240
|
+
#### Getting the Statistics for all Cattributes (excl. Purrstiges)
|
241
|
+
|
242
|
+
Use `GET /cattributes`
|
243
|
+
to get a list of all cattributes
|
244
|
+
with trait types and running totals.
|
245
|
+
Note: The new official service call does NOT include the purrstiges traits.
|
246
|
+
|
247
|
+
``` ruby
|
248
|
+
c = Kitties::V1::Client.new
|
249
|
+
c.get_cattributes ## same as get( '/cattributes' )
|
250
|
+
```
|
251
|
+
|
252
|
+
resulting in:
|
253
|
+
|
254
|
+
``` json
|
255
|
+
[{"description":"shadowgrey", "type":"colorprimary", "gene":0, "total":133927},
|
256
|
+
{"description":"salmon", "type":"colorprimary", "gene":1, "total":90376},
|
257
|
+
{"description":"greymatter", "type":"colorprimary", "gene":10, "total":196549},
|
258
|
+
...
|
259
|
+
]
|
260
|
+
```
|
261
|
+
|
262
|
+
Again let's save the data in the JSON format pretty printed
|
263
|
+
into a file:
|
264
|
+
|
265
|
+
``` ruby
|
266
|
+
data = c.get_cattributes ## same as get( '/cattributes' )
|
267
|
+
save( "cattributes", data )
|
268
|
+
```
|
269
|
+
|
270
|
+
|
271
|
+
#### Getting the Kitten #1, #2, #3, ...
|
272
|
+
|
273
|
+
Use `GET /kitties/<id>`
|
274
|
+
to get all the kitten's data by id.
|
275
|
+
|
276
|
+
``` ruby
|
277
|
+
c.get_kitty( 1 ) ## same as get( '/kitties/1' )
|
278
|
+
```
|
279
|
+
|
280
|
+
resulting in:
|
281
|
+
|
282
|
+
``` json
|
283
|
+
{ "id": 1,
|
284
|
+
"name": "Genesis",
|
285
|
+
"generation": 0,
|
286
|
+
"created_at": "2017-11-23T06:19:59Z",
|
287
|
+
"image_url": "https://img.cryptokitties.co/0x06012c8cf97bead5deae237070f9587f8e7a266d/1.png",
|
288
|
+
"image_url_cdn": "https://img.cn.cryptokitties.co/0x06012c8cf97bead5deae237070f9587f8e7a266d/1.png",
|
289
|
+
"image_url_png": "https://img.cryptokitties.co/0x06012c8cf97bead5deae237070f9587f8e7a266d/1.png",
|
290
|
+
"image_path": "",
|
291
|
+
"color": "sizzurp",
|
292
|
+
"bio": "Greetings, human. I am #{name}...",
|
293
|
+
"is_fancy": true,
|
294
|
+
"is_exclusive": true,
|
295
|
+
"fancy_type": "Genesis",
|
296
|
+
"fancy_ranking": 1,
|
297
|
+
"language": "en",
|
298
|
+
"is_prestige": false,
|
299
|
+
...
|
300
|
+
}
|
301
|
+
```
|
302
|
+
|
303
|
+
Note: The new official service call does NOT (yet) include the `birthday`, `is_special_edition` and other "newer" properties.
|
304
|
+
|
305
|
+
<!--
|
306
|
+
check if v1 includes:
|
307
|
+
- birthday
|
308
|
+
- is_special_edition
|
309
|
+
- etc.
|
310
|
+
-->
|
311
|
+
|
312
|
+
Again let's save the data for kitten #1 and #2
|
313
|
+
in the JSON format pretty printed into files:
|
314
|
+
|
315
|
+
``` ruby
|
316
|
+
data = c.get_kitty( 1 ) ## same as get( '/kitties/1' )
|
317
|
+
save( "kitty1", data )
|
318
|
+
|
319
|
+
data = c.get_kitty( 2 ) ## same as get( '/kitties/2' )
|
320
|
+
save( "kitty2", data )
|
321
|
+
```
|
322
|
+
|
323
|
+
|
324
|
+
#### Getting Colors for Body, Eyes, ...
|
325
|
+
|
326
|
+
Use `GET /colors/body|eyes|secondary|tertiary`,
|
327
|
+
to get a list of all hexadecimal r(ed)/g(gree)/b(lue) color codes
|
328
|
+
for the body, eyes, secondary and
|
329
|
+
tertiary color cattributes - known in the official kitties
|
330
|
+
profile pages as base color, eye color, highlight color and accent color.
|
331
|
+
|
332
|
+
|
333
|
+
```ruby
|
334
|
+
data = c.get_colors_body ## same as get( '/colors/body' )
|
335
|
+
save( "colors-body", data )
|
336
|
+
data = c.get_colors_eyes ## same as get( '/colors/eyes' )
|
337
|
+
save( "colors-eyes", data )
|
338
|
+
data = c.get_colors_secondary ## same as get( '/colors/secondary' )
|
339
|
+
save( "colors-secondary", data )
|
340
|
+
data = c.get_colors_tertiary ## same as get( '/colors/tertiary' )
|
341
|
+
save( "colors-tertiary", data )
|
342
|
+
```
|
343
|
+
|
344
|
+
#### Getting Everything Else
|
345
|
+
|
346
|
+
If there's no pre-made convenience wrapper in the kittyverse library (yet) for the
|
347
|
+
service, use the generic `get` method. Example:
|
348
|
+
|
349
|
+
``` ruby
|
350
|
+
data = c.get( '/cattributes/eyes/12' )
|
351
|
+
save( "cattributes-eyes-12", data )
|
352
|
+
|
353
|
+
data = c.get( '/kitties?gen=3-4' ) # or
|
354
|
+
data = c.get( '/kitties', gen: '3-4' )
|
355
|
+
save( "kitties-gen_3-4", data )
|
356
|
+
|
357
|
+
# ...
|
358
|
+
```
|
359
|
+
|
360
|
+
|
361
|
+
That's it for now.
|
362
|
+
Happy data wrangling and cat herding with ruby.
|
363
|
+
|
364
|
+
|
365
|
+
|
366
|
+
|
367
|
+
## License
|
368
|
+
|
369
|
+
![](https://publicdomainworks.github.io/buttons/zero88x31.png)
|
370
|
+
|
371
|
+
The `kittyverse` scripts are dedicated to the public domain.
|
372
|
+
Use it as you please with no restrictions whatsoever.
|
373
|
+
|
374
|
+
|
375
|
+
## Questions? Comments?
|
376
|
+
|
377
|
+
Post them on the [cryptokitties reddit](https://www.reddit.com/r/cryptokitties). Thanks.
|
data/Rakefile
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'hoe'
|
2
|
+
require './lib/kittyverse/api/version.rb'
|
3
|
+
|
4
|
+
Hoe.spec 'kittyverse-api' do
|
5
|
+
|
6
|
+
self.version = KittyverseClient::VERSION
|
7
|
+
|
8
|
+
self.summary = "kittyverse-api - web client (helpers) for using the CryptoKitties unofficial (v0) and official (v1) public (HTTP JSON) APIs"
|
9
|
+
self.description = summary
|
10
|
+
|
11
|
+
self.urls = { home: 'https://github.com/cryptocopycats/kittyverse'}
|
12
|
+
|
13
|
+
self.author = 'Gerald Bauer'
|
14
|
+
self.email = 'wwwmake@googlegroups.com'
|
15
|
+
|
16
|
+
# switch extension to .markdown for gihub formatting
|
17
|
+
self.readme_file = 'README.md'
|
18
|
+
self.history_file = 'CHANGELOG.md'
|
19
|
+
|
20
|
+
self.extra_deps = []
|
21
|
+
|
22
|
+
self.licenses = ['Public Domain']
|
23
|
+
|
24
|
+
self.spec_extras = {
|
25
|
+
required_ruby_version: '>= 2.2.2'
|
26
|
+
}
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
## std libs
|
2
|
+
require 'pp'
|
3
|
+
require 'date'
|
4
|
+
require 'time'
|
5
|
+
require 'json'
|
6
|
+
require 'uri'
|
7
|
+
require 'net/http'
|
8
|
+
require 'net/https'
|
9
|
+
require 'fileutils'
|
10
|
+
|
11
|
+
|
12
|
+
## our own code
|
13
|
+
require 'kittyverse/api/version' # note: let version always go first
|
14
|
+
require 'kittyverse/api/client'
|
15
|
+
require 'kittyverse/api/service_v0'
|
16
|
+
require 'kittyverse/api/service_v1'
|
17
|
+
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
module Kitties
|
22
|
+
|
23
|
+
class Configuration
|
24
|
+
attr_accessor :token
|
25
|
+
attr_accessor :debug
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
# try default setup via ENV variables
|
29
|
+
@token = ENV[ 'KITTIES_TOKEN' ]
|
30
|
+
@debug = false
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
## lets you use
|
35
|
+
## Kitties.configure do |config|
|
36
|
+
## config.token = 'secret'
|
37
|
+
## end
|
38
|
+
def self.configuration
|
39
|
+
@configuration ||= Configuration.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.configure
|
43
|
+
yield( configuration )
|
44
|
+
end
|
45
|
+
|
46
|
+
### debug convenience helpers
|
47
|
+
def self.debug?() configuration.debug; end
|
48
|
+
def self.debug=(value) configuration.debug = value; end
|
49
|
+
|
50
|
+
|
51
|
+
## track last response
|
52
|
+
def self.last_response() @last_response; end
|
53
|
+
def self.last_response=(value) @last_response = value; end
|
54
|
+
|
55
|
+
|
56
|
+
## CLIENT_V0 = V0::Client.new
|
57
|
+
## CLIENT_V1 = V1::Client.new
|
58
|
+
##
|
59
|
+
## def self.v0() CLIENT_V0; end
|
60
|
+
## def self.v1() CLIENT_V1; end
|
61
|
+
end # module Kitties
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
# say hello
|
66
|
+
puts KittyverseClient.banner
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Kitties
|
2
|
+
|
3
|
+
class Error < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
####
|
7
|
+
# todo/check:
|
8
|
+
# rename to HttpRequestError or similar??
|
9
|
+
# use "common" error class - why? why not?
|
10
|
+
class HttpError < Error
|
11
|
+
attr_reader :code, :message
|
12
|
+
|
13
|
+
def initialize( code, message )
|
14
|
+
@code, @message = code, message
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
"HTTP request failed (NOK) => #{@code} #{@message}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
class Response ## track last response
|
24
|
+
attr_accessor :code, :message,
|
25
|
+
:headers, :body
|
26
|
+
|
27
|
+
def initialize( code, message, headers, body )
|
28
|
+
@code, @message, @headers, @body = code, message, headers, body
|
29
|
+
end
|
30
|
+
|
31
|
+
## ratelimit convenience helpers (for headers)
|
32
|
+
## note: all values of headers are arrays e.g.:
|
33
|
+
## {"x-ratelimit-limit"=>["20"],
|
34
|
+
## "x-ratelimit-remaining"=>["19"],
|
35
|
+
## "x-ratelimit-reset"=>["1558206970"],
|
36
|
+
## "content-length"=>["776"], ... }
|
37
|
+
|
38
|
+
def ratelimit_limit
|
39
|
+
limit = @headers['x-ratelimit-limit']
|
40
|
+
limit ? limit[0].to_i : nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def ratelimit_remaining
|
44
|
+
remaining = @headers['x-ratelimit-remaining']
|
45
|
+
remaining ? remaining[0].to_i : nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def ratelimit_reset?
|
49
|
+
## x-ratelimit-reset => 1558079593 ## - assume it's unix epoch time
|
50
|
+
reset = @headers['x-ratelimit-reset']
|
51
|
+
reset ? (reset[0].to_i < Time.now.to_i) : true ## always assume true (unlimited requests)
|
52
|
+
end
|
53
|
+
|
54
|
+
def ratelimit_reset
|
55
|
+
## x-ratelimit-reset => 1558079593 ## - assume it's unix epoch time
|
56
|
+
reset = @headers['x-ratelimit-reset']
|
57
|
+
reset ? Time.at(reset[0].to_i) : nil
|
58
|
+
end
|
59
|
+
end ## class Response (used for tracking last(_response))
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
class Client
|
64
|
+
|
65
|
+
##
|
66
|
+
## todo: add (optional) close with @http.close - why? why not?
|
67
|
+
|
68
|
+
def initialize( base_uri:, token: nil )
|
69
|
+
uri = URI.parse( base_uri )
|
70
|
+
@http = Net::HTTP.new( uri.host, uri.port )
|
71
|
+
if uri.instance_of? URI::HTTPS
|
72
|
+
@http.use_ssl = true
|
73
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
74
|
+
end
|
75
|
+
|
76
|
+
@base_request_uri = uri.request_uri ## e.g. save /v1 etc.
|
77
|
+
## puts "base_request_uri: >#{@base_request_uri}<"
|
78
|
+
|
79
|
+
@request_headers = if token
|
80
|
+
{ "x-api-token" => token }
|
81
|
+
else
|
82
|
+
{}
|
83
|
+
end
|
84
|
+
end # method initialize
|
85
|
+
|
86
|
+
def get( service, **params )
|
87
|
+
|
88
|
+
## add url-encoded query string from params hash e.g. ?limit=100&type=sale
|
89
|
+
unless params.empty?
|
90
|
+
query = URI.encode_www_form( params )
|
91
|
+
service += "?#{query}"
|
92
|
+
end
|
93
|
+
|
94
|
+
puts "GET #{service}"
|
95
|
+
|
96
|
+
request_uri = if @base_request_uri == "/"
|
97
|
+
service
|
98
|
+
else
|
99
|
+
"#{@base_request_uri}#{service}" ## e.g. add /v1 etc.
|
100
|
+
end
|
101
|
+
|
102
|
+
pp @request_headers
|
103
|
+
|
104
|
+
req = Net::HTTP::Get.new( request_uri, @request_headers )
|
105
|
+
|
106
|
+
res = @http.request(req)
|
107
|
+
|
108
|
+
headers = res.to_hash ## get all response headers
|
109
|
+
|
110
|
+
if Kitties.debug?
|
111
|
+
# Iterate all response headers.
|
112
|
+
# res.each_header do |key, value|
|
113
|
+
# p "#{key} => #{value}"
|
114
|
+
# end
|
115
|
+
pp headers
|
116
|
+
# => "content-type => application/json; charset=utf-8"
|
117
|
+
# => "x-ratelimit-limit => 20"
|
118
|
+
# => "x-ratelimit-remaining => 19"
|
119
|
+
# => "x-ratelimit-reset => 1558079593"
|
120
|
+
# ...
|
121
|
+
end
|
122
|
+
|
123
|
+
body = res.read_body
|
124
|
+
## pp body
|
125
|
+
|
126
|
+
## track last response
|
127
|
+
Kitties.last_response = Response.new( res.code,
|
128
|
+
res.message,
|
129
|
+
headers,
|
130
|
+
body )
|
131
|
+
|
132
|
+
if res.code != '200'
|
133
|
+
raise HttpError.new( res.code, res.message )
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
json = JSON.parse( body ) ## use just body (any difference?) - why? why not?
|
138
|
+
## pp json
|
139
|
+
json
|
140
|
+
end # method get
|
141
|
+
|
142
|
+
end ## class Client
|
143
|
+
|
144
|
+
|
145
|
+
end # module Kitties
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Kitties
|
2
|
+
module V0
|
3
|
+
class Client < ::Kitties::Client
|
4
|
+
def initialize
|
5
|
+
super( base_uri: "https://api.cryptokitties.co" )
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_cattributes() get('/cattributes'); end
|
9
|
+
def get_kitty( id ) get("/kitties/#{id}"); end ## use get_kitty_by_id - why? why not?
|
10
|
+
alias_method :get_kitten, :get_kitty
|
11
|
+
|
12
|
+
def get_kitties( **params ) get( '/kitties', **params ); end
|
13
|
+
def get_auctions( **params ) get( '/auctions', **params ); end
|
14
|
+
def get_user( addr ) get( "/user/#{addr}" ); end
|
15
|
+
|
16
|
+
def get_network_status() get( '/network-status' ); end
|
17
|
+
|
18
|
+
end # class Client
|
19
|
+
end # module V0
|
20
|
+
end # module Kitties
|
21
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Kitties
|
2
|
+
module V1
|
3
|
+
###
|
4
|
+
## see https://docs.api.cryptokitties.co
|
5
|
+
|
6
|
+
class Client < ::Kitties::Client
|
7
|
+
def initialize
|
8
|
+
super( base_uri: "https://public.api.cryptokitties.co/v1",
|
9
|
+
token: Kitties.configuration.token )
|
10
|
+
end
|
11
|
+
|
12
|
+
def get_cattributes() get('/cattributes'); end
|
13
|
+
def get_kitty( id ) get("/kitties/#{id}"); end ## use get_kitty_by_id - why? why not?
|
14
|
+
alias_method :get_kitten, :get_kitty
|
15
|
+
|
16
|
+
def get_colors_body() get('/colors/body'); end
|
17
|
+
def get_colors_eyes() get('/colors/eyes'); end
|
18
|
+
def get_colors_secondary() get('/colors/secondary'); end
|
19
|
+
def get_colors_tertiary() get('/colors/tertiary'); end
|
20
|
+
|
21
|
+
end # class Client
|
22
|
+
end # module V1
|
23
|
+
end # module Kitties
|
24
|
+
|
25
|
+
|
26
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module KittyverseClient
|
3
|
+
|
4
|
+
MAJOR = 1
|
5
|
+
MINOR = 0
|
6
|
+
PATCH = 0
|
7
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
8
|
+
|
9
|
+
def self.version
|
10
|
+
VERSION
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.banner
|
14
|
+
"kittyverse-api/#{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.dirname(__FILE__)))) )
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module KittyverseClient
|
22
|
+
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kittyverse-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gerald Bauer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-02-17 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rdoc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '7'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '7'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: hoe
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '3.22'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.22'
|
47
|
+
description: kittyverse-api - web client (helpers) for using the CryptoKitties unofficial
|
48
|
+
(v0) and official (v1) public (HTTP JSON) APIs
|
49
|
+
email: wwwmake@googlegroups.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files:
|
53
|
+
- CHANGELOG.md
|
54
|
+
- Manifest.txt
|
55
|
+
- README.md
|
56
|
+
files:
|
57
|
+
- CHANGELOG.md
|
58
|
+
- Manifest.txt
|
59
|
+
- README.md
|
60
|
+
- Rakefile
|
61
|
+
- lib/kittyverse-api.rb
|
62
|
+
- lib/kittyverse/api.rb
|
63
|
+
- lib/kittyverse/api/client.rb
|
64
|
+
- lib/kittyverse/api/service_v0.rb
|
65
|
+
- lib/kittyverse/api/service_v1.rb
|
66
|
+
- lib/kittyverse/api/version.rb
|
67
|
+
homepage: https://github.com/cryptocopycats/kittyverse
|
68
|
+
licenses:
|
69
|
+
- Public Domain
|
70
|
+
metadata: {}
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options:
|
73
|
+
- "--main"
|
74
|
+
- README.md
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: 2.2.2
|
82
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubygems_version: 3.1.4
|
89
|
+
signing_key:
|
90
|
+
specification_version: 4
|
91
|
+
summary: kittyverse-api - web client (helpers) for using the CryptoKitties unofficial
|
92
|
+
(v0) and official (v1) public (HTTP JSON) APIs
|
93
|
+
test_files: []
|