sequence-sdk 1.0.2 → 1.0.3
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/lib/sequence/account.rb +3 -3
- data/lib/sequence/asset.rb +3 -3
- data/lib/sequence/balance.rb +1 -1
- data/lib/sequence/client.rb +9 -5
- data/lib/sequence/contract.rb +1 -1
- data/lib/sequence/dev_utils.rb +1 -1
- data/lib/sequence/errors.rb +2 -2
- data/lib/sequence/http_wrapper.rb +111 -0
- data/lib/sequence/key.rb +3 -3
- data/lib/sequence/session.rb +95 -0
- data/lib/sequence/stats.rb +1 -1
- data/lib/sequence/transaction.rb +4 -4
- data/lib/sequence/version.rb +1 -1
- metadata +29 -28
- data/lib/sequence/connection.rb +0 -164
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 13297573e64f55ffcba16f88365a13ee4540d7c3
|
4
|
+
data.tar.gz: e94b5d7ab7f11a8dfe48140fceea4c921d56b2d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f3231c2b04e1e9a99a8318aac330fdd4ea1eb1bb54ab0510c9cbfa49335454fbfaaa8114d823bc70a799ce89ef6617c9502940f33c48ae4dd5240bd2a2939dea
|
7
|
+
data.tar.gz: dad7408ea6e7c10eb8e793faffa29150e95cdaf39a4c651c7566eea2760c46ed0a16e60a545b6993f3e1aab48921dfd03b624a7fa9c96e2511c528c5f0d311d5
|
data/lib/sequence/account.rb
CHANGED
@@ -47,7 +47,7 @@ module Sequence
|
|
47
47
|
# @return [Account]
|
48
48
|
def create(opts)
|
49
49
|
opts = {client_token: SecureRandom.uuid}.merge(opts)
|
50
|
-
Account.new(client.
|
50
|
+
Account.new(client.session.request('create-account', opts))
|
51
51
|
end
|
52
52
|
|
53
53
|
# Updates an account's tags.
|
@@ -57,7 +57,7 @@ module Sequence
|
|
57
57
|
# @option opts [Hash] tags A new set of tags, which will replace the existing tags.
|
58
58
|
# @return [void]
|
59
59
|
def update_tags(opts)
|
60
|
-
client.
|
60
|
+
client.session.request('update-account-tags', opts)
|
61
61
|
end
|
62
62
|
|
63
63
|
# Executes a query, returning an enumerable over individual accounts.
|
@@ -72,7 +72,7 @@ module Sequence
|
|
72
72
|
|
73
73
|
class Query < Sequence::Query
|
74
74
|
def fetch(query)
|
75
|
-
client.
|
75
|
+
client.session.request('list-accounts', query)
|
76
76
|
end
|
77
77
|
|
78
78
|
def translate(raw)
|
data/lib/sequence/asset.rb
CHANGED
@@ -49,7 +49,7 @@ module Sequence
|
|
49
49
|
# @return [Asset]
|
50
50
|
def create(opts)
|
51
51
|
opts = {client_token: SecureRandom.uuid}.merge(opts)
|
52
|
-
Asset.new(client.
|
52
|
+
Asset.new(client.session.request('create-asset', opts))
|
53
53
|
end
|
54
54
|
|
55
55
|
# Updates an asset's tags.
|
@@ -59,7 +59,7 @@ module Sequence
|
|
59
59
|
# @option opts [Hash] tags A new set of tags, which will replace the existing tags.
|
60
60
|
# @return [void]
|
61
61
|
def update_tags(opts)
|
62
|
-
client.
|
62
|
+
client.session.request('update-asset-tags', opts)
|
63
63
|
end
|
64
64
|
|
65
65
|
# Executes a query, returning an enumerable over individual assets.
|
@@ -74,7 +74,7 @@ module Sequence
|
|
74
74
|
|
75
75
|
class Query < Sequence::Query
|
76
76
|
def fetch(query)
|
77
|
-
client.
|
77
|
+
client.session.request('list-assets', query)
|
78
78
|
end
|
79
79
|
|
80
80
|
def translate(raw)
|
data/lib/sequence/balance.rb
CHANGED
data/lib/sequence/client.rb
CHANGED
@@ -15,9 +15,13 @@ module Sequence
|
|
15
15
|
# @option opts [String] access_token The ledger access token.
|
16
16
|
# @return [Query]
|
17
17
|
def initialize(opts = {})
|
18
|
-
if !opts.key?(:
|
19
|
-
raise ArgumentError.new('missing :
|
18
|
+
if !opts.key?(:ledger) || opts[:ledger].empty?
|
19
|
+
raise ArgumentError.new('missing :ledger parameter')
|
20
20
|
end
|
21
|
+
if !opts.key?(:credential) || opts[:credential].empty?
|
22
|
+
raise ArgumentError.new('missing :credential parameter')
|
23
|
+
end
|
24
|
+
|
21
25
|
@opts = opts
|
22
26
|
end
|
23
27
|
|
@@ -25,9 +29,9 @@ module Sequence
|
|
25
29
|
@opts.dup
|
26
30
|
end
|
27
31
|
|
28
|
-
# @return [
|
29
|
-
def
|
30
|
-
@
|
32
|
+
# @return [Session]
|
33
|
+
def session
|
34
|
+
@session ||= Session.new(@opts)
|
31
35
|
end
|
32
36
|
|
33
37
|
# @return [Account::ClientModule]
|
data/lib/sequence/contract.rb
CHANGED
data/lib/sequence/dev_utils.rb
CHANGED
@@ -8,7 +8,7 @@ module Sequence
|
|
8
8
|
class ClientModule < Sequence::ClientModule
|
9
9
|
# Deletes all data in the ledger.
|
10
10
|
def reset
|
11
|
-
client.
|
11
|
+
client.session.request('/reset', client_token: SecureRandom.uuid)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
end
|
data/lib/sequence/errors.rb
CHANGED
@@ -11,7 +11,7 @@ module Sequence
|
|
11
11
|
attr_accessor :response
|
12
12
|
|
13
13
|
def initialize(response)
|
14
|
-
super
|
14
|
+
super 'Response HTTP header field Chain-Request-ID is unset. There may be network issues. Please check your local network settings.'
|
15
15
|
self.response = response
|
16
16
|
end
|
17
17
|
end
|
@@ -53,7 +53,7 @@ module Sequence
|
|
53
53
|
self.temporary = body['temporary']
|
54
54
|
|
55
55
|
self.response = response
|
56
|
-
self.request_id = response['
|
56
|
+
self.request_id = response['Chain-Request-ID'] if response
|
57
57
|
|
58
58
|
super self.class.format_error_message(code, chain_message, detail, request_id)
|
59
59
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
require 'openssl'
|
4
|
+
require 'thread'
|
5
|
+
|
6
|
+
module Sequence
|
7
|
+
class HttpWrapper
|
8
|
+
|
9
|
+
# Parameters to the retry exponential backoff function.
|
10
|
+
MAX_RETRIES = 10
|
11
|
+
RETRY_BASE_DELAY_MS = 40
|
12
|
+
RETRY_MAX_DELAY_MS = 4000
|
13
|
+
|
14
|
+
NETWORK_ERRORS = [
|
15
|
+
InvalidRequestIDError,
|
16
|
+
SocketError,
|
17
|
+
EOFError,
|
18
|
+
IOError,
|
19
|
+
Timeout::Error,
|
20
|
+
Errno::ECONNABORTED,
|
21
|
+
Errno::ECONNRESET,
|
22
|
+
Errno::ETIMEDOUT,
|
23
|
+
Errno::EHOSTUNREACH,
|
24
|
+
Errno::ECONNREFUSED,
|
25
|
+
]
|
26
|
+
|
27
|
+
attr_accessor :dis_macaroon
|
28
|
+
|
29
|
+
def initialize(host, macaroon, opts={})
|
30
|
+
@mutex = Mutex.new
|
31
|
+
@host = URI(host)
|
32
|
+
@macaroon = macaroon
|
33
|
+
@dis_macaroon = nil
|
34
|
+
@opts = opts
|
35
|
+
@http = setup_http
|
36
|
+
end
|
37
|
+
|
38
|
+
def post(url, body)
|
39
|
+
attempts = 0
|
40
|
+
begin
|
41
|
+
attempts += 1
|
42
|
+
# If this is a retry and not the first attempt, sleep before making the
|
43
|
+
# retry request.
|
44
|
+
sleep(backoff_delay(attempts)) if attempts > 1
|
45
|
+
|
46
|
+
@mutex.synchronize do
|
47
|
+
req = Net::HTTP::Post.new(url)
|
48
|
+
req.body = JSON.dump(body)
|
49
|
+
req['Accept'] = 'application/json'
|
50
|
+
req['Content-Type'] = 'application/json'
|
51
|
+
req['User-Agent'] = 'chain-sdk-ruby/' + Sequence::VERSION
|
52
|
+
if @macaroon != nil && @dis_macaroon != nil
|
53
|
+
req['Macaroon'] = @macaroon
|
54
|
+
req['Discharge-Macaroon'] = @dis_macaroon
|
55
|
+
end
|
56
|
+
return @http.request(req)
|
57
|
+
end
|
58
|
+
rescue *NETWORK_ERRORS => e
|
59
|
+
raise e if attempts > MAX_RETRIES
|
60
|
+
retry
|
61
|
+
rescue APIError => e
|
62
|
+
raise e if attempts > MAX_RETRIES
|
63
|
+
retry if e.retriable?
|
64
|
+
raise e
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
MILLIS_TO_SEC = 0.001
|
71
|
+
|
72
|
+
def backoff_delay(attempt)
|
73
|
+
max = RETRY_BASE_DELAY_MS * 2**(attempt-1)
|
74
|
+
max = [max, RETRY_MAX_DELAY_MS].min
|
75
|
+
millis = rand(max) + 1
|
76
|
+
millis * MILLIS_TO_SEC
|
77
|
+
end
|
78
|
+
|
79
|
+
def setup_http
|
80
|
+
args = [@host.hostname, @host.port]
|
81
|
+
|
82
|
+
# Proxy configuration
|
83
|
+
if @opts.key?(:proxy_addr)
|
84
|
+
args += [@opts[:proxy_addr], @opts[:proxy_port]]
|
85
|
+
if @opts.key?(:proxy_user)
|
86
|
+
args += [@opts[:proxy_user], @opts[:proxy_pass]]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
http = Net::HTTP.new(*args)
|
91
|
+
http.set_debug_output($stdout) if ENV['DEBUG']
|
92
|
+
|
93
|
+
# TLS configuration
|
94
|
+
http.use_ssl = true
|
95
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
96
|
+
[:ca_file, :cert, :key].each do |k|
|
97
|
+
next unless @opts.key?(:ssl_params) && @opts[:ssl_params].key?(k)
|
98
|
+
http.send("#{k}=", @opts[:ssl_params][k])
|
99
|
+
end
|
100
|
+
|
101
|
+
# Timeout configuration
|
102
|
+
[:open_timeout, :read_timeout, :ssl_timeout].each do |k|
|
103
|
+
next unless @opts.key?(k)
|
104
|
+
http.send "#{k}=", @opts[k]
|
105
|
+
end
|
106
|
+
|
107
|
+
return http
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
data/lib/sequence/key.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require_relative './client_module'
|
2
|
-
require_relative './
|
2
|
+
require_relative './session'
|
3
3
|
require_relative './query'
|
4
4
|
require_relative './response_object'
|
5
5
|
|
@@ -23,7 +23,7 @@ module Sequence
|
|
23
23
|
# @option opts [String] alias Unique, user-specified identifier of the key.
|
24
24
|
# @return [Key]
|
25
25
|
def create(opts = {})
|
26
|
-
Key.new(client.
|
26
|
+
Key.new(client.session.request('create-key', opts))
|
27
27
|
end
|
28
28
|
|
29
29
|
# Executes a query, returning an enumerable over individual keys.
|
@@ -37,7 +37,7 @@ module Sequence
|
|
37
37
|
|
38
38
|
class Query < Sequence::Query
|
39
39
|
def fetch(query)
|
40
|
-
client.
|
40
|
+
client.session.request('list-keys', query)
|
41
41
|
end
|
42
42
|
|
43
43
|
def translate(obj)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require_relative './http_wrapper'
|
4
|
+
require_relative './errors'
|
5
|
+
require_relative './version'
|
6
|
+
|
7
|
+
module Sequence
|
8
|
+
class Session
|
9
|
+
def initialize(opts)
|
10
|
+
@opts = opts
|
11
|
+
@host = @opts[:host] || 'https://api.seq.com'
|
12
|
+
@session_host = @opts[:session_host] || 'https://session-api.seq.com'
|
13
|
+
@ledger = @opts[:ledger] || raise(ArgumentError, "missing ledger")
|
14
|
+
@macaroon = @opts[:credential] || raise(ArgumentError, "missing credential")
|
15
|
+
|
16
|
+
# Start at 0 to trigger an immediate refresh
|
17
|
+
@refresh_at = 0
|
18
|
+
|
19
|
+
# Expect this to get set in #refresh!
|
20
|
+
@team_name = nil
|
21
|
+
|
22
|
+
# This can be used to avoid making an http request to get a
|
23
|
+
# new discharge macaroon.
|
24
|
+
@refresh_method = @opts[:refresh_method]
|
25
|
+
if @refresh_method
|
26
|
+
if !@refresh_method.respond_to?(:call)
|
27
|
+
raise(ArgumentError, "refresh_method is not a lambda")
|
28
|
+
end
|
29
|
+
if @refresh_method.arity != 1
|
30
|
+
raise(ArgumentError, "refresh_method must take 1 argument. (the macaroon)")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
@session_api = HttpWrapper.new(@session_host, nil)
|
35
|
+
@ledger_api = HttpWrapper.new(@host, @macaroon, @opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a copy of the configuration options
|
39
|
+
def opts
|
40
|
+
@opts.dup
|
41
|
+
end
|
42
|
+
|
43
|
+
def request(path, body = {})
|
44
|
+
request_full_resp(path, body)[:parsed_body]
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_full_resp(path, body={})
|
48
|
+
refresh!
|
49
|
+
|
50
|
+
response = @ledger_api.post(ledger_url(path), body)
|
51
|
+
req_id = response['Chain-Request-ID']
|
52
|
+
unless req_id.is_a?(String) && req_id.size > 0
|
53
|
+
raise InvalidRequestIDError.new(response)
|
54
|
+
end
|
55
|
+
|
56
|
+
status = Integer(response.code)
|
57
|
+
parsed_body = nil
|
58
|
+
if status != 204 # No Content
|
59
|
+
begin
|
60
|
+
parsed_body = JSON.parse(response.body)
|
61
|
+
rescue JSON::JSONError
|
62
|
+
raise JSONError.new(req_id, response)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
if status / 100 != 2
|
66
|
+
klass = status == 401 ? UnauthorizedError : APIError
|
67
|
+
raise klass.new(parsed_body, response)
|
68
|
+
end
|
69
|
+
|
70
|
+
{parsed_body: parsed_body, response: response}
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def ledger_url(path)
|
76
|
+
path = path[1..-1] if path.start_with?("/")
|
77
|
+
"/#{@team_name}/#{@ledger}/#{path}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def refresh!
|
81
|
+
return if @refresh_at > Time.now.to_i
|
82
|
+
|
83
|
+
result = if @refresh_method
|
84
|
+
@refresh_method.call(@macaroon)
|
85
|
+
else
|
86
|
+
r = @session_api.post('/sessions/validate', {macaroon: @macaroon})
|
87
|
+
JSON.parse(r.body)
|
88
|
+
end
|
89
|
+
|
90
|
+
@team_name = result['team_name']
|
91
|
+
@refresh_at = Integer(result['refresh_at'])
|
92
|
+
@ledger_api.dis_macaroon = result['refresh_token']
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
data/lib/sequence/stats.rb
CHANGED
data/lib/sequence/transaction.rb
CHANGED
@@ -50,12 +50,12 @@ module Sequence
|
|
50
50
|
builder = Builder.new(&block)
|
51
51
|
end
|
52
52
|
|
53
|
-
tpl = client.
|
54
|
-
tpl = client.
|
53
|
+
tpl = client.session.request('build-transaction', builder)
|
54
|
+
tpl = client.session.request(
|
55
55
|
'/sign-transaction',
|
56
56
|
transaction: tpl,
|
57
57
|
)
|
58
|
-
Transaction.new(client.
|
58
|
+
Transaction.new(client.session.request(
|
59
59
|
'submit-transaction',
|
60
60
|
{transaction: tpl}
|
61
61
|
))
|
@@ -75,7 +75,7 @@ module Sequence
|
|
75
75
|
|
76
76
|
class Query < Sequence::Query
|
77
77
|
def fetch(query)
|
78
|
-
client.
|
78
|
+
client.session.request('list-transactions', query)
|
79
79
|
end
|
80
80
|
|
81
81
|
def translate(raw)
|
data/lib/sequence/version.rb
CHANGED
metadata
CHANGED
@@ -1,137 +1,137 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequence-sdk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chain Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-10-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler-audit
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 3.5.0
|
62
|
-
- -
|
62
|
+
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
64
|
version: 3.5.0
|
65
65
|
type: :development
|
66
66
|
prerelease: false
|
67
67
|
version_requirements: !ruby/object:Gem::Requirement
|
68
68
|
requirements:
|
69
|
-
- - ~>
|
69
|
+
- - "~>"
|
70
70
|
- !ruby/object:Gem::Version
|
71
71
|
version: 3.5.0
|
72
|
-
- -
|
72
|
+
- - ">="
|
73
73
|
- !ruby/object:Gem::Version
|
74
74
|
version: 3.5.0
|
75
75
|
- !ruby/object:Gem::Dependency
|
76
76
|
name: rspec-its
|
77
77
|
requirement: !ruby/object:Gem::Requirement
|
78
78
|
requirements:
|
79
|
-
- - ~>
|
79
|
+
- - "~>"
|
80
80
|
- !ruby/object:Gem::Version
|
81
81
|
version: 1.2.0
|
82
82
|
type: :development
|
83
83
|
prerelease: false
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- - ~>
|
86
|
+
- - "~>"
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: 1.2.0
|
89
89
|
- !ruby/object:Gem::Dependency
|
90
90
|
name: simplecov
|
91
91
|
requirement: !ruby/object:Gem::Requirement
|
92
92
|
requirements:
|
93
|
-
- - ~>
|
93
|
+
- - "~>"
|
94
94
|
- !ruby/object:Gem::Version
|
95
95
|
version: 0.14.1
|
96
96
|
type: :development
|
97
97
|
prerelease: false
|
98
98
|
version_requirements: !ruby/object:Gem::Requirement
|
99
99
|
requirements:
|
100
|
-
- - ~>
|
100
|
+
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: 0.14.1
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: webmock
|
105
105
|
requirement: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
|
-
- - ~>
|
107
|
+
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
109
|
version: 2.3.2
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
112
|
version_requirements: !ruby/object:Gem::Requirement
|
113
113
|
requirements:
|
114
|
-
- - ~>
|
114
|
+
- - "~>"
|
115
115
|
- !ruby/object:Gem::Version
|
116
116
|
version: 2.3.2
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
118
|
name: yard
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- - ~>
|
121
|
+
- - "~>"
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: 0.9.5
|
124
|
-
- -
|
124
|
+
- - ">="
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: 0.9.5
|
127
127
|
type: :development
|
128
128
|
prerelease: false
|
129
129
|
version_requirements: !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
|
-
- - ~>
|
131
|
+
- - "~>"
|
132
132
|
- !ruby/object:Gem::Version
|
133
133
|
version: 0.9.5
|
134
|
-
- -
|
134
|
+
- - ">="
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: 0.9.5
|
137
137
|
description: SDK for Sequence
|
@@ -140,25 +140,26 @@ executables: []
|
|
140
140
|
extensions: []
|
141
141
|
extra_rdoc_files: []
|
142
142
|
files:
|
143
|
-
- README.md
|
144
143
|
- LICENSE
|
144
|
+
- README.md
|
145
|
+
- lib/sequence.rb
|
145
146
|
- lib/sequence/account.rb
|
146
147
|
- lib/sequence/asset.rb
|
147
148
|
- lib/sequence/balance.rb
|
148
149
|
- lib/sequence/client.rb
|
149
150
|
- lib/sequence/client_module.rb
|
150
|
-
- lib/sequence/connection.rb
|
151
151
|
- lib/sequence/contract.rb
|
152
152
|
- lib/sequence/dev_utils.rb
|
153
153
|
- lib/sequence/errors.rb
|
154
|
+
- lib/sequence/http_wrapper.rb
|
154
155
|
- lib/sequence/key.rb
|
155
156
|
- lib/sequence/page.rb
|
156
157
|
- lib/sequence/query.rb
|
157
158
|
- lib/sequence/response_object.rb
|
159
|
+
- lib/sequence/session.rb
|
158
160
|
- lib/sequence/stats.rb
|
159
161
|
- lib/sequence/transaction.rb
|
160
162
|
- lib/sequence/version.rb
|
161
|
-
- lib/sequence.rb
|
162
163
|
homepage: https://dashboard.sequenceledger.com
|
163
164
|
licenses:
|
164
165
|
- Apache-2.0
|
@@ -169,17 +170,17 @@ require_paths:
|
|
169
170
|
- lib
|
170
171
|
required_ruby_version: !ruby/object:Gem::Requirement
|
171
172
|
requirements:
|
172
|
-
- - ~>
|
173
|
+
- - "~>"
|
173
174
|
- !ruby/object:Gem::Version
|
174
175
|
version: '2.0'
|
175
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
176
177
|
requirements:
|
177
|
-
- -
|
178
|
+
- - ">="
|
178
179
|
- !ruby/object:Gem::Version
|
179
180
|
version: '0'
|
180
181
|
requirements: []
|
181
182
|
rubyforge_project:
|
182
|
-
rubygems_version: 2.
|
183
|
+
rubygems_version: 2.6.14
|
183
184
|
signing_key:
|
184
185
|
specification_version: 4
|
185
186
|
summary: SDK for Sequence
|
data/lib/sequence/connection.rb
DELETED
@@ -1,164 +0,0 @@
|
|
1
|
-
require 'json'
|
2
|
-
require 'net/http'
|
3
|
-
require 'net/https'
|
4
|
-
require 'openssl'
|
5
|
-
require 'thread'
|
6
|
-
|
7
|
-
require_relative './errors'
|
8
|
-
require_relative './version'
|
9
|
-
|
10
|
-
module Sequence
|
11
|
-
class Connection
|
12
|
-
|
13
|
-
# Parameters to the retry exponential backoff function.
|
14
|
-
MAX_RETRIES = 10
|
15
|
-
RETRY_BASE_DELAY_MS = 40
|
16
|
-
RETRY_MAX_DELAY_MS = 4000
|
17
|
-
|
18
|
-
NETWORK_ERRORS = [
|
19
|
-
InvalidRequestIDError,
|
20
|
-
SocketError,
|
21
|
-
EOFError,
|
22
|
-
IOError,
|
23
|
-
Timeout::Error,
|
24
|
-
Errno::ECONNABORTED,
|
25
|
-
Errno::ECONNRESET,
|
26
|
-
Errno::ETIMEDOUT,
|
27
|
-
Errno::EHOSTUNREACH,
|
28
|
-
Errno::ECONNREFUSED,
|
29
|
-
]
|
30
|
-
|
31
|
-
def initialize(opts)
|
32
|
-
@opts = opts
|
33
|
-
@url = URI(@opts[:url])
|
34
|
-
@access_token = @opts[:access_token] || @url.userinfo
|
35
|
-
@http_mutex = Mutex.new
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns a copy of the configuration options
|
39
|
-
def opts
|
40
|
-
@opts.dup
|
41
|
-
end
|
42
|
-
|
43
|
-
def request(path, body = {})
|
44
|
-
_request_with_retries(path, body)[:body]
|
45
|
-
end
|
46
|
-
|
47
|
-
def _request_with_retries(path, body)
|
48
|
-
attempts = 0
|
49
|
-
|
50
|
-
begin
|
51
|
-
attempts += 1
|
52
|
-
|
53
|
-
# If this is a retry and not the first attempt, sleep before making the
|
54
|
-
# retry request.
|
55
|
-
sleep(backoff_delay(attempts)) if attempts > 1
|
56
|
-
|
57
|
-
_single_request(path, body)
|
58
|
-
rescue *NETWORK_ERRORS => e
|
59
|
-
raise e if attempts > MAX_RETRIES
|
60
|
-
retry
|
61
|
-
rescue APIError => e
|
62
|
-
raise e if attempts > MAX_RETRIES
|
63
|
-
retry if e.retriable?
|
64
|
-
raise e
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def _single_request(path, body)
|
69
|
-
@http_mutex.synchronize do
|
70
|
-
# Timeout configuration
|
71
|
-
[:open_timeout, :read_timeout, :ssl_timeout].each do |k|
|
72
|
-
next unless @opts.key?(k)
|
73
|
-
http.send "#{k}=", @opts[k]
|
74
|
-
end
|
75
|
-
|
76
|
-
full_path = @url.request_uri.chomp('/')
|
77
|
-
full_path += (path[0] == '/') ? path : '/' + path
|
78
|
-
|
79
|
-
req = Net::HTTP::Post.new(full_path)
|
80
|
-
req['Accept'] = 'application/json'
|
81
|
-
req['Content-Type'] = 'application/json'
|
82
|
-
req['User-Agent'] = 'chain-sdk-ruby/' + Sequence::VERSION
|
83
|
-
req.body = JSON.dump(body)
|
84
|
-
|
85
|
-
if @access_token
|
86
|
-
user, pass = @access_token.split(':')
|
87
|
-
req.basic_auth(user, pass)
|
88
|
-
end
|
89
|
-
|
90
|
-
response = http.request(req)
|
91
|
-
|
92
|
-
req_id = response['Chain-Request-ID']
|
93
|
-
unless req_id.is_a?(String) && req_id.size > 0
|
94
|
-
raise InvalidRequestIDError.new(response)
|
95
|
-
end
|
96
|
-
|
97
|
-
status = Integer(response.code)
|
98
|
-
parsed_body = nil
|
99
|
-
|
100
|
-
if status != 204 # No Content
|
101
|
-
begin
|
102
|
-
parsed_body = JSON.parse(response.body)
|
103
|
-
rescue JSON::JSONError
|
104
|
-
raise JSONError.new(req_id, response)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
if status / 100 != 2
|
109
|
-
klass = status == 401 ? UnauthorizedError : APIError
|
110
|
-
raise klass.new(parsed_body, response)
|
111
|
-
end
|
112
|
-
|
113
|
-
{body: parsed_body, response: response}
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
private
|
118
|
-
|
119
|
-
MILLIS_TO_SEC = 0.001
|
120
|
-
|
121
|
-
def backoff_delay(attempt)
|
122
|
-
max = RETRY_BASE_DELAY_MS * 2**(attempt-1)
|
123
|
-
max = [max, RETRY_MAX_DELAY_MS].min
|
124
|
-
millis = rand(max) + 1
|
125
|
-
millis * MILLIS_TO_SEC
|
126
|
-
end
|
127
|
-
|
128
|
-
def http
|
129
|
-
return @http if @http
|
130
|
-
|
131
|
-
args = [@url.host, @url.port]
|
132
|
-
|
133
|
-
# Proxy configuration
|
134
|
-
if @opts.key?(:proxy_addr)
|
135
|
-
args += [@opts[:proxy_addr], @opts[:proxy_port]]
|
136
|
-
if @opts.key?(:proxy_user)
|
137
|
-
args += [@opts[:proxy_user], @opts[:proxy_pass]]
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
@http = Net::HTTP.new(*args)
|
142
|
-
|
143
|
-
@http.set_debug_output($stdout) if ENV['DEBUG']
|
144
|
-
if @url.scheme == 'https'
|
145
|
-
@http.use_ssl = true
|
146
|
-
@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
147
|
-
if @opts.key?(:ssl_params)
|
148
|
-
ssl_params = @opts[:ssl_params]
|
149
|
-
if ssl_params.key?(:ca_file)
|
150
|
-
@http.ca_file = ssl_params[:ca_file]
|
151
|
-
end
|
152
|
-
if ssl_params.key?(:cert)
|
153
|
-
@http.cert = ssl_params[:cert]
|
154
|
-
end
|
155
|
-
if ssl_params.key?(:key)
|
156
|
-
@http.key = ssl_params[:key]
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
@http
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|