Search code examples
rubyhttp-headersuribinance

Is there a way to pass parameters and headers using Net::HTTP in Ruby?


I'm trying to build a small Ruby script to interact with the Binance API (https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md)

Here is what I have so far. This is all one script, but I've broken this up into "what I think works" and "what I think is broken" sections for clarity:

I think the includes, function, and param creation work properly:

require 'json'
require 'uri'
require 'net/http'
require 'openssl'

def params_with_signature(params, secret)
  params = params.reject { |_k, v| v.nil? }
  query_string = URI.encode_www_form(params)
  signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, query_string)
  params = params.merge(signature: signature)
end

BASE_URL = 'https://api.binance.com'
api_key = ''
api_secret = ''

params = {
    symbol: 'BNBBTC',
    side: 'BUY',
    type: 'MARKET',
    timeInForce: 'GTC',
    quantity: 1,
    recvWindow: 5000,
    timestamp: Time.now.to_i * 1000
}

I think this is where things are going wrong

uri = URI("#{BASE_URL}/api/v3/order")

header = {'Content-Type': 'text/json'}

http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, header)
request.body = params_with_signature(params, api_secret).to_json
request["X-MBX-APIKEY"] = api_key

response = http.request(request)

puts response.body

The problem is that I keep receiving various "malformed" errors when attempting to send requests. Again, I think the problem is with the Net::HTTP post attempt above.

Any ideas would be great!


Solution

  • I am not sure if it's a solution for you but I've rewritten your code to use HTTParty gem instead of net/http. In my opinion it's much easier to use this gem. As a result, I've got {"code":-2014,"msg":"API-key format invalid."} which I think is a proper response as far I don't have API key for Binance.

    require 'json'
    require 'uri'
    require 'httparty'
    require 'openssl'
    
    def params_with_signature(params, secret)
      params = params.reject { |_k, v| v.nil? }
      query_string = URI.encode_www_form(params)
      signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), secret, query_string)
      params.merge(signature: signature)
    end
    
    params = {
        symbol: 'BNBBTC',
        side: 'BUY',
        type: 'MARKET',
        timeInForce: 'GTC',
        quantity: 1,
        recvWindow: 5000,
        timestamp: Time.now.to_i * 1000
    }
    
    BASE_URL = 'https://api.binance.com'
    api_key = ''
    api_secret = ''
    
    uri = URI("#{BASE_URL}/api/v3/order")
    
    headers = {
      'X-MBX-APIKEY': api_key,
      'Content-Type': 'text/json'
    }
    
    response = HTTParty.post(uri, headers: headers, body: params_with_signature(params, api_secret))
    
    puts response.body
    

    Let me know if it helped you :)

    For Net/Http soution you may look here: https://stackoverflow.com/questions/1252210/parametrized-get-request-in-ruby