Is it just me or does this Advanced Trade API feel way worse than Coinbase Pro? It just feels unfinished and badly implemented.
For example, I’m looking for the API endpoint to tell me the current maker/taker fees for a user and I can’t seem to find it in the documentation. Coinbase Pro and every other exchange has it.
It seems ridiculous to be forcing people to migrate from Coinbase Pro to Advanced Trade when it’s a huge step down. At very least they should have matched the API functionality!
Does anyone know if there is an API endpoint to retrieve the user’s current fee rates?
It’s not what I’m looking for. This is just a list of fees per transaction. I am looking for the current maker/taker fee tier like you get with /fees with Coinbase Pro.
The maker and taker fee rates will be in the fee_tier property. They are shown as a percentage on the site, so you have to shift the decimal 2 places to the right if you want it to match. For example, for me you can see a fee tier of 0.004, but on the Coinbase website shows it as 0.4%. It’s not a fee for any particular transaction.
The language they use is maybe a bit confusing. It’s not a summary of each transaction you’ve made. It’s more like a summary of your entire account, in relation to your transaction activity. So it will tell you how much volume in total you’ve traded, how many total fees you’ve paid, etc.
As far as the start/end dates go, I never use them either. When I call the endpoint it gives me a summary of the last 30 days. My assumption would be you could put in a start and end date, and get a summary of a particular timeframe. Haven’t tested that though, so I’m not 100% sure. Wish the documentation were a little more clear on it.
Are these optional and I’m not passing any of them?
start_date date-time
end_date date-time
user_native_currency string String of the users native currency, default is USD
product_type string
Type of product SPOT
I’m getting a error 403 and I’m just trying to figure out why. I checked they I have the wallet:transactions:read permission.
I got a 401 is I do call this: /api/v3/brokerage/transaction_summary?user_native_currency=GBP
I don’t think it was in the docs at the time, but I did need to pass user_native_currency: 'USD' as a param, as it was not defaulting to anything and was returning an error. Not sure if that’s still required, but it hasn’t hurt anything so I still have it in my code and it’s still working.
Also worth noting that you pass the param in the body of the request, not the url.
When you say you are passing it in the body of your request do you have an example? It seems strange for them to do this and it’s opposite of what the documentation example shows.
I tried this but it doesn’t work…
body = (request.body or b"").decode()
message = f"{timestamp}{request.method}{request.path_url}{body}"
@jmicko, I’ve updated my requests.get to look like this:
resp = requests.get(self._api_url + uri, params=payload, auth=self)
It still results in a message before signing that looks like this:
‘1679732266GET/api/v3/brokerage/transaction_summary?user_native_currency=GBP’
For a GET the params are passed in the URL. I’m not quite sure what you mean about passing the param in the body of the request. That would normally be what a POST looks like. This isn’t a POST right?
Do you have an example of what you have done that works?
You’re right, my bad. I read my own code wrong lol. The params do go in the url.
One thing I’m noticing now is that your message has the params in it.
You shouldn’t have them in there when you sign the message. So in that example, you should be signing a message that looks like this: 1679732266GET/api/v3/brokerage/transaction_summary
I have a javascript example, idk if that helps. It’s taken from a much larger class object so I’ll just paste the relevant parts and you can maybe work it out.
class Coinbase {
constructor(key, secret) {
if (!secret?.length || !key?.length) {
throw new Error('Coinbase is missing mandatory key and/or secret!');
}
this.key = key;
this.secret = secret;
this.WS_API_URL = 'wss://advanced-trade-ws.coinbase.com';
this.ws = null;
this.products = null;
}
async getTransactionSummary(params) {
return new Promise(async (resolve, reject) => {
try {
// data should just be blank
const data = null;
const API = {
url: `https://coinbase.com/api/v3/brokerage/transaction_summary`,
path: "/api/v3/brokerage/transaction_summary",
method: 'GET',
}
// sign the request
const options = this.signRequest(data, API);
// add params, if any
if (params) { this.addParams(options, params) };
// make the call
let response = await axios.request(options);
resolve(response.data);
} catch (err) {
reject(err);
}
})
}
// used for signing all REST requests
signRequest(data, API) {
// convert the data to JSON, if any
const body = data ? JSON.stringify(data) : '';
// get the timestamp
const timestamp = Math.floor(Date.now() / 1000).toString();
// build the message string
const message = timestamp + API.method + API.path + body;
// sign the message
const sig = CryptoJS.HmacSHA256(message, this.secret).toString();
// build the options object to return to the requester function
const options = {
method: API.method,
timeout: 10000,
url: API.url,
headers: {
Accept: 'application/json',
'cb-access-key': this.key,
'cb-access-sign': sig,
'cb-access-timestamp': timestamp
},
data: data
};
return options;
}
// add params to url after signing but before calling
addParams(options, params) {
// this function is only called if there are params, so add a ? to the url string
options.url = options.url + `?`;
// Iterate over each object key/value pair, adding them to the url
Object.keys(params).forEach(key => {
// add new param
options.url += `${key}=${params[key]}&`;
});
// cut off the last & symbol
options.url = options.url.slice(0, -1)
}
}
@michael.whittle Your github repo is very helpful! It seems that the fee rate is applied to the quote based on the example they have in the doc for ‘commission’ field in Fills endpoint, can you shed some light? (I am heading to your github to check there as well)
Thank you