bitflyer 0.2.0 → 0.2.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 +5 -5
- data/Gemfile.lock +8 -59
- data/bitflyer.gemspec +1 -1
- data/lib/bitflyer/realtime/client.rb +12 -18
- data/lib/bitflyer/realtime/websocket.rb +136 -0
- data/lib/bitflyer/version.rb +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 96469fe331a89e6551b43e7224b0eb9dbe7e21a5f6c6811068d1fcbdc6d73472
|
|
4
|
+
data.tar.gz: 4480a1a3aa087333adf60e31b60c90d568a403b43acd348aac0d60c3f8de1c65
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21ad55e0aedf232c88aa20ed7bc49ebe5f3a92acff3dfe18772bb4d4b6576f07f7fad79926372f6fe2ca840175064b75fef6db767e246d882d4624845082bd9c
|
|
7
|
+
data.tar.gz: 95570ef23a9d6a6abb4667406a7fe19b41e81ec0b3e0cfd433d1d77b2df9a3f2224616eb5c4ae92abcc8ede4769953cd7c060ec0e7da4b5d35bc9ca6ab7e156f
|
data/Gemfile.lock
CHANGED
|
@@ -1,74 +1,21 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
bitflyer (0.2.
|
|
4
|
+
bitflyer (0.2.1)
|
|
5
5
|
faraday (~> 0.14.0)
|
|
6
6
|
faraday_middleware (~> 0.12.0)
|
|
7
|
-
|
|
7
|
+
websocket-client-simple (~> 0.3.0)
|
|
8
8
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
11
11
|
specs:
|
|
12
|
-
celluloid (0.17.3)
|
|
13
|
-
celluloid-essentials
|
|
14
|
-
celluloid-extras
|
|
15
|
-
celluloid-fsm
|
|
16
|
-
celluloid-pool
|
|
17
|
-
celluloid-supervision
|
|
18
|
-
timers (>= 4.1.1)
|
|
19
|
-
celluloid-essentials (0.20.5)
|
|
20
|
-
timers (>= 4.1.1)
|
|
21
|
-
celluloid-extras (0.20.5)
|
|
22
|
-
timers (>= 4.1.1)
|
|
23
|
-
celluloid-fsm (0.20.5)
|
|
24
|
-
timers (>= 4.1.1)
|
|
25
|
-
celluloid-pool (0.20.5)
|
|
26
|
-
timers (>= 4.1.1)
|
|
27
|
-
celluloid-supervision (0.20.6)
|
|
28
|
-
timers (>= 4.1.1)
|
|
29
|
-
concurrent-ruby (1.0.5)
|
|
30
12
|
diff-lcs (1.3)
|
|
31
|
-
|
|
32
|
-
concurrent-ruby (~> 1.0)
|
|
33
|
-
dry-container (0.6.0)
|
|
34
|
-
concurrent-ruby (~> 1.0)
|
|
35
|
-
dry-configurable (~> 0.1, >= 0.1.3)
|
|
36
|
-
dry-core (0.4.2)
|
|
37
|
-
concurrent-ruby (~> 1.0)
|
|
38
|
-
dry-equalizer (0.2.0)
|
|
39
|
-
dry-logic (0.4.2)
|
|
40
|
-
dry-container (~> 0.2, >= 0.2.6)
|
|
41
|
-
dry-core (~> 0.2)
|
|
42
|
-
dry-equalizer (~> 0.2)
|
|
43
|
-
dry-types (0.12.2)
|
|
44
|
-
concurrent-ruby (~> 1.0)
|
|
45
|
-
dry-configurable (~> 0.1)
|
|
46
|
-
dry-container (~> 0.3)
|
|
47
|
-
dry-core (~> 0.2, >= 0.2.1)
|
|
48
|
-
dry-equalizer (~> 0.2)
|
|
49
|
-
dry-logic (~> 0.4, >= 0.4.2)
|
|
50
|
-
inflecto (~> 0.0.0, >= 0.0.2)
|
|
51
|
-
dry-validation (0.11.1)
|
|
52
|
-
concurrent-ruby (~> 1.0)
|
|
53
|
-
dry-configurable (~> 0.1, >= 0.1.3)
|
|
54
|
-
dry-core (~> 0.2, >= 0.2.1)
|
|
55
|
-
dry-equalizer (~> 0.2)
|
|
56
|
-
dry-logic (~> 0.4, >= 0.4.0)
|
|
57
|
-
dry-types (~> 0.12.0)
|
|
13
|
+
event_emitter (0.2.6)
|
|
58
14
|
faraday (0.14.0)
|
|
59
15
|
multipart-post (>= 1.2, < 3)
|
|
60
16
|
faraday_middleware (0.12.2)
|
|
61
17
|
faraday (>= 0.7.4, < 1.0)
|
|
62
|
-
hitimes (1.2.6)
|
|
63
|
-
httpclient (2.8.3)
|
|
64
|
-
inflecto (0.0.2)
|
|
65
|
-
json (2.1.0)
|
|
66
18
|
multipart-post (2.0.0)
|
|
67
|
-
pubnub (4.0.27)
|
|
68
|
-
celluloid (~> 0.17)
|
|
69
|
-
dry-validation (~> 0.10)
|
|
70
|
-
httpclient (~> 2.8, >= 2.8.3)
|
|
71
|
-
json (>= 1.8, < 3)
|
|
72
19
|
rake (12.3.0)
|
|
73
20
|
rspec (3.7.0)
|
|
74
21
|
rspec-core (~> 3.7.0)
|
|
@@ -83,8 +30,10 @@ GEM
|
|
|
83
30
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
84
31
|
rspec-support (~> 3.7.0)
|
|
85
32
|
rspec-support (3.7.1)
|
|
86
|
-
|
|
87
|
-
|
|
33
|
+
websocket (1.2.8)
|
|
34
|
+
websocket-client-simple (0.3.0)
|
|
35
|
+
event_emitter
|
|
36
|
+
websocket
|
|
88
37
|
|
|
89
38
|
PLATFORMS
|
|
90
39
|
ruby
|
|
@@ -96,4 +45,4 @@ DEPENDENCIES
|
|
|
96
45
|
rspec
|
|
97
46
|
|
|
98
47
|
BUNDLED WITH
|
|
99
|
-
1.
|
|
48
|
+
1.17.2
|
data/bitflyer.gemspec
CHANGED
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
|
|
20
20
|
spec.add_dependency 'faraday', '~> 0.14.0'
|
|
21
21
|
spec.add_dependency 'faraday_middleware', '~> 0.12.0'
|
|
22
|
-
spec.add_dependency '
|
|
22
|
+
spec.add_dependency 'websocket-client-simple', '~> 0.3.0'
|
|
23
23
|
spec.add_development_dependency 'bundler', '~> 1.12'
|
|
24
24
|
spec.add_development_dependency 'rake'
|
|
25
25
|
spec.add_development_dependency 'rspec'
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
require_relative './websocket'
|
|
2
2
|
|
|
3
3
|
module Bitflyer
|
|
4
4
|
module Realtime
|
|
5
|
-
PUBNUB_SUBSCRIBE_KEY = 'sub-c-52a9ab50-291b-11e5-baaa-0619f8945a4f'.freeze
|
|
6
5
|
CHANNEL_NAMES = [
|
|
7
6
|
'lightning_board_snapshot_BTC_JPY',
|
|
8
7
|
'lightning_board_snapshot_FX_BTC_JPY',
|
|
@@ -22,25 +21,20 @@ module Bitflyer
|
|
|
22
21
|
'lightning_executions_BCH_BTC'
|
|
23
22
|
].freeze
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
attr_accessor *Realtime::CHANNEL_NAMES.map { |name| name.gsub('lightning_', '').downcase.to_sym }
|
|
24
|
+
SOCKET_HOST = 'https://io.lightstream.bitflyer.com'
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
class Client
|
|
27
|
+
attr_accessor :websocket_client, :ping_interval, :ping_timeout, :last_ping_at, :last_pong_at
|
|
30
28
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
presence: ->(envelope) {},
|
|
38
|
-
status: ->(envelope) {}
|
|
39
|
-
)
|
|
29
|
+
Realtime::CHANNEL_NAMES.each do |channel_name|
|
|
30
|
+
define_method "#{channel_name.gsub('lightning_', '').downcase.to_sym}=" do |callback|
|
|
31
|
+
@websocket_client.subscribe(channel_name: channel_name.to_sym, &callback)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
40
34
|
|
|
41
|
-
|
|
42
|
-
@
|
|
35
|
+
def initialize
|
|
36
|
+
@websocket_client = Bitflyer::Realtime::WebSocketClient.new(host: SOCKET_HOST)
|
|
43
37
|
end
|
|
44
38
|
end
|
|
45
39
|
end
|
|
46
|
-
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
require 'websocket-client-simple'
|
|
2
|
+
|
|
3
|
+
module Bitflyer
|
|
4
|
+
module Realtime
|
|
5
|
+
class WebSocketClient
|
|
6
|
+
attr_accessor :websocket_client, :channel_name, :channel_callbacks, :ping_interval, :ping_timeout,
|
|
7
|
+
:last_ping_at, :last_pong_at, :error
|
|
8
|
+
|
|
9
|
+
def initialize(host:, debug: false)
|
|
10
|
+
@host = host
|
|
11
|
+
@debug = debug
|
|
12
|
+
@error = nil
|
|
13
|
+
@channel_names = []
|
|
14
|
+
@channel_callbacks = {}
|
|
15
|
+
connect
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def subscribe(channel_name:, &block)
|
|
19
|
+
debug_log "Subscribe #{channel_name}"
|
|
20
|
+
@channel_names = (@channel_names + [channel_name]).uniq
|
|
21
|
+
@channel_callbacks[channel_name] = block
|
|
22
|
+
websocket_client.send "42#{['subscribe', channel_name].to_json}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def connect
|
|
26
|
+
@websocket_client = WebSocket::Client::Simple.connect "#{@host}/socket.io/?transport=websocket"
|
|
27
|
+
this = self
|
|
28
|
+
|
|
29
|
+
Thread.new do
|
|
30
|
+
loop do
|
|
31
|
+
sleep 1
|
|
32
|
+
if @websocket_client && @websocket_client.open?
|
|
33
|
+
send_ping
|
|
34
|
+
wait_pong
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
Thread.new do
|
|
40
|
+
loop do
|
|
41
|
+
sleep 1
|
|
42
|
+
next unless @error
|
|
43
|
+
reconnect
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
@websocket_client.on(:message) { |payload| this.handle_message(payload: payload) }
|
|
48
|
+
@websocket_client.on(:error) { |error| this.handle_error(error: error) }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def send_ping
|
|
52
|
+
return unless @last_ping_at && @ping_interval
|
|
53
|
+
return unless Time.now.to_i - @last_ping_at > @ping_interval / 1000
|
|
54
|
+
|
|
55
|
+
debug_log 'Sent ping'
|
|
56
|
+
@websocket_client.send "2"
|
|
57
|
+
@last_ping_at = Time.now.to_i
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def wait_pong
|
|
61
|
+
return unless @last_pong_at && @ping_timeout
|
|
62
|
+
return unless Time.now.to_i - @last_pong_at > @ping_timeout / 1000
|
|
63
|
+
|
|
64
|
+
debug_log 'Timed out waiting pong'
|
|
65
|
+
@websocket_client.close
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def reconnect
|
|
69
|
+
return unless @error
|
|
70
|
+
debug_log 'Reconnecting...'
|
|
71
|
+
|
|
72
|
+
@error = nil
|
|
73
|
+
@websocket_client.close if @websocket_client.open?
|
|
74
|
+
connect
|
|
75
|
+
@channel_names.each do |channel_name|
|
|
76
|
+
debug_log "42#{{ subscribe: channel_name }.to_json}"
|
|
77
|
+
websocket_client.send "42#{['subscribe', channel_name].to_json}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def handle_error(error:)
|
|
82
|
+
debug_log error
|
|
83
|
+
return unless error.kind_of? Errno::ECONNRESET
|
|
84
|
+
reconnect
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def handle_message(payload:)
|
|
88
|
+
debug_log payload.data
|
|
89
|
+
return unless payload.data =~ /^\d+/
|
|
90
|
+
code, body = payload.data.scan(/^(\d+)(.*)$/)[0]
|
|
91
|
+
|
|
92
|
+
case code.to_i
|
|
93
|
+
when 0 then setup_by_response(json: body)
|
|
94
|
+
when 3 then receive_pong
|
|
95
|
+
when 41 then disconnect
|
|
96
|
+
when 42 then emit_message(json: body)
|
|
97
|
+
end
|
|
98
|
+
rescue => e
|
|
99
|
+
puts e
|
|
100
|
+
puts e.backtrace.join("\n")
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def setup_by_response(json:)
|
|
104
|
+
body = JSON.parse json
|
|
105
|
+
@ping_interval = body["pingInterval"].to_i || 25000
|
|
106
|
+
@ping_timeout = body["pingTimeout"].to_i || 60000
|
|
107
|
+
@last_ping_at = Time.now.to_i
|
|
108
|
+
@last_pong_at = Time.now.to_i
|
|
109
|
+
channel_callbacks.each do |channel_name, _|
|
|
110
|
+
websocket_client.send "42#{['subscribe', channel_name].to_json}"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def receive_pong
|
|
115
|
+
debug_log 'Received pong'
|
|
116
|
+
@last_pong_at = Time.now.to_i
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def disconnect
|
|
120
|
+
debug_log 'Disconnecting from server...'
|
|
121
|
+
@error = true
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def emit_message(json:)
|
|
125
|
+
channel_name, *messages = JSON.parse json
|
|
126
|
+
return unless channel_name
|
|
127
|
+
messages.each { |message| @channel_callbacks[channel_name.to_sym]&.call(message) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def debug_log(message)
|
|
131
|
+
return unless @debug
|
|
132
|
+
p message
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
data/lib/bitflyer/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bitflyer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yuji Ueki
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2019-01-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -39,19 +39,19 @@ dependencies:
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: 0.12.0
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
|
-
name:
|
|
42
|
+
name: websocket-client-simple
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version:
|
|
47
|
+
version: 0.3.0
|
|
48
48
|
type: :runtime
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version:
|
|
54
|
+
version: 0.3.0
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: bundler
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -114,6 +114,7 @@ files:
|
|
|
114
114
|
- lib/bitflyer/http/public.rb
|
|
115
115
|
- lib/bitflyer/realtime.rb
|
|
116
116
|
- lib/bitflyer/realtime/client.rb
|
|
117
|
+
- lib/bitflyer/realtime/websocket.rb
|
|
117
118
|
- lib/bitflyer/version.rb
|
|
118
119
|
homepage: https://github.com/unhappychoice/bitflyer
|
|
119
120
|
licenses:
|
|
@@ -135,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
135
136
|
version: '0'
|
|
136
137
|
requirements: []
|
|
137
138
|
rubyforge_project:
|
|
138
|
-
rubygems_version: 2.6
|
|
139
|
+
rubygems_version: 2.7.6
|
|
139
140
|
signing_key:
|
|
140
141
|
specification_version: 4
|
|
141
142
|
summary: Bitflyer API wrapper
|