Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/chomp-api-service/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Bump `@tanstack/query-core` from `^5.89.0` to `^5.103.2` ([#10511](https://github.com/MetaMask/core/pull/10511))

### Fixed

- Ignore unrecognised intent types returned by the CHOMP API instead of failing to parse the whole response ([#10609](https://github.com/MetaMask/core/pull/10609))
- `getIntentsByAddress` now omits intents whose `metadata.type` is not a known `ChompIntentType`.
- `getServiceDetails` now omits unknown values from each protocol's `intentTypes`.

## [6.0.0]

### Added
Expand Down
63 changes: 63 additions & 0 deletions packages/chomp-api-service/src/chomp-api-service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,38 @@ describe('ChompApiService', () => {
});
}

it('omits intents with an unknown intent type', async () => {
const unknownIntent = {
...intentsResponse[0],
delegationHash: '0x456',
metadata: { ...intentsResponse[0].metadata, type: 'some-future-type' },
};
nock(BASE_URL)
.get('/v1/intent/account/0xabc')
.reply(200, [unknownIntent, ...intentsResponse]);
const { service } = createService();

expect(await service.getIntentsByAddress('0xabc')).toStrictEqual(
intentsResponse,
);
});

it('throws when an intent type is not a string', async () => {
nock(BASE_URL)
.get('/v1/intent/account/0xabc')
.reply(200, [
{
...intentsResponse[0],
metadata: { ...intentsResponse[0].metadata, type: 123 },
},
]);
const { service } = createService();

await expect(service.getIntentsByAddress('0xabc')).rejects.toThrow(
'At path: 0.metadata.type -- Expected a string, but received: 123',
);
});

it('throws on malformed response', async () => {
nock(BASE_URL)
.get('/v1/intent/account/0xabc')
Expand Down Expand Up @@ -769,6 +801,37 @@ describe('ChompApiService', () => {
);
});

it('omits unknown intent types from a protocol', async () => {
const response = {
...serviceDetailsResponse,
chains: {
'0xa4b1': {
...serviceDetailsResponse.chains['0xa4b1'],
protocol: {
vedaProtocol: {
...serviceDetailsResponse.chains['0xa4b1'].protocol
.vedaProtocol,
intentTypes: [
'cash-deposit',
'some-future-type',
'cash-withdrawal',
],
},
},
},
},
};
nock(BASE_URL)
.get('/v1/chomp')
.query({ chainId: '0xa4b1' })
.reply(200, response);
const { service } = createService();

expect(await service.getServiceDetails(['0xa4b1'])).toStrictEqual(
serviceDetailsResponse,
);
});

it('supports multiple chain IDs as a comma-separated query param', async () => {
nock(BASE_URL)
.get('/v1/chomp')
Expand Down
20 changes: 16 additions & 4 deletions packages/chomp-api-service/src/chomp-api-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ const CHOMP_INTENT_TYPES: ChompIntentType[] = [
'cash-subscription',
];

function isChompIntentType(value: string): value is ChompIntentType {
return (CHOMP_INTENT_TYPES as string[]).includes(value);
}

// === GENERAL ===

/**
Expand Down Expand Up @@ -225,7 +229,7 @@ const IntentEntryArrayStruct = array(
allowance: StrictHexStruct,
tokenAddress: StrictHexStruct,
tokenSymbol: string(),
type: enums(CHOMP_INTENT_TYPES),
type: string(),
}),
}),
);
Expand All @@ -242,7 +246,11 @@ const ServiceDetailsProtocolStruct = type({
}),
),
adapterAddress: StrictHexStruct,
intentTypes: array(enums(CHOMP_INTENT_TYPES)),
intentTypes: coerce(
array(enums(CHOMP_INTENT_TYPES)),
array(string()),
(intentTypes) => intentTypes.filter(isChompIntentType),
),
});

const ServiceDetailsResponseStruct = type({
Expand Down Expand Up @@ -612,7 +620,8 @@ export class ChompApiService extends BaseDataService<
* is always fetched fresh (`staleTime: 0`).
*
* @param address - The address to look up intents for.
* @returns The array of intents for the address.
* @returns The array of intents for the address, omitting any with an
* intent type this service does not recognise.
*/
async getIntentsByAddress(address: Hex): Promise<IntentEntry[]> {
const jsonResponse = await this.fetchQuery({
Expand All @@ -636,7 +645,10 @@ export class ChompApiService extends BaseDataService<
},
});

return create(jsonResponse, IntentEntryArrayStruct);
return create(jsonResponse, IntentEntryArrayStruct).filter(
(intent): intent is IntentEntry =>
isChompIntentType(intent.metadata.type),
);
}

/**
Expand Down
Loading