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?
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?
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);
}