cryptomarket-sdk 1.0.0 → 3.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.
@@ -1,71 +0,0 @@
1
- require 'net/http'
2
- require 'uri'
3
- require 'json'
4
- require 'base64'
5
- require 'rest-client'
6
-
7
- module Cryptomarket
8
- class HttpManager
9
- @@apiUrl = 'https://api.exchange.cryptomkt.com'
10
- @@apiVersion = '/api/2/'
11
-
12
-
13
- def initialize(apiKey:, apiSecret:)
14
- @apiKey = apiKey
15
- @apiSecret = apiSecret
16
- end
17
-
18
- def getCredential(httpMethod, method, params)
19
- timestamp = Time.now.to_i.to_s
20
- msg = httpMethod + timestamp + @@apiVersion + method
21
- if not params.nil? and params.keys.any?
22
- if httpMethod == 'GET'
23
- msg += '?'
24
- end
25
- msg += URI.encode_www_form params
26
- end
27
- digest = OpenSSL::Digest.new 'sha256'
28
- signature = OpenSSL::HMAC.hexdigest digest, @apiSecret, msg
29
- encoded = Base64.encode64(@apiKey + ':' + timestamp + ':' + signature).delete "\n"
30
- return 'HS256 ' + encoded
31
- end
32
-
33
- def makeRequest(method:, endpoint:, params:nil, public:false)
34
- uri = URI(@@apiUrl + @@apiVersion + endpoint)
35
- headers = Hash.new
36
- if not public
37
- headers['Authorization'] = getCredential(method.upcase, endpoint, params)
38
- end
39
- if method.upcase == 'GET' and not params.nil?
40
- uri.query = URI.encode_www_form params
41
- params = nil
42
- end
43
- begin
44
- response = RestClient::Request.execute(
45
- method: method.downcase.to_sym,
46
- url: uri.to_s,
47
- payload: params,
48
- headers: headers)
49
- return handleResponse(response)
50
- rescue RestClient::ExceptionWithResponse => e
51
- response = e.response
52
- return handleResponse(response)
53
- end
54
- end
55
-
56
- def handleResponse(response)
57
- result = response.body
58
- parsed_result = JSON.parse result
59
- if response.code != 200 and not parsed_result['error'].nil?
60
- error = parsed_result['error']
61
- msg = "(code=#{error['code']}): #{error['message']}"
62
- if not error['description'].nil?
63
- msg += ": #{error['description']}"
64
- end
65
- exception = Cryptomarket::APIException.new error
66
- raise exception, msg
67
- end
68
- return parsed_result
69
- end
70
- end
71
- end
@@ -1,57 +0,0 @@
1
- module Cryptomarket
2
- module Utils
3
- def extend_hash_with_pagination!(hash, sort: nil, by:nil, from: nil, till: nil, limit: nil, offset: nil)
4
- if not sort.nil?
5
- hash['sort'] = sort
6
- end
7
- if not by.nil?
8
- hash['by'] = by
9
- end
10
- if not from.nil?
11
- hash['from'] = from
12
- end
13
- if not till.nil?
14
- hash['till'] = till
15
- end
16
- if not limit.nil?
17
- hash['limit'] = limit
18
- end
19
- if not offset.nil?
20
- hash['offset'] = offset
21
- end
22
- end
23
-
24
- def extend_hash_with_order_params! hash, symbol:nil, side:nil, quantity:nil, type:nil, timeInForce:nil, price:nil, stopPrice:nil, expireTime:nil, strictValidate:nil, postOnly:nil
25
- if not symbol.nil?
26
- hash['symbol'] = symbol
27
- end
28
- if not side.nil?
29
- hash['side'] = side
30
- end
31
- if not quantity.nil?
32
- hash['quantity'] = quantity
33
- end
34
- if not type.nil?
35
- hash['type'] = type
36
- end
37
- if not timeInForce.nil?
38
- hash['timeInForce'] = timeInForce
39
- end
40
- if not price.nil?
41
- hash['price'] = price
42
- end
43
- if not stopPrice.nil?
44
- hash['stopPrice'] = stopPrice
45
- end
46
- if not expireTime.nil?
47
- hash['expireTime'] = expireTime
48
- end
49
- if not strictValidate.nil?
50
- hash['strictValidate'] = strictValidate
51
- end
52
- if not postOnly.nil?
53
- hash['postOnly'] = postOnly
54
- end
55
- end
56
- end
57
- end
@@ -1,110 +0,0 @@
1
- require_relative "authClient"
2
- require_relative"../utils"
3
-
4
- module Cryptomarket
5
- module Websocket
6
-
7
- # AccountClient connects via websocket to cryptomarket to get account information of the user. uses SHA256 as auth method and authenticates automatically.
8
- #
9
- # +string+ +apiKey+:: the user api key
10
- # +string+ +apiSecret+:: the user api secret
11
- # +Proc+ +callback+:: Optional. A +Proc+ to call with the client once the connection is established and the authentication is successful. if an error ocurrs is return as the fist parameter of the callback: callback(err, client)
12
-
13
- class AccountClient < AuthClient
14
- include Utils
15
- # Creates a new client and authenticates it to the server
16
- def initialize(apiKey:, apiSecret:)
17
- super(url:"wss://api.exchange.cryptomkt.com/api/2/ws/account", apiKey:apiKey, apiSecret:apiSecret)
18
- end
19
-
20
- # get the account balance as a list of balances. non-zero balances only
21
- #
22
- # https://api.exchange.cryptomarket.com/#request-balance
23
-
24
- def getAccountBalance(callback)
25
- sendById('getBalance', callback)
26
- end
27
-
28
- # Get a list of transactions of the account. Accepts only filtering by Datetime
29
- #
30
- # https://api.exchange.cryptomarket.com/#find-transactions
31
- #
32
- # Parameters:
33
- # +Proc+ +callback+:: A +Proc+ to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: Proc.new {|err, result| ...}
34
- # +string+ +currency+:: Optional. Currency to filter transactions by.
35
- # +string+ +sort+:: Optional. sort direction. 'ASC' or 'DESC' default is 'DESC'
36
- # +string+ +from+:: Optional. Initial value of the queried interval
37
- # +string+ +till+:: Optional. Last value of the queried interval
38
- # +integer+ +limit+:: Optional. Trades per query. Defaul is 100. Max is 1000
39
- # +integer+ +offset+:: Optional. Default is 0. Max is 100000
40
- # +bool+ +showSenders+:: Optional. If true incluedes senders addresses. Default is false.
41
-
42
- def findTransactions(callback, currency:nil, sort:nil, from:nil, till:nil, limit:nil, offset:nil, showSenders:nil)
43
- params = Hash.new
44
- if not currency.nil?
45
- params['currency'] = currency
46
- end
47
- if not showSenders.nil?
48
- params['showSenders'] = showSenders
49
- end
50
- extend_hash_with_pagination! params, sort:sort, from:from, till:till, limit:limit, offset:offset
51
- sendById('findTransactions', callback, params)
52
- end
53
-
54
- # LoadTransactions gets a list of transactions of the account. Accepts only filtering by Index
55
- #
56
- # https://api.exchange.cryptomarket.com/#find-transactions
57
- #
58
- # Parameters:
59
- # +Proc+ +callback+:: A +Proc+ to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: Proc.new {|err, result| ...}
60
- # +string+ +currency+:: Optional. Currency to filter transactions by.
61
- # +string+ +sort+:: Optional. sort direction. 'ASC' or 'DESC' default is 'ASC'
62
- # +string+ +from+:: Optional. Initial value of the queried interval (Included)
63
- # +string+ +till+:: Optional. Last value of the queried interval (Excluded)
64
- # +integer+ +limit+:: Optional. Trades per query. Defaul is 100. Max is 1000
65
- # +integer+ +offset+:: Optional. Default is 0. Max is 100000
66
- # +bool+ +showSenders+:: Optional. If true incluedes senders addresses. Default is false.
67
-
68
- def loadTransactions(callback, currency:nil, sort:nil, from:nil, till:nil, limit:nil, offset:nil, showSenders:nil)
69
- params = Hash.new
70
- if not currency.nil?
71
- params['currency'] = currency
72
- end
73
- if not showSenders.nil?
74
- params['showSenders'] = showSenders
75
- end
76
- extend_hash_with_pagination! params, sort:sort, from:from, till:till, limit:limit, offset:offset
77
- sendById('loadTransactions', callback, params)
78
- end
79
-
80
- # subscribes to a feed of transactions
81
- #
82
- # A transaction notification occurs each time the transaction has been changed:
83
- # such as creating a transaction, updating the pending state (for example the hash assigned)
84
- # or completing a transaction. This is the easiest way to track deposits or develop real-time asset monitoring.
85
- #
86
- # A combination of the recovery mechanism and transaction subscription provides reliable and consistent information
87
- # regarding transactions. For that, you should store the latest processed index and
88
- # requested possible gap using a "loadTransactions" method after connecting or reconnecting the Websocket.
89
- #
90
- # https://api.exchange.cryptomarket.com/#subscription-to-the-transactions
91
- #
92
- # +Proc+ +callback+:: A +Proc+ to call with the result data. It takes one argument. a feed of reports
93
- # +Proc+ +resultCallback+:: Optional. A +Proc+ to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: Proc.new {|err, result| ...}
94
-
95
- def subscribeToTransactions(callback, resultCallback:nil)
96
- sendSubscription('subscribeTransactions', callback, {}, resultCallback)
97
- end
98
-
99
- # unsubscribe to the transaction feed.
100
- #
101
- # https://api.exchange.cryptomkt.com/#subscription-to-the-transactions
102
- #
103
- # +Proc+ +callback+:: Optional. A +Proc+ to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: Proc.new {|err, result| ...}
104
-
105
- def unsubscribeToTransactions(callback:nil)
106
- sendUnsubscription('unsubscribeTransactions', callback, {})
107
- end
108
- end
109
- end
110
- end
@@ -1,53 +0,0 @@
1
- require "securerandom"
2
- require_relative "wsClientBase"
3
-
4
- module Cryptomarket
5
- module Websocket
6
- class AuthClient < ClientBase
7
- # Creates a new client
8
- def initialize(url:, apiKey:, apiSecret:)
9
- @apiKey = apiKey
10
- @apiSecret = apiSecret
11
- super url:url
12
- @authed = false
13
- end
14
-
15
- def connected?
16
- return (super.connected? and @authed)
17
- end
18
-
19
- # connects via websocket to the exchange and authenticates it.
20
- def connect
21
- super
22
- authenticate(Proc.new {|err, result|
23
- if not err.nil?
24
- raise err
25
- end
26
- @authed = true
27
- })
28
- while not @authed
29
- sleep(1)
30
- end
31
- end
32
-
33
- # Authenticates the websocket
34
- #
35
- # https://api.exchange.cryptomkt.com/#socket-session-authentication
36
- #
37
- # +Proc+ +callback+:: Optional. A +Proc+ to call with the result data. It takes two arguments, err and result. err is None for successful calls, result is None for calls with error: Proc.new {|err, result| ...}
38
-
39
- def authenticate(callback=nil)
40
- nonce = SecureRandom.hex
41
- digest = OpenSSL::Digest.new 'sha256'
42
- signature = OpenSSL::HMAC.hexdigest digest, @apiSecret, nonce
43
- params = {
44
- 'algo'=> 'HS256',
45
- 'pKey'=> @apiKey,
46
- 'nonce'=> nonce,
47
- 'signature'=> signature
48
- }
49
- return sendById('login', callback, params)
50
- end
51
- end
52
- end
53
- end
@@ -1,51 +0,0 @@
1
- module Cryptomarket
2
- module Websocket
3
- class CallbackCache
4
- def initialize()
5
- @callbacks = Hash.new
6
- @nextId = 1
7
- end
8
-
9
- def getNextId
10
- _nextId = @nextId
11
- @nextId+= 1
12
- if @nextId < 0
13
- @nextId = 1
14
- end
15
- return _nextId
16
- end
17
-
18
- def storeCallback(callback)
19
- id = getNextId()
20
- @callbacks[id] = callback
21
- return id
22
- end
23
-
24
- def popCallback(id)
25
- if not @callbacks.has_key? id
26
- return nil
27
- end
28
- callback = @callbacks[id]
29
- @callbacks.delete(id)
30
- return callback
31
- end
32
-
33
- def storeSubscriptionCallback(key, callback)
34
- @callbacks[key] = callback
35
- end
36
-
37
- def getSubscriptionCallback(key)
38
- if not @callbacks.has_key? key
39
- return nil
40
- end
41
- return @callbacks[key]
42
- end
43
-
44
- def deleteSubscriptionCallback(key)
45
- if @callbacks.has_key? key
46
- @callbacks.delete(key)
47
- end
48
- end
49
- end
50
- end
51
- end
@@ -1,123 +0,0 @@
1
- require "bigdecimal"
2
-
3
- module Cryptomarket
4
- module Websocket
5
- class OrderbookCache
6
-
7
- # orderbook states
8
- @@UPDATING = 0
9
- @@WAITING = 1
10
- @@BROKEN = 2
11
- # order book side ordering direction
12
- @@ASCENDING = 3
13
- @@DESCENDING = 4
14
-
15
- def initialize()
16
- @orderbooks = Hash.new
17
- @orderbooks_states = Hash.new
18
- end
19
-
20
- def update(method, key, updateData)
21
- case method
22
- when 'snapshotOrderbook'
23
- @orderbooks_states[key] = @@UPDATING
24
- @orderbooks[key] = updateData
25
- return @orderbooks[key]
26
- when 'updateOrderbook'
27
- if @orderbooks_states[key] != @@UPDATING
28
- return
29
- end
30
- oldOrderbook = @orderbooks[key]
31
- if updateData['sequence'] - oldOrderbook['sequence'] != 1
32
- @orderbooks_states[key] = @@BROKEN
33
- return
34
- end
35
- oldOrderbook['sequence'] = updateData['sequence']
36
- oldOrderbook['timestamp'] = updateData['timestamp']
37
- if updateData.has_key? 'ask'
38
- oldOrderbook['ask'] = updateBookSide(oldOrderbook['ask'], updateData['ask'], @@ASCENDING)
39
- end
40
- if updateData.has_key? 'bid'
41
- oldOrderbook['bid'] = updateBookSide(oldOrderbook['bid'], updateData['bid'], @@DESCENDING)
42
- end
43
- end
44
- end
45
-
46
- def updateBookSide(oldList, updateList, sortDirection)
47
- newList = Array.new
48
- oldIdx = 0
49
- updateIdx = 0
50
- while (oldIdx < oldList.length && updateIdx < updateList.length)
51
- updateEntry = updateList[updateIdx]
52
- oldEntry = oldList[oldIdx]
53
- order = priceOrder(oldEntry, updateEntry, sortDirection)
54
- if (order == 0)
55
- if not zeroSize(updateEntry)
56
- newList.push(updateEntry)
57
- end
58
- updateIdx+= 1
59
- oldIdx+= 1
60
- elsif (order == 1)
61
- newList.push(oldEntry)
62
- oldIdx+= 1
63
- else
64
- newList.push(updateEntry)
65
- updateIdx+= 1
66
- end
67
- end
68
- if updateIdx == updateList.length
69
- for idx in oldIdx..oldList.length-1
70
- oldEntry = oldList[idx]
71
- newList.push(oldEntry)
72
- end
73
- end
74
- if (oldIdx == oldList.length)
75
- for idx in updateIdx..updateList.length-1
76
- updateEntry = updateList[idx]
77
- if not zeroSize(updateEntry)
78
- newList.push(updateEntry)
79
- end
80
- end
81
- end
82
- return newList
83
- end
84
-
85
- def zeroSize(entry)
86
- size = BigDecimal(entry['size'])
87
- return size == BigDecimal("0.00")
88
- end
89
-
90
- def priceOrder(oldEntry, updateEntry, sortDirection)
91
- oldPrice = BigDecimal(oldEntry['price'])
92
- updatePrice = BigDecimal(updateEntry['price'])
93
- # puts oldEntry.to_s() +"\t" + updateEntry.to_s()
94
- direction = 1
95
- if oldPrice > updatePrice
96
- direction = -1
97
- end
98
- if oldPrice == updatePrice
99
- direction = 0
100
- end
101
- if sortDirection == @@ASCENDING
102
- return direction
103
- end
104
- return -direction
105
- end
106
-
107
- def getOrderbook(key)
108
- return Marshal.load(Marshal.dump(@orderbooks[key]))
109
- end
110
-
111
- def orderbookBroken(key)
112
- return @orderbooks_states[key] == @@BROKEN
113
- end
114
- def orderbookWating(key)
115
- return @orderbooks_states[key] == @@WAITING
116
- end
117
-
118
- def waitOrderbook(key)
119
- @orderbooks_states[key] = @@WAITING
120
- end
121
- end
122
- end
123
- end