ccxt: itBit fetchBalance Error with signature

  • OS: High Sierra v10.13.6
  • Node.js v8.9.4
  • CCXT v1.17.88
  • Exchange: itBit
  • Method: fetchBalance

The Issue:

When I try calling the fetchBalance Method I get back a 401 unauthorized from itBit for having a bad signature. I know my credentials are valid because when I use a different library (npm itbit) the response is fine.

Code:

const ccxt = require("ccxt");

const getBalances = async () => {
  try {
    const client = new ccxt.itbit({
      apiKey: 'API_KEY',
      secret: 'API_SECRET',
      userId: 'USER_ID',
      verbose: true
    });

    const accounts = await client.fetchBalance();
    console.log(accounts);
    return;
  } catch (error) {
    console.log(error);
    return error;
  }
};

getBalances();
fetch:
 itbit GET https://api.itbit.com/v1/wallets?userId='USER_ID' 
Request:
 { Authorization: 'API_KEY:signature',
  'Content-Type': 'application/json',
  'X-Auth-Timestamp': '1533766553321',
  'X-Auth-Nonce': '1533766553321' }
Response: 
{ Error: itbit GET https://api.itbit.com/v1/wallets?userId='USER_ID' 401 Unauthorized {"code":10002,"description":"Your request lacked a valid signature, and could not be authenticated.","requestId":"REQUEST_ID"}

I was curious if anybody else has ran into this same issue. I’m assuming it is because the signature is being generated incorrectly in some portion of the sign method in itbit.js. I am currently looking into it, but if somebody could help me out that would be much appreciated.

Thanks, Trent

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 15 (10 by maintainers)

Commits related to this issue

Most upvoted comments

@gRittyKitty i’ve uploaded the fix provided by @trentduncan, it will be available in 5-10 minutes in version 1.18.113. It would be great if you could help us test it and report if everything works on your side. Thx!

@kroitor I have confirmed it is an issue in the sign method in itbit.js.

When I changed the signature generation in CCXT It is working.

Here is the code for reference:

ccxt/js/itbit.js

// this import is also required
const crypto = require('crypto');

sign( path, api = "public", method = "GET", params = {}, headers = undefined, body = undefined) {
    let url = this.urls["api"] + "/" + this.version + "/" + this.implodeParams(path, params);
    let query = this.omit(params, this.extractParams(path));
    if (method === "GET" && Object.keys(query).length)
      url += "?" + this.urlencode(query);
    if (method === "POST" && Object.keys(query).length) body = this.json(query);
    else body = "";
    if (api === "private") {
      this.checkRequiredCredentials();
      let nonce = this.nonce().toString();
      let timestamp = nonce;

      // start of new code

      const message =
        nonce +
        JSON.stringify([
          method,
          url,
          "",
          nonce.toString(),
          timestamp.toString()
        ]);

      const hashBuffer = crypto
        .createHash("sha256")
        .update(message)
        .digest();

      const bufferToHash = Buffer.concat([Buffer.from(url), hashBuffer]);

      const signature = crypto
        .createHmac("sha512", this.secret)
        .update(bufferToHash)
        .digest("base64");

      // end of new code

      headers = {
        Authorization: this.apiKey + ":" + signature,
        "Content-Type": "application/json",
        "X-Auth-Timestamp": timestamp,
        "X-Auth-Nonce": nonce
      };
    }
    return { url: url, method: method, body: body, headers: headers };
  }

I don’t know if this change will work for all of the methods you support for itbit because the empty string in the message is hardcoded since it is a GET request. It will have to be refactored, but it fixes the fetchBalance issue.

@kroitor Yes I can confirm I tried ccxt with a fresh key before the other library.

Yes. Also when I go back and forth between the other library and ccxt the other library works consistently.