Skip to content

Commit

Permalink
[TokenDetectionController] pass header to accounts API (#4877)
Browse files Browse the repository at this point in the history
## Explanation

Following the documentation in
https://docs.cx.metamask.io/docs/further-info/internalClientId, pass a
`x-metamask-clientproduct` header when calling the account api.

## References

<!--
Are there any issues that this pull request is tied to?
Are there other links that reviewers should consult to understand these
changes better?
Are there client or consumer pull requests to adopt any breaking
changes?

For example:

* Fixes #12345
* Related to #67890
-->

## Changelog

<!--
If you're making any consumer-facing changes, list those changes here as
if you were updating a changelog, using the template below as a guide.

(CATEGORY is one of BREAKING, ADDED, CHANGED, DEPRECATED, REMOVED, or
FIXED. For security-related issues, follow the Security Advisory
process.)

Please take care to name the exact pieces of the API you've added or
changed (e.g. types, interfaces, functions, or methods).

If there are any breaking changes, make sure to offer a solution for
consumers to follow once they upgrade to the changes.

Finally, if you're only making changes to development scripts or tests,
you may replace the template below with "None".
-->

### `@metamask/assets-controllers`

- **BREAKING**: A `platform` argument must now be passed to the
`TokenDetectionController` constructor.
- **CHANGED**: The `TokenDetectionController` now passes a
`x-metamask-clientproduct` header when calling the account API.


## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
- [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've highlighted breaking changes using the "BREAKING" category
above as appropriate
- [ ] I've prepared draft pull requests for clients and consumer
packages to resolve any breaking changes
  • Loading branch information
bergeron authored Oct 31, 2024
1 parent eb2ae98 commit d16f2f8
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2931,6 +2931,7 @@ async function withController<ReturnValue>(
trackMetaMetricsEvent: jest.fn(),
messenger: buildTokenDetectionControllerMessenger(controllerMessenger),
useAccountsAPI: false,
platform: 'extension',
...options,
});
try {
Expand Down
16 changes: 13 additions & 3 deletions packages/assets-controllers/src/TokenDetectionController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
#accountsAPI = {
isAccountsAPIEnabled: true,
supportedNetworksCache: null as number[] | null,
platform: '' as 'extension' | 'mobile',

async getSupportedNetworks() {
/* istanbul ignore next */
if (!this.isAccountsAPIEnabled) {
Expand Down Expand Up @@ -232,9 +234,13 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
);
}

const result = await fetchMultiChainBalances(address, {
networks: [chainIdNumber],
});
const result = await fetchMultiChainBalances(
address,
{
networks: [chainIdNumber],
},
this.platform,
);

return result.balances;
},
Expand All @@ -250,6 +256,7 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
* @param options.getBalancesInSingleCall - Gets the balances of a list of tokens for the given address.
* @param options.trackMetaMetricsEvent - Sets options for MetaMetrics event tracking.
* @param options.useAccountsAPI - Feature Switch for using the accounts API when detecting tokens (default: true)
* @param options.platform - Indicates whether the platform is extension or mobile
*/
constructor({
interval = DEFAULT_INTERVAL,
Expand All @@ -258,6 +265,7 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
trackMetaMetricsEvent,
messenger,
useAccountsAPI = true,
platform,
}: {
interval?: number;
disabled?: boolean;
Expand All @@ -277,6 +285,7 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
}) => void;
messenger: TokenDetectionControllerMessenger;
useAccountsAPI?: boolean;
platform: 'extension' | 'mobile';
}) {
super({
name: controllerName,
Expand Down Expand Up @@ -315,6 +324,7 @@ export class TokenDetectionController extends StaticIntervalPollingController<To
this.#isUnlocked = isUnlocked;

this.#accountsAPI.isAccountsAPIEnabled = useAccountsAPI;
this.#accountsAPI.platform = platform;

this.#registerEventListeners();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('fetchMultiChainBalances()', () => {
it('should successfully return balances response', async () => {
const mockAPI = createMockAPI().reply(200, MOCK_GET_BALANCES_RESPONSE);

const result = await fetchMultiChainBalances(MOCK_ADDRESS);
const result = await fetchMultiChainBalances(MOCK_ADDRESS, {}, 'extension');
expect(result).toBeDefined();
expect(result).toStrictEqual(MOCK_GET_BALANCES_RESPONSE);
expect(mockAPI.isDone()).toBe(true);
Expand All @@ -59,9 +59,13 @@ describe('fetchMultiChainBalances()', () => {
})
.reply(200, MOCK_GET_BALANCES_RESPONSE);

const result = await fetchMultiChainBalances(MOCK_ADDRESS, {
networks: [1, 10],
});
const result = await fetchMultiChainBalances(
MOCK_ADDRESS,
{
networks: [1, 10],
},
'extension',
);
expect(result).toBeDefined();
expect(result).toStrictEqual(MOCK_GET_BALANCES_RESPONSE);
expect(mockAPI.isDone()).toBe(true);
Expand All @@ -79,7 +83,8 @@ describe('fetchMultiChainBalances()', () => {
const mockAPI = createMockAPI().reply(httpCode);

await expect(
async () => await fetchMultiChainBalances(MOCK_ADDRESS),
async () =>
await fetchMultiChainBalances(MOCK_ADDRESS, {}, 'extension'),
).rejects.toThrow(expect.any(Error));
expect(mockAPI.isDone()).toBe(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,21 @@ export async function fetchSupportedNetworks(): Promise<number[]> {
* @param address - address to fetch balances from
* @param options - params to pass down for a more refined search
* @param options.networks - the networks (in decimal) that you want to filter by
* @param platform - indicates whether the platform is extension or mobile
* @returns a Balances Response
*/
export async function fetchMultiChainBalances(
address: string,
options?: { networks?: number[] },
options: { networks?: number[] },
platform: 'extension' | 'mobile',
) {
const url = getBalancesUrl(address, {
networks: options?.networks?.join(),
});
const response: GetBalancesResponse = await handleFetch(url);
const response: GetBalancesResponse = await handleFetch(url, {
headers: {
'x-metamask-clientproduct': `metamask-${platform}`,
},
});
return response;
}

0 comments on commit d16f2f8

Please sign in to comment.