I try to send authenticated request to new okex api. part of their documentation:
Creating a Request
All REST requests must contain the following headers:
OK-ACCESS-KEY The api key as a string.
OK-ACCESS-SIGN The base64-encoded signature (see Signing a Message).
OK-ACCESS-TIMESTAMP A timestamp for your request.
OK-ACCESS-PASSPHRASE The passphrase you specified when creating the API key.
All request bodies should have content type application/json and be valid JSON.
Signing a Message
The OK-ACCESS-SIGN header is generated by creating a sha256 HMAC using the base64-decoded secret key on the prehash string timestamp + method + requestPath + body (where + represents string concatenation), secretKey and base64-encode the output. For example: sign=CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(timestamp + 'GET' + '/users/self/verify', secretKey))
The timestamp value is the same as the OK-ACCESS-TIMESTAMP header and nanometer precision.
The method should be UPPER CASE, like GET/POST.
requestPath is the path of requesting an endpoint, such as:/orders?before=2&limit=30.
The body is the request body string or omitted if there is no request body (typically for GET requests). For example:{"product_id":"BTC-USD-0309","order_id":"377454671037440"}
secretKey is generated when a user is subscribing to an Apikey. Prehash string:2018-03-08T10:59:25.789ZPOST/orders?before=2&limit=30{"product_id":"BTC-USD-0309","order_id":"377454671037440"}
So that's what i tried
BASE_URL = 'https://www.okex.com'.freeze
def base_api_endpoint
url = URI.parse BASE_URL
"#{url.scheme}://#{url.host}:#{url.port}"
end
def authenticated_request(method, url, options = {}, paginated: false)
raise Exceptions::InvalidApiKey if @key.blank? || @secret.blank? || @passphrase.blank?
response = rest_connection.run_request(method, URI.encode(url), nil, nil) do |req|
if method == :post
req.body = options.to_json
else
req.params.merge! options
end
end
def rest_connection
@conn ||= new_rest_connection
end
TimestampRequestMiddleware = Struct.new(:app) do
def call(env)
env[:request_headers].merge!('OK-ACCESS-TIMESTAMP' => Time.now.utc.iso8601(3))
app.call env
end
end
SignRequestMiddleware = Struct.new(:app, :key, :secret, :passphrase) do
def call(env)
request_path = env[:url].path
if env[:url].query.present?
request_path += ('?' + env[:url].query)
end
timestamp = env[:request_headers]['OK-ACCESS-TIMESTAMP']
method = env[:method].to_s.upcase
what = "#{timestamp} + #{method} + #{request_path} + #{env.body}"
decoded_secret = Base64.decode64(secret)
mac = OpenSSL::HMAC.digest('sha256', decoded_secret, what)
sign = Base64.strict_encode64(mac)
env[:request_headers].merge!('OK-ACCESS-KEY' => key, 'OK-ACCESS-SIGN' => sign, 'OK-ACCESS-TIMESTAMP' => timestamp, 'OK-ACCESS-PASSPHRASE' => passphrase)
app.call env
end
end
def new_rest_connection
Faraday.new( base_api_endpoint, { ssl: { verify: false } }) do |conn|
conn.use Market::OkexMarket::OkexCustomErrors, api_key: @key
conn.request :json
conn.response :json, content_type: /\bjson$/
conn.response :logger, Logger.new(STDOUT) , bodies: true if Rails.env.development?
conn.use FaradayMiddleware::ParseJson, :content_type => /\bjson$/
conn.use TimestampRequestMiddleware
conn.use SignRequestMiddleware, @key, @secret, @passphrase
conn.headers['Content-Type'] = 'application/json'
conn.adapter :net_http
end
end
def complete_balances
data = authenticated_request(:get, '/api/spot/v3/accounts')
data.map do |d|
[
d['currency'],
{'available' => d['available'].to_f, 'onOrders' => d['hold'].to_f}
]
end.to_h
end
But when i call complete_balances method, i got an error from okex response: {"code"=>30013, "message"=>"Invalid Sign"} and i can't recognize where i'm wrong. Can someone help me with that?