question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Correct way to construct a request?

See original GitHub issue
  • OS: Manjaro Linux
  • Programming Language version: Python 3.10.2
  • CCXT version: 1.76.75

Hi there, I’m trying to extend the kucoin exchange, and I’ve made my own sub-class which succesfully inherits everything from ccxt.kucoin

from ccxt.kucoin import kucoin


class kucoin_extended(kucoin):
    """
    - KuCoin doesn't have an API method for fetchBorrowRate.
    If it's possible to infer that from fetchMaxBorrowAmount (or any other way),
    then I will be able to implement this in a way that conforms to CCXT's standards.

    - fetchMaxBorrowAmount is a non-standard CCXT method that I made up. None of the other
    exchanges seem to have it, so any strategies which need it won't work on other exchanges
    (i.e. the N2SuperTrend strategy as it was written in the requirements).
        * It would also be possible to make another version of the strategy which doesn't
        rely on fetchMaxBorrowAmount, but I want to fulfil your requirements exactly as they
        were written, so I'm implementing it.
    """

    def describe(self):
        return self.deep_extend(super(kucoin_extended, self).describe(), {
            'id': 'kucoin_extended',
            'alias': True,
            'version': 'v0.0.1',
            'has': {
                # 'fetchBorrowRate': True,  # If/when this is implemented, I'll un-comment this line
                'fetchMaxBorrowAmount': True
            }
        })

    def fetch_max_borrow_amount(self, currency):
        """Fetches the maximum available borrow amount for a given currency"""
        self.load_markets()
        request = {
            # TODO: construct a request here
        }

        response = self.privateMarginAccount()
        pass

    def fetch_borrow_rate(self, currency):
        """Not working yet"""
        raise NotImplementedError("This isn't natively supported by KuCoin's API.\n"
                                  "It might be possible to implement this somehow")

Actually I just wanted to ask advice, and it’s not about a particular re-producable error.

I have looked at kucoin and other exchange’s source code and I see different ways that requests are made:

response = self.privateXYZ(self.extend(request, params))
response = getattr(self, method)(self.extend(request, params))
response = self.publicXYZ(params)
...
response = self.privateGetAccounts(params)
...
response = self.publicGetCurrencies(params)

At first I thought maybe only having the params was only for public API methods, but I can see it for private ones too.

Can someone explain the difference between these to me? As in, whether to supply only params as a param, or whether to use self.extend, or whether to use getattr(self, method)(self.extend ...) I’m still learning programming and I couldn’t really figure out what the appropriate way to form a request is. What’s the criteria for deciding which way to use?

Thanks so much! I really love this project, and once I learn more about it I want to contribute to it.

I looked in the Exchange class at the definition of extend and I’m not really sure why this would need to be done?

    @staticmethod
    def extend(*args):
        if args is not None:
            result = None
            if type(args[0]) is collections.OrderedDict:
                result = collections.OrderedDict()
            else:
                result = {}
            for arg in args:
                result.update(arg)
            return result
        return {}

Sorry if this is a dumb question.

Issue Analytics

  • State:closed
  • Created a year ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
kroitorcommented, Mar 23, 2022

Hi! First and foremost, the exchanges will have two kinds of the API:

  • the implicit endpoints API (a list of all the endpoints for the exchange, and you can call any endpoint in an exchange-specific way)
  • the unified API (a set of methods that call those implicit endpoints seamlessly for any exchange, if the exchange has this or that endpoint)

See these notes:

All implicit endpoints have just one params argument. The extend call is used to allow the user to override some or all the request params. Which is why all unified methods will have an extra params argument, that is fed to the implicit API as well.

In your case, the goal is to make a new unified method based on the implicit methods:

from ccxt.kucoin import kucoin


class kucoin_extended(kucoin):
    """
    - KuCoin doesn't have an API method for fetchBorrowRate.
    If it's possible to infer that from fetchMaxBorrowAmount (or any other way),
    then I will be able to implement this in a way that conforms to CCXT's standards.

    - fetchMaxBorrowAmount is a non-standard CCXT method that I made up. None of the other
    exchanges seem to have it, so any strategies which need it won't work on other exchanges
    (i.e. the N2SuperTrend strategy as it was written in the requirements).
        * It would also be possible to make another version of the strategy which doesn't
        rely on fetchMaxBorrowAmount, but I want to fulfil your requirements exactly as they
        were written, so I'm implementing it.
    """

    def describe(self):
        return self.deep_extend(super(kucoin_extended, self).describe(), {
            'id': 'kucoin_extended',
            'alias': True,
            'version': 'v0.0.1',
            'has': {
                # 'fetchBorrowRate': True,  # If/when this is implemented, I'll un-comment this line
                'fetchMaxBorrowAmount': True
            }
        })

    def fetch_max_borrow_amount(self, currency, params = {}):  # -------------------+
        """Fetches the maximum available borrow amount for a given currency"""    # ↓
        self.load_markets()                                                       # ↓
        request = {                                                               # ↓
            # TODO: construct a request here                                      # ↓
        }                                                                         # ↓
        response = self.privateMarginAccount(this.extend (request, params))  # ← ---+
        pass

    def fetch_borrow_rate(self, currency):
        """Not working yet"""
        raise NotImplementedError("This isn't natively supported by KuCoin's API.\n"
                                  "It might be possible to implement this somehow")

So a unified method takes the default request object, extends it with params-overrides (which are empty by default, but could be used to override a param by the user) and then the unified method passes the resulting extended params to the implicit method.

Hope that answers your question, let us know if not. Feel free to reopen it or just ask further questions if any.

2reactions
pcriadoperezcommented, Mar 23, 2022

Hi @spliffli ,

We use self.extend to merge a request and params that may be passed in. This is regardless if the method called is private or public, that’s why you see it can be used in both cases. (As your example 1 and 2)

In the cases there is no request object there is no need to use self.extend (As your example 3.)

For the question around when we use getattr(self, method) it is another way to call the same function.

self.privateXYZ(self.extend(request, params)) would be the same as getattr(self, method)(self.extend(request, params)) where method = privateXYZ

I hope this helps! And feel fee to ask any more questions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

HTTP - Requests - Tutorialspoint
The Request-Line begins with a method token, followed by the Request-URI and the protocol version, and ending with CRLF. The elements are separated...
Read more >
Here are the most popular ways to make an HTTP request in ...
In this article, we are going to look at a few popular ways to make HTTP requests in JavaScript. Ajax. Ajax is the...
Read more >
Request() - Web APIs - MDN Web Docs
The Request() constructor creates a new Request object.
Read more >
What is the best way to make an HTTP request from a Java ...
Builder() .url(url) .post(body) .build(); Response response = client.newCall(request).execute(); return response.body().string(); }.
Read more >
Requests - Grammar - Cambridge Dictionary
Asking for something ; Can I have the salt? · Of course, here you are. ; Could I ask you the time, please?...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found