Search code examples
pythongoogle-apps-scriptgoogle-gemini

Gemini API: "InvalidSignature" in App Scripts


I am attempting to call Gemini API using App Scripts but I am consistently getting the 'InvalidSignature' error message. The code that I am using is a conversion of the python code from their documentation for Private API Invocation.

Code:

function createHeaders(payload) {
  var geminiApiKey = API_KEY
  var geminiApiSecret = SECRET_KEY
  var encodedApiSecret = Utilities.newBlob(geminiApiSecret, 'UTF-8').getBytes()

  var payloadNonce = new Date().getTime() / 1000;
  payload["nonce"] = Math.round(payloadNonce);

  var encodedPayload = Utilities.newBlob(JSON.stringify(payload), 'UTF-8').getBytes()
  var b64 = Utilities.base64Encode(encodedPayload) //string

  var signature = Utilities.computeHmacSignature(
    Utilities.MacAlgorithm.HMAC_SHA_384,
    b64,
    geminiApiSecretAuditor 
  ) //bytes

  return {
    "Content-Type": "text/plain",
    "X-GEMINI-APIKEY": geminiApiKeyAuditor,
    "X-GEMINI-PAYLOAD": b64,
    "X-GEMINI-SIGNATURE": Utilities.base64Encode(signature), //string
    "Cache-Control": "no-cache"
  };
}

function fetchGeminiData() {
  var baseUrl = "https://api.gemini.com";
  var url = baseUrl + "/v1/mytrades";

  var payload = {
    "request": "/v1/mytrades"
  };

  var headers = createHeaders(payload);
  var options = {
    "method": "post",
    "headers": headers,
  };

  var response = UrlFetchApp.fetch(url, options);
  var responseData = response.getContentText();
  var jsonResponse = JSON.parse(responseData);
  Logger.log(jsonResponse);
}

The error messages:

Exception: Request failed for https://api.gemini.com returned code 400. Truncated server response: {"result":"error","reason":"InvalidSignature","message":"InvalidSignature"}

I have ensured that the object types are as per what is expected from each methods, but I still get the above error messages. What am I missing?


Solution

  • I believe your goal is as follows.

    • You want to convert the following Python script to Google Apps Script. Ref

      import requests
      import json
      import base64
      import hmac
      import hashlib
      import datetime, time
      
      url = "https://api.gemini.com/v1/mytrades"
      gemini_api_key = "mykey"
      gemini_api_secret = "1234abcd".encode()
      
      t = datetime.datetime.now()
      payload_nonce = time.time()
      payload =  {"request": "/v1/mytrades", "nonce": payload_nonce}
      encoded_payload = json.dumps(payload).encode()
      b64 = base64.b64encode(encoded_payload)
      signature = hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()
      
      request_headers = {
          'Content-Type': "text/plain",
          'Content-Length': "0",
          'X-GEMINI-APIKEY': gemini_api_key,
          'X-GEMINI-PAYLOAD': b64,
          'X-GEMINI-SIGNATURE': signature,
          'Cache-Control': "no-cache"
          }
      
      response = requests.post(url, headers=request_headers)
      
      my_trades = response.json()
      print(my_trades)
      

    In this case, how about the following sample script?

    Sample script:

    function myFunction() {
      API_KEY = "mykey"; // Please set your api key.
      SECRET_KEY = "1234abcd"; // Please set your secret.
    
      var gemini_api_key = API_KEY;
      var gemini_api_secret = SECRET_KEY;
    
      var baseUrl = "https://api.gemini.com";
      var url = baseUrl + "/v1/mytrades";
      var nonce = (new Date().getTime() / 1000).toString();
      var payload = `{"request": "/v1/mytrades", "nonce": "${nonce}"}`;
      var b64 = Utilities.base64Encode(payload);
      var signature = Utilities.computeHmacSignature(Utilities.MacAlgorithm.HMAC_SHA_384, b64, gemini_api_secret).map(b => ('0' + (b & 0xFF).toString(16)).slice(-2)).join('');
      var request_headers = {
        'Content-Type': "text/plain",
        'X-GEMINI-APIKEY': gemini_api_key,
        'X-GEMINI-PAYLOAD': b64,
        'X-GEMINI-SIGNATURE': signature,
        'Cache-Control': "no-cache"
      };
      var options = { method: "post", headers: request_headers };
      var response = UrlFetchApp.fetch(url, options);
      var responseData = response.getContentText();
      var jsonResponse = JSON.parse(responseData);
      console.log(jsonResponse);
    }
    

    Note:

    • I think that the request of this sample script is the same as the above Python script. But, unfortunately, I cannot test this script. So, if an error occurs, please confirm your API key, your secret, and the URL again.

    Reference: