Skip to content

Commit

Permalink
fix(v1.0.7, #62): fix sign issue when trying pass through pagination …
Browse files Browse the repository at this point in the history
…URL with params for CB APP API
  • Loading branch information
tiagosiebler committed Feb 12, 2025
1 parent 78e2216 commit aa3c0fe
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 17 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "coinbase-api",
"version": "1.0.6",
"version": "1.0.7",
"description": "Node.js SDK for Coinbase's REST APIs and WebSockets, with TypeScript & strong end to end tests.",
"scripts": {
"clean": "rm -rf dist",
Expand Down
65 changes: 51 additions & 14 deletions src/CBAppClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AxiosRequestConfig } from 'axios';

import { BaseRestClient } from './lib/BaseRestClient.js';
import {
getParamsFromURL,
REST_CLIENT_TYPE_ENUM,
RestClientOptions,
RestClientType,
Expand Down Expand Up @@ -36,7 +37,7 @@ export class CBAppClient extends BaseRestClient {
headers: {
// Some endpoints return a warning if a version header isn't included: https://docs.cdp.coinbase.com/coinbase-app/docs/versioning
// Currently set to a date from the changelog: https://docs.cdp.coinbase.com/coinbase-app/docs/changelog
'CB-VERSION': '2024-09-13',
'CB-VERSION': '2025-FEB-3',
...requestOptions.headers,
},
});
Expand All @@ -61,14 +62,18 @@ export class CBAppClient extends BaseRestClient {
* This endpoint is paginated. In case you are calling it first time, leave paginationURL empty.
* If you are paginating, provide the paginationURL value from the previous response and you will receive the next page of accounts.
*/
getAccounts(params?: { paginationURL?: string }): Promise<{
getAccounts(params?: {
paginationURL?: string;
starting_after?: string;
}): Promise<{
data: CBAppAccount[];
pagination: CBAppPagination;
}> {
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, derivedParams.params);
}
return this.getPrivate('/v2/accounts');
return this.getPrivate('/v2/accounts', params);
}

/**
Expand Down Expand Up @@ -116,10 +121,15 @@ export class CBAppClient extends BaseRestClient {
pagination: CBAppPagination;
data: CBAppAddress[];
}> {
const { account_id, ...otherParams } = params;
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, {
...otherParams,
...derivedParams.params,
});
}
return this.getPrivate(`/v2/accounts/${params.account_id}/addresses`);
return this.getPrivate(`/v2/accounts/${account_id}/addresses`, otherParams);
}

/**
Expand Down Expand Up @@ -155,11 +165,17 @@ export class CBAppClient extends BaseRestClient {
pagination: CBAppPagination;
data: CBAppTransaction[];
}> {
const { account_id, addressId, ...otherParams } = params;
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, {
...otherParams,
...derivedParams.params,
});
}
return this.getPrivate(
`/v2/accounts/${params.account_id}/addresses/${params.addressId}/transactions`,
`/v2/accounts/${account_id}/addresses/${addressId}/transactions`,
otherParams,
);
}

Expand Down Expand Up @@ -214,10 +230,18 @@ export class CBAppClient extends BaseRestClient {
pagination: CBAppPagination;
data: CBAppTransaction[];
}> {
const { account_id, ...otherParams } = params;
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, {
...otherParams,
...derivedParams.params,
});
}
return this.getPrivate(`/v2/accounts/${params.account_id}/transactions`);
return this.getPrivate(
`/v2/accounts/${account_id}/transactions`,
otherParams,
);
}

/**
Expand Down Expand Up @@ -282,10 +306,15 @@ export class CBAppClient extends BaseRestClient {
pagination: CBAppPagination;
data: CBAppDepositWithdrawal[];
}> {
const { account_id, ...otherParams } = params;
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, {
...otherParams,
...derivedParams.params,
});
}
return this.getPrivate(`/v2/accounts/${params.account_id}/deposits`);
return this.getPrivate(`/v2/accounts/${account_id}/deposits`, otherParams);
}

/**
Expand Down Expand Up @@ -350,10 +379,18 @@ export class CBAppClient extends BaseRestClient {
pagination: CBAppPagination;
data: CBAppDepositWithdrawal[];
}> {
const { account_id, ...otherParams } = params;
if (params?.paginationURL) {
return this.getPrivate(params.paginationURL);
const derivedParams = getParamsFromURL(params.paginationURL);
return this.getPrivate(derivedParams.endpoint, {
...otherParams,
...derivedParams.params,
});
}
return this.getPrivate(`/v2/accounts/${params.account_id}/withdrawals`);
return this.getPrivate(
`/v2/accounts/${account_id}/withdrawals`,
otherParams,
);
}

/**
Expand Down
31 changes: 31 additions & 0 deletions src/lib/requestUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,3 +199,34 @@ export function getRestBaseUrl(

return exchangeBaseUrls.livenet;
}

/**
* Extract and separate request parameters in query string from the rest of the endpoint, to prevent sign issues.
*
* @param url endpoint containing params in query string; "/v2/acconuts/123123213?someParam=xyz"
* @returns
*/
export function getParamsFromURL(url: string): {
endpoint: string;
params: any;
} {
const [endpoint, paramsStr] = url.split('?');
if (!paramsStr) {
return {
endpoint: url,
params: {},
};
}

const result = {
endpoint: endpoint,
params: {} as Record<string, string>,
};

(paramsStr || '').split('&').forEach((param) => {
const [key, value] = param.split('=');
result.params[key] = value;
});

return result;
}

0 comments on commit aa3c0fe

Please sign in to comment.