kittyverse-api 1.0.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 +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
|
+

|
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: []
|