All threads / FTX.com REST API POST Authentication FAILS with Ruby on Rails and net/https
Ask A Question

Notifications

You’re not receiving notifications from this thread.

FTX.com REST API POST Authentication FAILS with Ruby on Rails and net/https

Joergen asked in Rails

Hoping for some help as this one has me baffled...

I created a user account and API credentials at FTX.com.

They have an interesting Auth setup which is detailed here: xhxtxtxpxsx://docs.ftx.com/?python#authentication

They only provide code examples for python, javascript and c#, but I need to implement the integration on a RoR app.

Here's a link which also provides an example for both GET and POST calls: xhxtxtxpxsx://blog.ftx.com/blog/api-authentication/

I'm using:

ruby '3.0.1'

gem 'rails', '~> 6.1.4', '>= 6.1.4.1'

also,

require 'uri'
require 'net/https'
require 'net/http'
require 'json'

I got the authentication working for GET calls as follows:

def get_market
 get_market_url = 'xhxtxtxpxs://ftx.com/api/markets/BTC-PERP/orderbook?depth=20'

 api_get_call(get_market_url)
end
def api_get_call(url)
    ts = (Time.now.to_f * 1000).to_i

    signature_payload = "#{ts}GET/api/markets"

    key = ENV['FTX_API_SECRET']
    data = signature_payload
    digest = OpenSSL::Digest.new('sha256')

    signature = OpenSSL::HMAC.hexdigest(digest, key, data)

    headers = {
      'FTX-KEY': ENV['FTX_API_KEY'],
      'FTX-SIGN': signature,
      'FTX-TS': ts.to_s
    }
    uri = URI.parse(url)
    http = Net::HTTP.new(uri.host, uri.port)
    http.read_timeout = 1200
    http.use_ssl = true
    rsp = http.get(uri, headers)
    JSON.parse(rsp.body)
  end

This works great and I get the correct response:

=>
{"success"=>true,
"result"=>
{"bids"=>
[[64326.0, 2.0309],
...
[64303.0, 3.1067]],
"asks"=>
[[64327.0, 4.647],
...
[64352.0, 0.01]]}}

However, I can't seem to authenticate correctly for POST calls (even though as far as I can tell I am following the instructions correctly). I use the following:

  def create_subaccount
    create_subaccount_url = 'xhxtxtxpxsx://ftx.com/api/subaccounts'

    call_body =
      {
        "nickname": "sub2",
      }.to_json

    api_post_call(create_subaccount_url, call_body)
  end
  def api_post_call(url, body)
    ts = (Time.now.to_f * 1000).to_i

    signature_payload = "#{ts}POST/api/subaccounts#{body}"

    key = ENV['FTX_API_SECRET']
    data = signature_payload
    digest = OpenSSL::Digest.new('sha256')

    signature = OpenSSL::HMAC.hexdigest(digest, key, data)

    headers = {
      'FTX-KEY': ENV['FTX_API_KEY'],
      'FTX-SIGN': signature,
      'FTX-TS': ts.to_s
    }

    uri = URI.parse(url)
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true
    request = Net::HTTP::Post.new(uri, headers)
    request.body = body
    response = https.request(request)

    JSON.parse(response.body)
  end

This is the error response:
=> {"success"=>false, "error"=>"Not logged in: Invalid signature"}

My feeling is the issue is somewhere in adding the body to signature_payload before generating the signature via HMAC here..?:
signature_payload = "#{ts}POST/api/subaccounts#{body}"

Thinking this because, if I leave out #{body} here, like so:
signature_payload = "#{ts}POST/api/subaccounts"
the response is:
=> {"success"=>false, "error"=>"Missing parameter nickname"}

I have tried several iterations of setting up the POST call method using various different net/https examples but have had no luck...
I have also contacted FTX support but have had no response.

Would truly appreciate if anyone has some insight on what I am doing wrong here?

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 68,099+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2022 GoRails, LLC. All rights reserved.