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

@iamchaoticcoder

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
Andy

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

Hi
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?

1 Like

Made a quick little script for getting the current price and MA(9), MA(20), MA(50) and MA(100) from CoinGecko-API (https://www.npmjs.com/package/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(Date.now() / 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 = “”;

CoinGeckoClient.coins.fetch(cryptoAsset,
{
tickers: false,
market_data: true,
community_data: false,
developer_data: false,
localization: false,
sparkline: false
})
.then(coinData => {
results += “--------------------------------\r\n”;
results += cryptoAsset + " " + formatter.format(coinData.data.market_data.current_price.usd) + “\r\n”;
results += “--------------------------------\r\n”;

CoinGeckoClient.coins.fetchMarketChartRange(
  cryptoAsset,
  {
    from: dateMinus100Hours,
    to: currentDate
  }
).then(coinData =>
  {
    //console.log("--------------------------------");
    //console.log(cryptoAsset);
    //console.log("--------------------------------");
    // coinData has data section with prices section
    var prices = coinData.data.prices.reverse(); // 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";

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

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

// Actual call to fetch information
fetchMovingAverages(‘bitcoin’, true, function(results)
{
console.log(results);
}
);

fetchMovingAverages(‘ethereum’, true, function(results)
{
console.log(results);
}
);

fetchMovingAverages(‘mantra-dao’, true, function(results)
{
console.log(results);
}
);

1 Like

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 https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (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 :
“restClient.newOrder({amount:10,price:100,side:“buy”,symbol:“btcusd”})
.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”.


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


Error:
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

@filip I haven’t found a way to continue this course on Mac. The problem I’m facing is with Yarn and gemini-api.

I have this structure in my folder named “algotrading”:
index.js
node_modules
package-lock.json
package.json

The folder “node_modules” has “yarn” folder in it. So I understand the Yarn is installed.

Now when I run the command:
[algotrading]$ yarn add gemini-api

I get this result:
-bash: yarn: command not found
[algotrading]$

What I’m missing here? Thanks!

What do you mean by “The forum swaps out quotes, so if you copy, replace the quotes.”. Do you mean to delete the quotes?

1 Like

This was just in response to a code snippet that had left quote and right quotes, and the IDE did not like that. I was considering running through this on my mac to try and help out.
Does your mac say anything about using zsh instead of bash?

Fixed using this in my Mac terminal:

I didnt have an account on Gemini, but decided to create one to be able to follow along before trying to do the same at another exchange. I get stuck at the SMS verification part of signing up. I inserted my phone number, no SMS , sent code again, but still no SMS.

Anyone else with this problem? I understand that it’s a US exchange and that most things in the US suck and require this and that, but cmon, if I give the number why cant your crappy system send that friggin SMS to register?

No way im ever giving a penny to Gemini.

1 Like