Giter Club home page Giter Club logo

coinbase-pro-node's Introduction

Important

On 2022-06-22 Coinbase announced that it will discontinue the Pro API in favor of its Advanced Trade API.

With this news the coinbase-pro-node package, which has been serving users effectively since 2019-04-11, will become non functional.

Luckily, the code of this library is open-source, allowing you to fork it and tailor it to the new Advanced Trade API. Coinbase offers a Pro to Advanced Trade API Mapping guide to assist in this process.

Coinbase API

Language Details Code Coverage License Package Version


๐ŸŒŸ Better than the original Coinbase API. See why. ๐ŸŒŸ

Community-maintained Coinbase API for Node.js & Deno, written in TypeScript and covered by tests.

Motivation

The purpose of this coinbase-pro-node package is to maintain a recent Coinbase API for Node.js with type safety through TypeScript.

Features

  • โœ… Typed. Source code is 100% TypeScript. No need to install external typings.
  • โœ… Tested. Code coverage is 100%. No surprises when using "coinbase-pro-node".
  • โœ… Convenient. Request throttling is built-in. Don't worry about rate limiting.
  • โœ… Comfortable. More than an API client. You will get extras like candle watching.
  • โœ… Maintained. Automated security updates. No threats from outdated dependencies.
  • โœ… Documented. Get started with demo scripts and generated documentation.
  • โœ… Modern. HTTP client with Promise API. Don't lose yourself in callback hell.
  • โœ… Robust. WebSocket reconnection is built-in. No problems if your Wi-Fi is gone.
  • โœ… Reliable. Following semantic versioning. Get notified about breaking changes.

Installation

npm

npm install coinbase-pro-node

Yarn

yarn add coinbase-pro-node

Setup

JavaScript

const {CoinbasePro} = require('coinbase-pro-node');
const client = new CoinbasePro();

TypeScript

import {CoinbasePro} from 'coinbase-pro-node';
const client = new CoinbasePro();

Usage

The demo section provides many examples on how to use "coinbase-pro-node". There is also an automatically generated API documentation. For a quick start, here is a simple example for a REST request:

REST Example

import {CoinbasePro} from 'coinbase-pro-node';

// API Keys can be generated here:
// https://pro.coinbase.com/profile/api
// https://public.sandbox.pro.coinbase.com/profile/api
const auth = {
  apiKey: '',
  apiSecret: '',
  passphrase: '',
  // The Sandbox is for testing only and offers a subset of the products/assets:
  // https://docs.cloud.coinbase.com/exchange/docs#sandbox
  useSandbox: true,
};

const client = new CoinbasePro(auth);

client.rest.account.listAccounts().then(accounts => {
  const message = `You can trade "${accounts.length}" different pairs.`;
  console.log(message);
});

WebSocket Example

If you want to listen to WebSocket messages, have a look at these demo scripts:

Demos

All demo scripts are executable from the root directory. If you want to use specific credentials with a demo script, simply add a .env file to the root of this package to modify environment variables used in init-client.ts.

npx ts-node ./src/demo/dump-candles.ts

Tip: There is a .env.defaults file which serves as a template. Just remove its .defaults extension and enter your credentials to get started. Do not commit this file (or your credentials) to any repository!

Web Frontend Applications

The "coinbase-pro-node" library was built to be used in Node.js environments BUT you can also make use of it in web frontend applications (using React, Vue.js, etc.). However, due to the CORS restrictions of modern web browser, you will have to use a proxy server.

A proxy server can be setup with webpack's DevServer proxy configuration or http-proxy-middleware.

Here is an example:

Backend

import {createProxyMiddleware} from 'http-proxy-middleware';
import express from 'express';

const app = express();

app.use(
  '/api-coinbase-pro',
  createProxyMiddleware({
    target: 'https://api.exchange.coinbase.com',
    changeOrigin: true,
    pathRewrite: {
      [`^/api-coinbase-pro`]: '',
    },
  })
);

Later on, you can use the proxy URL (/api-coinbase-pro from above) in your web application to initialize "coinbase-pro-node" with it:

Frontend

const client = new CoinbasePro({
  httpUrl: '/api-coinbase-pro',
  apiKey: '',
  apiSecret: '',
  passphrase: '',
  useSandbox: false,
});

Real-world Examples

Checkout GitHub's dependency graph to see who uses "coinbase-pro-node" in production. There are also npm packages depending on "coinbase-pro-node".

Maintainers

Benny Neugebauer on Stack Exchange

Stargazers

Stargazers

Contributing

Contributions, issues and feature requests are welcome!

Feel free to check the issues page.

The following commits will help you getting started quickly with the code base:

All resources can be found in the Coinbase Exchange API reference. For the latest updates, check Coinbase's API Changelog.

License

This project is MIT licensed.

โญ๏ธ Show your support โญ๏ธ

Please leave a star if you find this project useful.

If you like this project, you might also like these related projects:

  • trading-signals, Technical indicators, written in TypeScript, with arbitrary-precision arithmetic.
  • ig-trading-api, REST API, written in TypeScript, for CFD trading with IG.
  • binance-api-node, Heavily tested and Promise-based Binance API with TypeScript definitions.

Problems with official Coinbase APIs

There are official Coinbase APIs for Node.js, but they all come with some disadvantages leading to decreased developer experience (DX):

  1. Coinbase's first Node.js API has no type safety and got deprecated on July, 19th 2016
  2. Coinbase's second Node.js API has no type safety and got deprecated on January, 16 2020
  3. Coinbase's current Node.js API (OAS spec) still lacks type safety and does not incorporate best practices like automatic reconnections and request throttling

Official Coinbase API

Coinbase is versioning its API through ReadMe.com, so you can generate an API client from their OpenAPI Specification. ReadMe provides a Node.js package named "api" which allows you to retrieve an automatically generated Node.js client:

Installation

npm install api@^4.5.1

Usage

import api from 'api';

const sdk = api('@coinbase-exchange/v1.0#qgumw1pl3iz4yut');

sdk['ExchangeRESTAPI_GetProductTrades']({
  product_id: 'BTC-USD',
}).then(response => {
  console.log(`Found "${response.length}" trades.`);
});

Drawbacks

The current Coinbase Node.js SDK (provided by the api package) does not support typings for response payloads:

Official Coinbase API

coinbase-pro-node's People

Contributors

akwodkiewicz avatar alexander-hagen avatar aliasbody avatar antriver avatar bengotow avatar bennycode avatar definitelycarter avatar dependabot-preview[bot] avatar dependabot[bot] avatar edmundpf avatar hjoelr avatar jdgriffith avatar jonluca avatar ohkthx avatar piotr-roslaniec avatar quezak avatar tcar121293 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

coinbase-pro-node's Issues

feat: useSandbox optional

In 2.15.0 and earlier, the useSandbox parameter was optional in

this._client=new CoinbasePro({ apiKey: account.apikey, apiSecret: account.secret, passphrase: account.passphrase})

From 2.16.0 the useSandbox parameter is mandatory

this._client=new CoinbasePro({ apiKey: account.apikey, apiSecret: account.secret, passphrase: account.passphrase, useSandbox: false })

Can we make useSandbox optional again and have it default to false?

Websocket connection argument

Hi @bennyn, I have been running the library and so far so good. I would like to point out an issue I got today, though this is not a library issue, I think.

So, today websocket was trying to reconnect for more than 15 minutes and it couldn't. I restarted the program and it connected. Even though the Coinbase Pro documentation says that it is 4 seconds interval I think it prevents to reconnect at some point (if you keep reconnecting).

Don't you think it would be a good idea to provide an option to set a reconnection interval when websocket connects (in connect() method)?

Please let me know what do you think.

Issue with WS Documentation

Hey thanks for building and maintaining this package. I was attempting to migrate from depreciated coinbase-pro package and unfortunately, my event listeners are not firing using the example provided in the docs.

I attempted to go through the code in coinbase-pro-node/src/client/WebSocketClient.ts and I was not able to even find subscribeToTickers method in src. I do not have a good grasp of typescript so it could be part of the problem.

(I created a simplified gist using the old package), would it be possible for me to implement an identical/similar system for handling WS messages as I have done below?

1. Subscribe to multiple channels ex ['ticker', 'full']
2. receive all channel updates to one event listener [WebSocketEvent.ON_MESSAGE'] so I can redirect them to a switch statement.
3. store an instance of the socket and resubscribe/ destroy recreate

https://gist.github.com/Slurpgoose/ab41a4674a7a353b8f68b9d80af2b004

Also if this is possible will I need to import WebSocketEvent, WebSocketChannelName objects to access these methods or are they inherited from new CoinbasePro(auth)? Or am I able to subscribe using a string.

Getting internal server error on crypto transfer

I've been getting an internal server error for a couple of hours on a crypto transfer.

client.rest.withdraw.postCryptoWithdrawal(0.0000001, 'BTC', '339FL7Xoh3WmrcJmo6ejeLfBVZgus2fTdx', true).then((data) => {
    console.log('===============')
    console.log('Transfering DATA')
    console.log(data)
}).catch((error) => {
    console.log('===============')
    console.log('Transfering DATA')
    console.log(error)
})

Do we have support for /withdraw/coinbase-account? That would be much easier, and have no fees. Thanks again!

getProductHistoricRates function?

What is the equivalent in your library to the following code from the coinbase-pro library:

publicClient.getProductHistoricRates(
  'BTC-USD',
  { 
    granularity: 3600,
    start: start_time,
    end: end_time
  }  
)

Better error surfacing

I'm getting a 400 error message when using your library but nothing very specific beyond that. Is there way to surface the errors a little better on the rest calls?

Thanks!

Return value must be between brackets

When returning a structure in a function in NodeJS, the returnvalue must be between brackets. Otherwise it returns {}. There are 7 files with 10 occurences where this should be fixed.

I tried to create a pull request, but it removed the brackets, or assigning the structure to a variable first

Websocket Reconnection Failes

Hi @bennyn I am still having a reconnection issue though I changed connect() parameters.

So, at some point websocket establishes connection and then closes, and this run as a loop. On ON_OPEN it shows that it establishes connect and just after that ON_CLOSE it says convection closed and repeats the same. I have to manually stop and run program in order to make it work.

Any recommendation and/or suggestion? should I subscribe every time when it reconnects again?

Querying ALL Orders

An opportunity to improve documentation:

Related to #339, I was curious how to query for all orders (rather than for open orders alone). It seemed like the only parameters we could pass with the request were pagination values. After a quick scan of the source I realized a general query-string is created from whatever object is passed as the pagination object (thanks to loose restrictions on the interface). As such, getOpenOrders({ status: 'all' }) would suffice to retrieve all orders.

async getOpenOrders(pagination?: Pagination): Promise<PaginatedData<Order>> {
const resource = OrderAPI.URL.ORDERS;
const response = await this.apiClient.get<Order[]>(resource, {params: pagination});
return {
data: response.data,
pagination: {
after: response.headers['cb-after'],
before: response.headers['cb-before'],
},
};
}

Backlog

No valid WebSocket class provided

Hi

I'm trying to use coinbase-pro-node in a Vue app but I'm receiving the following error when trying to use the websocketclient

Error: No valid WebSocket class provided
_connect reconnecting-websocket-mjs.js:506
ReconnectingWebSocket reconnecting-websocket-mjs.js:203
connect WebSocketClient.js:159
_callee$ VCoinbaseSocket.vue:49
Babel 10
VueJS 4
click vuetify.js:2564
VueJS 33
VCoinbaseSocket.vue:51

Any ideas?

Thanks

Watch Candles

Observed on watching one minute candles.
When candle minutes are skipped from coinbase api due to no activity candle watch of 1 minute is stuck.
Suggest
const matches = candles.filter((candle: any) => {
const open = new Date(candle.openTimeInISO)
const expected = new Date(expectedTimestampISO)
return open >= expected !Changed to >=
})

Latest axios seems to cache the get candle history automatically perhaps
in getCandles pass date or header to force fresh get
const response = await this.apiClient.get<RawCandle[]>(resource, {
params: { ...params, time: new Date() },
})

How to Get Complete Response from getCandles()

The following seems to only return the body from the response:

client.rest.product.getCandles('BTC-USD', {
  granularity: CandleGranularity.ONE_HOUR,
  start: start_time,
  end: end_time
});

How do you get the complete response including, e.g., the status code?

CORS issue when using coinbase-pro-node in web application

EDIT:
I'm also seeing this on private endpoints not just market data endpoints. So, I am not entirely sure if there is an issue here, may just be an issue with my stack.

First off, I really appreciate the work put into this project, I think its great and I would really like to be using it long term. I'd love to contribute as well, if I am knowledgeable enough, and I'll most likely take a stab as creating a patch for this issue locally.

That being said, here is my issue:

Initially I see that in my console this appears:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api-public.sandbox.pro.coinbase.com/products/BTC-USD/candles?granularity=60. (Reason: missing token โ€˜cb-access-keyโ€™ in CORS header โ€˜Access-Control-Allow-Headersโ€™ from CORS preflight channel)

I am attempting to integrate this library with a react application, using gatsbyjs. Everything imports and builds as I expect, however at runtime I see that the cb-access-key is checked for in every OPTIONS request:

Access-Control-Request-Headers | cb-access-key,cb-access-passphโ€ฆcess-sign,cb-access-timestamp
-- | --

But, this value is not listed in the response headers:

access-control-allow-headers | Content-Type, Accept, cb-session, cb-fp, cb-form-factor
-- | --

I've seen this while trying to use the rest client, such as with the getProductTicker() method and while trying to get the rest-watch-candles demo code to run in browser similarly to this:

const WatchCandle = ({client, productId, granularity}) => {
  let [candle,setCandle] = useState({});

  async function setWatch() {
    client.rest.on(ProductEvent.NEW_CANDLE, (productId, granularity, candle) => {
      console.info('Recent candle', productId, granularity, candle.openTimeInISO);
    });

    // 3. Get latest candle
    const candles = await client.rest.product.getCandles(productId, {
      granularity,
    });
    const latestCandle = candles[candles.length - 1];
    const latestOpen = latestCandle.openTimeInISO;
    console.info('Initial candle', productId, granularity, latestOpen);

    // 4. Subscribe to upcoming candles
    client.rest.product.watchCandles(productId, granularity, latestOpen);
  }

  useEffect(() => {
    setWatch();
  });

  return (<>Waiting...</>)
}

For reference on why I think its an issue with looking for that cb-access-key token on every request to coinbase, excerpt from here:

The Access-Control-Allow-Headers header is sent by the server to let the client know which headers it supports for CORS requests. The value of Access-Control-Allow-Headers should be a comma-delineated list of header names, such as "X-Custom-Information" or any of the standard but non-basic header names (which are always allowed).

This error occurs when attempting to preflight a header that is not expressly allowed (that is, it's not included in the list specified by the Access-Control-Allow-Headers header sent by the server). To fix this, the server needs to be updated so that it allows the indicated header, or you need to avoid using that header.

Angular app throws problem because of Crypto dependency

Hello, I was really looking forward to using this in my Angular project as it has TypeScript support and that's a huge plus for me, but when using it in something browser based, it doesn't work because of the Crypto dependency from what I gathered. Do you have any solution to this?

How get txHash?

I detecting new deposit from getAccountHistory method, but there is no txHash in the details. How do I get a transaction hash from api? What is a details.transfer_id for?

listAccounts() returns getTime(), sometimes

Usually, listAccounts() works fine and returns the balances of the requested account.


newbalances=await account._client.rest.account.listAccounts();
if(newbalances.length===undefined) { console.log("Newbalances:"+JSON.stringify(newbalances)); };

Sometimes it returns getTime(). Newbalances:{"iso":"2021-01-15T09:22:55.205Z","epoch":1610702575.205}

Again Websocket Reconnection

@bennyn So I partially tested websocket connection issue. When I manually connect to the Coinbase Pro websocket (wss://ws-feed.pro.coinbase.com) it works and in 24 hours hasn't broken yet, but in your library I still got loop (connect and reconnect). See timestamp list. Again when I restart the program it connects and listens for a while.

...
[2020-04-03T14:01:30.517Z] Coinbase Pro websocket established connection!
[2020-04-03T14:02:29.572Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:02:34.818Z] Coinbase Pro websocket established connection!
[2020-04-03T14:03:34.134Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:03:39.382Z] Coinbase Pro websocket established connection!
[2020-04-03T14:04:39.111Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:04:44.338Z] Coinbase Pro websocket established connection!
[2020-04-03T14:05:44.001Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:05:49.252Z] Coinbase Pro websocket established connection!
[2020-04-03T14:06:48.941Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:06:54.177Z] Coinbase Pro websocket established connection!
[2020-04-03T14:07:53.531Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:07:58.881Z] Coinbase Pro websocket established connection!
[2020-04-03T14:08:58.573Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:09:03.833Z] Coinbase Pro websocket established connection!
[2020-04-03T14:10:03.432Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:10:08.674Z] Coinbase Pro websocket established connection!
[2020-04-03T14:11:07.984Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:11:13.226Z] Coinbase Pro websocket established connection!
[2020-04-03T14:12:12.450Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:12:17.675Z] Coinbase Pro websocket established connection!
[2020-04-03T14:13:17.068Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:13:22.295Z] Coinbase Pro websocket established connection!
[2020-04-03T14:14:22.171Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:14:27.450Z] Coinbase Pro websocket established connection!
[2020-04-03T14:15:27.345Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:15:32.567Z] Coinbase Pro websocket established connection!
[2020-04-03T14:16:32.200Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:16:37.476Z] Coinbase Pro websocket established connection!
[2020-04-03T14:17:37.124Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:17:42.351Z] Coinbase Pro websocket established connection!
[2020-04-03T14:18:42.161Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:18:47.394Z] Coinbase Pro websocket established connection!
[2020-04-03T14:19:46.614Z] Coinbase Pro websocket was closed, it will reconnect again
[2020-04-03T14:19:51.846Z] Coinbase Pro websocket established connection!

OrderStatus.DONE should be a valid OrderStatus for listing orders

Docs: https://docs.pro.coinbase.com/#list-orders

Your API is called getOpenOrders, and I suppose it makes sense to have only open statuses available, but it seems that you may be missing a simple getOrders method that will accept any OrderStatus.

It would be nice to be able to use OrderStatus.DONE without having to use @ts-ignore. I could just use all for my purposes, but I feel like that could cause problems without extra filtering at some point.

401 request timestamp expired

I have a function that is called once per minute to refresh account balances:

newbalances=await account._client.rest.account.listAccounts();

This function mostly has no issues, but I get a "request timestamp expired" message after some time. I haven't been able to catch the error and the program thus terminates unexpectedly.

I have noticed that in these cases CB-ACCESS-TIMESTAMP has a value of NaN. I don't know if this is the cause, or not.

headers: {
  Accept: 'application/json, text/plain, */*',
  'CB-ACCESS-KEY': '*** VALID KEY ***',
  'CB-ACCESS-PASSPHRASE': '*** VALID PASS *** ',
  'CB-ACCESS-SIGN': '*** VALIG SIGNATURE ***',
  'CB-ACCESS-TIMESTAMP': NaN,
  'User-Agent': 'axios/0.21.0'
},

and the response is

response: {
status: 401,
statusText: 'Unauthorized',
...
data: { message: 'request timestamp expired' }
},

How to modify ErrorUtil.js to catch request timestamp expired so that the request is tried. I also have 400 request timeout, which I would also like handle in ErrorUtil.js, and have them retried.
401 Unauthorized - Timestamp expired.txt

Support for ETH-USD pair

In the previous deprecated version of Coinbase-pro-node, the only pairs returned when running getProduct(), were what is listed below. Noticeably missing is ETH-USD pair. Will this package have any support for ETH-USD pair?

  • ETH-BTC
  • LINK-USDC
  • BTC-EUR
  • BAT-USDC
  • BTC-GBP
  • BTC-USD

Are websocket L2 events supported?

I was reviewing the websocket client code and didnt see where L2 updates were being returned and just wanted to double check if they are in fact supported?

type WebSocketMessage =
| Record<string, string | number | boolean>
| WebSocketStatusMessage
| WebSocketTickerMessage
| WebSocketMatchMessage
| WebSocketErrorMessage;
export interface WebSocketErrorMessage {
message: string;
reason: string;
type: WebSocketResponseType.ERROR;
}
export interface WebSocketMatchMessage {
maker_order_id: UUID_V4;
price: string;
product_id: string;
sequence: number;
side: OrderSide;
size: string;
taker_order_id: UUID_V4;
time: ISO_8601_MS_UTC;
trade_id: number;
type: WebSocketResponseType.FULL_MATCH;
}
export interface WebSocketStatusMessage {
currencies: {
convertible_to: string[];
details: CurrencyDetail;
funding_account_id: string;
id: string;
max_precision: string;
min_size: string;
name: string;
status: 'online';
status_message?: string;
}[];
products: (Product & {type: 'spot'})[];
type: WebSocketResponseType.STATUS;
}
export interface WebSocketTickerMessage {
best_ask: string;
best_bid: string;
high_24h: string;
last_size: string;
low_24h: string;
open_24h: string;
price: string;
product_id: string;
sequence: number;
side: OrderSide;
time: ISO_8601_MS_UTC;
trade_id: number;
type: WebSocketResponseType.TICKER;
volume_24h: string;
volume_30d: string;
}

Websocket authentication problems

I apologize in advance, as this very well could be user error. But I was hoping you could help me connect to the user channel via Websocket. I've been trying to figure it out all day, with no success. Here is the simplified code I've been using:

const {CoinbasePro} = require('coinbase-pro-node');

const auth = {
  apiKey: '',
  apiSecret: '',
  passphrase: '',
  useSandbox: false,
};

const client = new CoinbasePro(auth);

const channel = {
  name: 'user',
  product_ids: ['BTC-USD'],
};

client.ws.on('message', message => {
  console.info(`Received message of type "${message.type}".`, message);
});

client.ws.on('error', errorMessage => {
  throw new Error(`${errorMessage.message}: ${errorMessage.reason}`);
});

client.ws.on('open', () => {

	console.log('OPENED....')

  client.ws.subscribe(channel);
});

client.ws.connect();

It's copied from an example I found in a closed issue for this module in an attempt to avoid any mistakes. However, it does not seem to work... the "OPENED...." console log never fires. And no message or errors seem to be triggered.

My authorization details are correct, which I can verify because the REST API version works properly.

Thanks in advance for any help! And thanks either way for the work you've put into the module.

Help please!

So I am stuck just trying to figure out how to just get the rest example given to work. I have it installed properly using node but every time I try to use it there's some sort of stupid error.

First trying to use it I got the error "Cannot use import statement outside of a module"
So I said okay and added the "type=module" to my code.

Then I get "Failed to resolve module specifier "CoinbasePro". Relative references must start with either "/", "./", or "../""
So I tried adding one of the characters it says.

Regardless of which one I use I get the error "net::ERR_ABORTED 404 (Not Found)"

The file I am running this from is in the root directory of the site. Does it have to be within the node_modules folder?

If anyone can assist me id appreciate it please!

Authentication is not passed to WS Client

Hi @bennyn ,

its me again, unfortunately I came across a new issue in regards to WebSocketChannelName.USER.

auth config is not passed to class WebSocketClient and I was not able to find a method inside the class to retrieve a new signature.

I was able to monkey patch the latest version by passing
the configuration to WebsocketClient here

As well by adding a validation here

      if (message.channels.some(channel => channel.name === 'user') && signature === undefined){
           signature= signRequest(this.auth, 'GET', '/users/self/verify');
       }

Although you already have implemented the logic for creating a signature in coinbase-pro-node/src/auth
I added these functions from depreciated coinbase-node package to return a signature since they were easier for me to understand.


const checkAuth = (auth) => {
    if (auth && !(auth.apiKey && auth.apiSecret && auth.passphrase)) {
        throw new Error(
            'Invalid or incomplete authentication credentials. Please provide all of the key, secret, and passphrase fields.',
        );
    }
    return auth || {};
};

const signRequest = (auth, method, path, options = {}) => {
    checkAuth(auth);
    const timestamp = Date.now() / 1000;
    let body = '';
    if (options.body) {
        body = JSON.stringify(options.body);
    } else if (options.qs && Object.keys(options.qs).length !== 0) {
        body = `?${querystring.stringify(options.qs)}`;
    }
    const what = timestamp + method.toUpperCase() + path + body;
    const key = Buffer.from(auth.apiSecret, 'base64');
    const hmac = crypto.createHmac('sha256', key);
    const signature = hmac.update(what).digest('base64');
    return {
        key: auth.apiKey,
        signature,
        timestamp,
        passphrase: auth.passphrase,
    };
};

I appreciate all the work you have done on this project and just wanted to share the issue in case I missed something or so it could be fixed in a future release.

if this solution seems reasonable (except for the 2 unnecessary functions from the old package) let me know and Id be happy to make a PR.

Your .dependabot/config.yml contained invalid details

Dependabot encountered the following error when parsing your .dependabot/config.yml:

The property '#/update_configs/0/default_assignees' did not contain a minimum number of items 1
The property '#/update_configs/0/ignored_updates' did not contain a minimum number of items 1

Please update the config file to conform with Dependabot's specification using our docs and online validator.

Invalid Order Type error

I'm trying to place a market order with a stop loss set below the current trade price but I get an error Invalid order_type market when I do. The code I am using is below

client.rest.order.placeOrder({
    type: "market",
    funds: "100",
    side: "buy",
    product_id: 'BTC-USD',
    stop: "loss",
    stop_price: "19300"
}).then(res => {
    console.log(res);
}).catch(err => {
    console.log(err);
});

It works fine if I remove the stop loss but fails if I keep it, even though the API documentation says otherwise

Feature Request: Emit Error Event on Network connection loss & heartbeat tracking

Hi, Ive finished transitioning over to using this library and everything seems to be working great!

A couple things I have concerns about:

  1. When network loss occurs reconnecting-websockets is able to handle reconnecting and messages automatically continue a few seconds later. Unfortunately there is no event emitted and so I am using a timer to keep track of how many subscribed markets did not receive a message per 1005ms interval (5ms to account for timer variance).

The reason I believe this is important is because, I use a unix socket to transmit exchange snapshots to another systemd services that handle buying and selling and I want to prevent placing limit orders based on incorrect market data.

  1. when reconnecting occurs client.ws.subscribe() is not called and therefore snapshots/last_match are not emitted. Meaning the orderbook has potential to be incorrect when a long interrupt occurs. (worst case scenario is some asks could be lower than the current bid causing a limit order to be a market order and loosing money).

At this point I am keeping track of max acceptable time disconnected and manually resubscribing.

  1. Along with using the timer to track when messages stop being emitted, I verify to make sure I receive one beat per channel subscribed per minute. My timer implementation is semi-accurate (1-5ms variation) and it seems that I miss maybe 50 out of 650,000 messages or so, in some instances they are delayed and not actually missed while other times maybe a silent reconnect occurs or some other bottleneck in my application.

Initially I had a lot more missed messages as a result of poor implementation on my end. I ended up using clinic and node-tick-processor to figure it out.

By implementing more error events new users of this library will be able to debug their issues faster.

my mistakes

  • I was subscribed to too many channels (bandwidth bottleneck).
  • I was doing too much processing in this thread and after 6 or 8 hours I would get 100% cpu utilization and was not getting any indication of missing data prior to setting up my own beat tracking.

coinbase pro has a built in sequenceId to track messages for all channels unfortunately it seems to require being subscribed to the full channel in order for sequence numbers to be in sync and l2_updates do not have a sequenceId.

To combat this instead of saving the sequence number I started taking the timestamp to save new Date(timestamp).getSeconds() to confirm there was not a larger period than 1 second from the previous message for a product_id.

An alternative could be to count heart-beat messages per minute per product id.

I would love to get your thoughts/criticism on this as maybe I am overthinking something simple and doing something unnecessary.

I am testing on V1.15. if adding snippets of timer code, beat tracking etc can help please let me know I will be happy to do so :)

Add automatic re-subscribe to channels upon connection drop

@bennycode First off, thank you for a great library! It has gotten me a long way in my project.

As far as I can tell, if the WebSocket connection is dropped, the next time it is connected it is up to the code using the library to re-subscribe to the channels to which the dropped connection was subscribed. I've implemented the logic for this in my own code, but was wondering if the place for this should be in this library? I'd be willing to put together a PR at some point if you thought that would be a good fit.

So, essentially, when the code using the library calls WebSocketClient.subscribe(), the WebSocketClient would keep track of what channels have been requested to subscribe. If something like WebSocketClient.disconnect() was called, it would forget previous subscriptions. Otherwise, when the WebSocket comes back up, it would automatically re-subscribe to the channels that were subscribed before the WebSocket went down. No worries if you don't think that logic fits in the library.

Making requests with 2 different keys is causing a 403

I am working on an app that will let a user add multiple exchanges to track their assets in 1 location. I am having an issue when I am testing adding 2 API keys for Coinbase Pro and requesting the history with this library. I have tried making sure its only requesting 1 set of data at a time. I have also tried creating a new connection object per request. Everything works great with 1 connection but as soon as it tries to request a 2nd it throws a 403 axios exception.

I don't think this is a bug in your code. But I am wondering if there is a known way to get around this issue.

price property does not exist on place order response.

node_version: 14
typescript_version: 4.2.4
coinbase_pro_node_version: 3.0.4

I'm currently placing a new order like this:

const orderResponse = await client.rest.order.placeOrder({...});

orderResponse :

{
  id: '8f3214cf-0db3-4c25-81b5-f7a05f863104',
  product_id: 'BTC-USD',
  side: 'buy',
  stp: 'dc',
  funds: '199.00497512',
  specified_funds: '200',
  type: 'market',
  post_only: false,
  created_at: '2021-05-25T01:44:22.982286Z',
  fill_fees: '0',
  filled_size: '0',
  executed_value: '0',
  status: 'pending',
  settled: false
}

Based on the Coinbase docs and the type definitions in the library, there should be a price property on the results, but there isn't one.

getOrders() returns 401

I was using getOpenOrders() without problems. After change to getOrders() I get 401 error. No other change made. I don't pass any params to getOrders().

Side question: when the autogenerated API reference is updated? It still references getOpenOrders(). Thank you.

API not being called within express router

Not sure if this is the right place to get help with this, but figured I'd give it a shot. Trying to make a call to this library on an api request from express, but the client never seems to actually do the request, just kinda hangs.

var express = require("express");
var router = express.Router();
var { CoinbasePro } = require('coinbase-pro-node');

router.get("/", function (req, res, next) {
    let query = req.query

    var auth = {
        apiKey: query.api_key,
        apiSecret: query.secret_key,
        passphrase: query.passphrase,
    };
    
    var client = new CoinbasePro(auth);

    client.rest.account.listAccounts().then(accounts => {
        const message = `You can trade "${accounts.length}" different pairs.`;
        res.send(message)

    }).catch((error) => {
        res.send(error)
    })
});

module.exports = router;

any explanation why anything else works in this route except this library would be appreciated

Invalid Signature when getting all orders of a certain product

In my code I'm trying to get all of my orders for a certain crypto currency and when I do, it throws a 401 error with the message invalid signature.

For more information, this is my code:

The product id I used was LTC-USD but it doesn't work with any I've tried.

const orders = await client.rest.order.getOrders({
  status: ["all"],
  product_id: productId,
});

Surprisingly, it works if I omit the product_id parameter.

const orders = await client.rest.order.getOrders({
  status: ["all"],
});

That works and returns a paginated result with all my orders.

I don't think I'm doing anything wrong?

Is this an official repo?

I understand two node packages with official Coinbase support appear to now be deprecated. Was there a state reason why it was deprecated? Can you please describe the support that this repo here has if official or not?

Keep Alive Websocket Connection

Hi @bennyn I found your library very interesting and I am trying to use it. However, the documentation says that connections to websocket feed are rate-limited to 1 per 4 seconds per IP. This is not related to the real-time feed data as far as you are connected right? I just want to know how does your lib handle this issue? or I have to manually reconnect?

Full list of products not listed by `getProducts`

I'm having an issue that I can't seem to figure out. There are a very limited number products being returned. I don't see anything listed on coinbase explaining the short list.

Current list of products:

[
  {
    id: 'BAT-USDC',
    base_currency: 'BAT',
    quote_currency: 'USDC',
    base_min_size: '1',
    base_max_size: '300000',
    quote_increment: '0.000001',
    base_increment: '0.000001',
    display_name: 'BAT/USDC',
    min_market_funds: '1',
    max_market_funds: '100000',
    margin_enabled: false,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  },
  {
    id: 'BTC-USD',
    base_currency: 'BTC',
    quote_currency: 'USD',
    base_min_size: '0.001',
    base_max_size: '10000',
    quote_increment: '0.01',
    base_increment: '0.00000001',
    display_name: 'BTC/USD',
    min_market_funds: '10',
    max_market_funds: '1000000',
    margin_enabled: true,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  },
  {
    id: 'LINK-USDC',
    base_currency: 'LINK',
    quote_currency: 'USDC',
    base_min_size: '1',
    base_max_size: '800000',
    quote_increment: '0.000001',
    base_increment: '1',
    display_name: 'LINK/USDC',
    min_market_funds: '10',
    max_market_funds: '100000',
    margin_enabled: false,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  },
  {
    id: 'BTC-EUR',
    base_currency: 'BTC',
    quote_currency: 'EUR',
    base_min_size: '0.001',
    base_max_size: '10000',
    quote_increment: '0.01',
    base_increment: '0.00000001',
    display_name: 'BTC/EUR',
    min_market_funds: '10',
    max_market_funds: '600000',
    margin_enabled: false,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  },
  {
    id: 'BTC-GBP',
    base_currency: 'BTC',
    quote_currency: 'GBP',
    base_min_size: '0.001',
    base_max_size: '10000',
    quote_increment: '0.01',
    base_increment: '0.00000001',
    display_name: 'BTC/GBP',
    min_market_funds: '10',
    max_market_funds: '200000',
    margin_enabled: false,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  },
  {
    id: 'ETH-BTC',
    base_currency: 'ETH',
    quote_currency: 'BTC',
    base_min_size: '0.01',
    base_max_size: '1000000',
    quote_increment: '0.00001',
    base_increment: '0.00000001',
    display_name: 'ETH/BTC',
    min_market_funds: '0.001',
    max_market_funds: '80',
    margin_enabled: false,
    post_only: false,
    limit_only: false,
    cancel_only: false,
    trading_disabled: false,
    status: 'online',
    status_message: ''
  }
]

TODO: REST API

MIssing api functionality

Hi there,

Not an issue but more like a feature request.

Right now the functionality to delete individual orders is missing (I think)

If I can work out how to do pull request, I'll have a stab at implementing it.

Thanks for your work!

feat: Ping support for WebSocket

WebSocket times-out after 100 seconds from establishing connection and subscribing to channel. There is no ping implemented to keep the WebSocket alive. I have implemented a work-around by re-subscribing every minute, but would be great if the connection would stay open.

    account._client.ws.subscribe([
      { name: WebSocketChannelName.USER, product_ids: user._products }
    ]);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.