Javascript bot programming using Gemini API, NodeJS and CryptoCompare - DISCUSSION

Try following this:

Let me know if you have more success by following the steps above. :smile:

1 Like

Has anyone recently been able to use the sandbox API to place a new order?
I get the feeling Gemini adjusted their API policies recently and it seems to me that they made “account-#####” keys to be read-only. I can’t seem to make an order with the “account-####” key as it doesn’t allow assinging trader roles. But if I use a “master-####” key then it complains of MissingAccounts (an optional parameter according to the gemini API doc for the nickname of the account being acted upon). I can’t seem to pass the correct object for that parameter or I think the wrapper is broken due to Gemini API updates. Would appreciate any insight into this…

  result: 'error',
  reason: 'MissingAccounts',
  message: 'Expected a JSON payload with accounts'

Yes I agree instructions for mac users would be very nice

1 Like

I join the mac users movement, so far, it was a pain I have even tried to install a virtual box and windows10 to use the shell and follow the course…

1 Like


Hi - I was able to use the updated API info

const key = "account-QIXkHGEGWE4SKT7gmbKWZ";

const secret = "3wEfedfewfewdefQf95KAAn6JSm6K";

const restClient = new GeminiAPI({key,secret,sandbox:true});


    "symbol": "ethusd",

    "amount": "5",

    "price": "300.00",

    "side": "buy",


    .then(response => console.log(response))


The forum swaps out quotes, so if you copy, replace the quotes. FYI,. Hope that helps

Also - I scrambled my keys in case someone wants to comment on my security habits. =)

1 Like


Thanks for your reply. I am unsure how you did this without getting an error (and without editing the index.js within the Gemini-API package). I would expect that if you did this before Gemini’s recent API changes then you would not have faced the errors which I did. Did you do it within the last few days or had you done this course some time ago ( >3 weeks)?
I ask because when I did this for the first time 2 weeks ago and followed the course plan I was unable to produce the expected result. I would like to share my results in case it resonates with other’s experience. When I tried this using an “account-XXxXXXXXXXx” key to open a trade it resulted in a “Missing roles” error (account key cannot be assigned trading role in gemini’s sandbox exchange api settings). When I tried with a “master-XxXXxXXXxX” key and received the “Missing Accounts” error I did some reading of the API documentation and figured out that “accounts: ‘primary’” needs to be added to the REST request through the extra parameters of each API function call. Alternatively one could edit the index.js of Gemini-API node package and add that account reference to line 47 (add bolded):
}, params), {account: ‘primary’};

This change allowed me to use a “master-XxXXXXXXx” key for private API calls and continue the course without too much deviation from the lesson plan.

1 Like

I just recently completed this. - When I set up the key, I looked at the master and primary, decided on primary, but checked the boxes to allow trading. - I believe there were three checkbox options, and one was disabled. I worked through a couple errors, but did not experience the Missing Roles.

Hi Joe,
Is there any reason why the .catch would not be working on my powershell?
I have added this line below to my code and it is giving me a syntax error: unexpected token ‘.’
.catch(error => console.log(error));

Its very frustrating!!

Many thanks

Sorry, I figured it out,
I had a semicolon at the end of the previous line of code and the .catch line wasnt recognized apparently.

If someone could explain that to me it would be much appreciated.

Many thanks

It literally took me 3 days to do this. Errors :crazy_face: but at least I got thru it. Keep pushing

intall hombrew, brew install yarn

1 Like

When I place an order with high price in any other coin other than Bitcoin, it gets cancelled.

order_id: ‘636143186’,
id: ‘636143186’,
symbol: ‘ltcusd’,
exchange: ‘gemini’,
avg_execution_price: ‘0.00’,
side: ‘buy’,
type: ‘exchange limit’,
timestamp: ‘1597531514’,
timestampms: 1597531514716,
is_live: false,
is_cancelled: true,
is_hidden: false,
was_forced: false,
executed_amount: ‘0’,
client_order_id: ‘-2AtmSRfn’,
reason: ‘ImmediateOrCancelWouldPost’,
options: [ ‘immediate-or-cancel’ ],
price: ‘100.00’,
original_amount: ‘1’,
remaining_amount: ‘1’

and the prices for the altcoins doesnt seem to be the correct one.
anyone having this issue?

Made a quick little script for getting the current price and MA(9), MA(20), MA(50) and MA(100) from CoinGecko-API (

The reason for using CoinGecko is simple: It is free and CryptoCompare is not (only for limited calls).

You’ll need to npm install coingecko-api for this and do additional audit request on two packages!!

// Get CoinGecko API
const CoinGecko = require(‘coingecko-api’);
const CoinGeckoClient = new CoinGecko();

// Formatter for formatting currency
const formatter = new Intl.NumberFormat(‘en-US’, {
style: ‘currency’,
currency: ‘USD’,
minimumFractionDigits: 2

// Dates in unixtimestamps
var currentDate = Math.floor( / 1000);
var dateMinus100Hours = currentDate - 360000;

// Helper function to transform unixtempstamps into readable dates
// Coingecko does not return hourly data which is accurate on the exact hour
// which is why I set the hour to 00 in the return value
function Unix_timestamp(t)
var dt = new Date(t);
var day = paddy(dt.getDate(), 2);
var month = paddy(dt.getMonth()+1, 2);
var year = dt.getFullYear();
var hr = paddy(dt.getHours(), 2);
var m = “0” + dt.getMinutes();
var s = “0” + dt.getSeconds();
return year + ‘-’ + month + ‘-’ + day + ’ ’ + hr + ‘:00’; // + m.substr(-2) + ‘:’ + s.substr(-2);

// Padding function for adding leading zero’s
function paddy(num, padlen, padchar) {
var pad_char = typeof padchar !== ‘undefined’ ? padchar : ‘0’;
var pad = new Array(1 + padlen).join(pad_char);
return (pad + num).slice(-pad.length);

// Call to CoinGecko to fetch the latest 100 hours price for bitcoin
// Also calculate the MA9, MA20, MA50 and MA100
function fetchMovingAverages(cryptoAsset, bOnlyMAs, callback) {

// results will be the string passed to the callback function
// with all the gathered information
var results = “”;

tickers: false,
market_data: true,
community_data: false,
developer_data: false,
localization: false,
sparkline: false
.then(coinData => {
results += “--------------------------------\r\n”;
results += cryptoAsset + " " + formatter.format( + “\r\n”;
results += “--------------------------------\r\n”;

    from: dateMinus100Hours,
    to: currentDate
).then(coinData =>
    // coinData has data section with prices section
    var prices =; // from newest to oldest
    var sum100 = 0;
    var sum9 = 0;
    var sum20 = 0;
    var sum50 = 0;

    // Loop over prices and return readable data to the console log
    prices.forEach((item, i) => {
      var timeStamp = Unix_timestamp(item[0]);
      var priceInUSD = formatter.format(item[1]);
      sum100 += item[1];
      if (i < 9) sum9 += item[1];
      if (i < 20) sum20 += item[1];
      if (i < 50) sum50 += item[1];
      if (bOnlyMAs == false) results += timeStamp + " " + priceInUSD;

    var movingAverage100 = formatter.format(sum100/100);
    var movingAverage9 = formatter.format(sum9/9);
    var movingAverage20 = formatter.format(sum20/20);
    var movingAverage50 = formatter.format(sum50/50);
    results += "MA(9) = " + movingAverage9 + "\r\n";
    results += "MA(20) = " + movingAverage20 + "\r\n";
    results += "MA(50) = " + movingAverage50 + "\r\n";
    results += "MA(100) = " + movingAverage100 + "\r\n";

).catch(error =>

.catch(error => {console.log(error)});

// Actual call to fetch information
fetchMovingAverages(‘bitcoin’, true, function(results)

fetchMovingAverages(‘ethereum’, true, function(results)

fetchMovingAverages(‘mantra-dao’, true, function(results)

The result :slight_smile:

1 Like

Error #1 :
“PS C:\Users…\JavaScript\bot> node index.js
(node:6120) UnhandledPromiseRejectionWarning: #
(node:6120) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag --unhandled-rejections=strict (see (rejection id: 3)
(node:6120) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.”

Fix #1 :
.then(response => console.log(response))
.catch(error => console.log(error));”

Error #2 :
“PS C:\Users…\JavaScript\bot> node index.js
result: ‘error’,
reason: ‘MissingAccounts’,
message: ‘Expected a JSON payload with accounts’

Fix #2 :
If you use a Primary API key, you should not get this error. I was using a Master API key, which need an extra parameter in the “newOrder” function specifying the account. Thus, I created a second API key, but this time I picked a Primary API key, and I modified the code to :

“restClient.newOrder({amount:10,price:100,side:“buy”,symbol:“btcusd”, account:“primary”})
.then(response => console.log(response))
.catch(error => console.log(error));”

1 Like

Note : the second API key having a primary scope might not be needed. To be tested.

Great job @Dhardesh !

Do you know the difference between these 2 wrapper :

I’m trying to use the CoinGecko API as well. I can’t connect to it though. I am using the other wrapper, which seems more recent. I installed “yarn add @coingecko/cg-api-ts” and “yarn add node-fetch”.

const CoinGeckoAPI = require("@coingecko/cg-api-ts");
const nodeFetch = require(“node-fetch”);
const cg = new CoinGeckoAPI(nodeFetch);

const cg = new CoinGeckoAPI(nodeFetch);
TypeError: CoinGeckoAPI is not a constructor
at Object. (C:…\CoinGecko\index.js:4:12)
e[90m at Module._compile (internal/modules/cjs/loader.js:1133:30)e[39m
e[90m at Object.Module._extensions…js (internal/modules/cjs/loader.js:1153:10)e[39m
e[90m at Module.load (internal/modules/cjs/loader.js:977:32)e[39m
e[90m at Function.Module._load (internal/modules/cjs/loader.js:877:14)e[39m
e[90m at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)e[39m
e[90m at internal/main/run_main_module.js:18:47e[39m

Any suggestions?

I quickly researched the two projects. The coingecko-api looks much more mature than the cg-api-ts. The first one in already past its 1.0 version, while the latter is still in beta. So I personally would prefer to use a more mature API to communicate with.

As to your error: try adding global.fetch = require(“node-fetch”); as first line in your code. Then maybe you don’t have to create a const nodeFetch line and can just use fetch.

Ivan used the same line because it was needed for CryptoCompare to run.

1 Like

Thanks! That makes sense for the maturity.

No luck with global.fetch… I might try your way. What are the 2 other audit packages you mentioned?

Not sure anymore. But when you install the npm you’ll get a warning that two requirements need to be audited. It also states the additional command to execute right after it.

1 Like