Skip to content

Commit 2e69015

Browse files
authored
Merge pull request #54 from skip-mev/jw/multi-recommend-assets
update recommendAssets to handle multiple requests
2 parents 74c0d83 + e1ce04a commit 2e69015

File tree

6 files changed

+217
-79
lines changed

6 files changed

+217
-79
lines changed

.changeset/soft-tips-give.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@skip-router/core": minor
3+
---
4+
5+
Update recommendAssets to handle multiple requests

packages/core/src/__test__/client.test.ts

+59-37
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
DenomWithChainID,
99
originAssetsResponseFromJSON,
1010
OriginAssetsResponseJSON,
11+
RecommendationEntry,
1112
} from "../types";
1213

1314
export const server = setupServer();
@@ -523,27 +524,34 @@ describe("client", () => {
523524
it("handles 200 OK", async () => {
524525
server.use(
525526
rest.post(
526-
"https://api.skip.money/v1/fungible/recommend_assets",
527+
"https://api.skip.money/v2/fungible/recommend_assets",
527528
(_, res, ctx) => {
528529
return res(
529530
ctx.status(200),
530531
ctx.json({
531-
recommendations: [
532+
recommendations: [],
533+
recommendation_entries: [
532534
{
533-
asset: {
534-
denom:
535-
"ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC",
536-
chain_id: "cosmoshub-4",
537-
origin_denom: "uosmo",
538-
origin_chain_id: "osmosis-1",
539-
trace: "transfer/channel-141",
540-
symbol: "OSMO",
541-
name: "OSMO",
542-
logo_uri:
543-
"https://raw.githubusercontent.com/cosmostation/chainlist/main/chain/osmosis/asset/osmo.png",
544-
decimals: 6,
545-
},
546-
reason: "MOST_LIQUID",
535+
recommendations: [
536+
{
537+
asset: {
538+
denom:
539+
"ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC",
540+
chain_id: "cosmoshub-4",
541+
origin_denom: "uosmo",
542+
origin_chain_id: "osmosis-1",
543+
trace: "transfer/channel-141",
544+
symbol: "OSMO",
545+
name: "OSMO",
546+
logo_uri:
547+
"https://raw.githubusercontent.com/cosmostation/chainlist/main/chain/osmosis/asset/osmo.png",
548+
decimals: 6,
549+
is_cw20: true,
550+
is_evm: true,
551+
},
552+
reason: "MOST_LIQUID",
553+
},
554+
],
547555
},
548556
],
549557
}),
@@ -556,30 +564,44 @@ describe("client", () => {
556564
apiURL: SKIP_API_URL,
557565
});
558566

559-
const response = await client.recommendAssets({
560-
sourceAssetChainID: "osmosis-1",
561-
sourceAssetDenom: "uosmo",
562-
destChainID: "cosmoshub-4",
563-
});
564-
565-
expect(response).toEqual([
567+
const response = await client.recommendAssets([
566568
{
567-
asset: {
568-
denom:
569-
"ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC",
570-
chainID: "cosmoshub-4",
571-
originDenom: "uosmo",
572-
originChainID: "osmosis-1",
573-
trace: "transfer/channel-141",
574-
symbol: "OSMO",
575-
name: "OSMO",
576-
logoURI:
577-
"https://raw.githubusercontent.com/cosmostation/chainlist/main/chain/osmosis/asset/osmo.png",
578-
decimals: 6,
579-
},
580-
reason: "MOST_LIQUID",
569+
sourceAssetChainID: "osmosis-1",
570+
sourceAssetDenom: "uosmo",
571+
destChainID: "cosmoshub-4",
581572
},
582573
]);
574+
575+
const expected: RecommendationEntry[] = [
576+
{
577+
recommendations: [
578+
{
579+
asset: {
580+
denom:
581+
"ibc/14F9BC3E44B8A9C1BE1FB08980FAB87034C9905EF17CF2F5008FC085218811CC",
582+
chainID: "cosmoshub-4",
583+
originDenom: "uosmo",
584+
originChainID: "osmosis-1",
585+
trace: "transfer/channel-141",
586+
symbol: "OSMO",
587+
name: "OSMO",
588+
logoURI:
589+
"https://raw.githubusercontent.com/cosmostation/chainlist/main/chain/osmosis/asset/osmo.png",
590+
decimals: 6,
591+
isCW20: true,
592+
isEVM: true,
593+
tokenContract: undefined,
594+
description: undefined,
595+
coingeckoID: undefined,
596+
recommendedSymbol: undefined,
597+
},
598+
reason: "MOST_LIQUID",
599+
},
600+
],
601+
},
602+
];
603+
604+
expect(response).toEqual(expected);
583605
});
584606
});
585607

packages/core/src/client.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ import {
5858
assetFromJSON,
5959
AssetJSON,
6060
AssetOrError,
61-
assetRecommendationFromJSON,
62-
AssetRecommendationJSON,
61+
AssetRecommendationRequest,
6362
AssetsBetweenChainsRequest,
6463
assetsBetweenChainsRequestToJSON,
6564
assetsBetweenChainsResponseFromJSON,
@@ -85,8 +84,9 @@ import {
8584
originAssetsRequestToJSON,
8685
originAssetsResponseFromJSON,
8786
OriginAssetsResponseJSON,
88-
RecommendAssetsRequest,
8987
recommendAssetsRequestToJSON,
88+
recommendAssetsResponseFromJSON,
89+
RecommendAssetsResponseJSON,
9090
RouteRequest,
9191
RouteRequestJSON,
9292
routeRequestToJSON,
@@ -850,20 +850,20 @@ export class SkipRouter {
850850
return routeResponseFromJSON(response);
851851
}
852852

853-
async recommendAssets(options: RecommendAssetsRequest) {
854-
const response = await this.requestClient.post<{
855-
recommendations: AssetRecommendationJSON[];
856-
}>(
857-
"/v1/fungible/recommend_assets",
858-
recommendAssetsRequestToJSON({
859-
...options,
860-
clientID: this.clientID,
861-
}),
862-
);
853+
async recommendAssets(
854+
request: AssetRecommendationRequest | AssetRecommendationRequest[],
855+
) {
856+
const options = recommendAssetsRequestToJSON({
857+
requests: Array.isArray(request) ? request : [request],
858+
clientID: this.clientID,
859+
});
863860

864-
return response.recommendations.map((recommendation) =>
865-
assetRecommendationFromJSON(recommendation),
861+
const response = await this.requestClient.post<RecommendAssetsResponseJSON>(
862+
"/v2/fungible/recommend_assets",
863+
options,
866864
);
865+
866+
return recommendAssetsResponseFromJSON(response).recommendationEntries;
867867
}
868868

869869
async ibcOriginAssets(assets: DenomWithChainID[]): Promise<AssetOrError[]> {

packages/core/src/types/__test__/converters.test.ts

+32-16
Original file line numberDiff line numberDiff line change
@@ -641,33 +641,49 @@ test("feeAssetToJSON", () => {
641641

642642
test("recommendAssetsRequestFromJSON", () => {
643643
const recommendAssetsRequestJSON: RecommendAssetsRequestJSON = {
644-
source_asset_denom: "uosmo",
645-
source_asset_chain_id: "osmosis-1",
646-
dest_chain_id: "neutron-1",
647-
reason: "MOST_LIQUID",
644+
requests: [
645+
{
646+
source_asset_denom: "uosmo",
647+
source_asset_chain_id: "osmosis-1",
648+
dest_chain_id: "neutron-1",
649+
reason: "MOST_LIQUID",
650+
},
651+
],
648652
};
649653

650654
expect(recommendAssetsRequestFromJSON(recommendAssetsRequestJSON)).toEqual({
651-
sourceAssetDenom: "uosmo",
652-
sourceAssetChainID: "osmosis-1",
653-
destChainID: "neutron-1",
654-
reason: "MOST_LIQUID",
655+
requests: [
656+
{
657+
sourceAssetDenom: "uosmo",
658+
sourceAssetChainID: "osmosis-1",
659+
destChainID: "neutron-1",
660+
reason: "MOST_LIQUID",
661+
},
662+
],
655663
});
656664
});
657665

658666
test("recommendAssetsRequestToJSON", () => {
659667
const recommendAssetsRequest: RecommendAssetsRequest = {
660-
sourceAssetDenom: "uosmo",
661-
sourceAssetChainID: "osmosis-1",
662-
destChainID: "neutron-1",
663-
reason: "MOST_LIQUID",
668+
requests: [
669+
{
670+
sourceAssetDenom: "uosmo",
671+
sourceAssetChainID: "osmosis-1",
672+
destChainID: "neutron-1",
673+
reason: "MOST_LIQUID",
674+
},
675+
],
664676
};
665677

666678
expect(recommendAssetsRequestToJSON(recommendAssetsRequest)).toEqual({
667-
source_asset_denom: "uosmo",
668-
source_asset_chain_id: "osmosis-1",
669-
dest_chain_id: "neutron-1",
670-
reason: "MOST_LIQUID",
679+
requests: [
680+
{
681+
source_asset_denom: "uosmo",
682+
source_asset_chain_id: "osmosis-1",
683+
dest_chain_id: "neutron-1",
684+
reason: "MOST_LIQUID",
685+
},
686+
],
671687
});
672688
});
673689

packages/core/src/types/converters.ts

+74-8
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ import {
8080
AssetBetweenChainsJSON,
8181
AssetRecommendation,
8282
AssetRecommendationJSON,
83+
AssetRecommendationRequest,
84+
AssetRecommendationRequestJSON,
8385
AssetsBetweenChainsRequest,
8486
AssetsBetweenChainsRequestJSON,
8587
AssetsBetweenChainsResponse,
@@ -96,6 +98,10 @@ import {
9698
OperationJSON,
9799
RecommendAssetsRequest,
98100
RecommendAssetsRequestJSON,
101+
RecommendAssetsResponse,
102+
RecommendAssetsResponseJSON,
103+
RecommendationEntry,
104+
RecommendationEntryJSON,
99105
RouteRequest,
100106
RouteRequestJSON,
101107
RouteResponse,
@@ -284,10 +290,9 @@ export function recommendAssetsRequestFromJSON(
284290
recommendAssetsRequestJSON: RecommendAssetsRequestJSON,
285291
): RecommendAssetsRequest {
286292
return {
287-
sourceAssetDenom: recommendAssetsRequestJSON.source_asset_denom,
288-
sourceAssetChainID: recommendAssetsRequestJSON.source_asset_chain_id,
289-
destChainID: recommendAssetsRequestJSON.dest_chain_id,
290-
reason: recommendAssetsRequestJSON.reason,
293+
requests: recommendAssetsRequestJSON.requests.map(
294+
assetRecommendationRequestFromJSON,
295+
),
291296
clientID: recommendAssetsRequestJSON.client_id,
292297
};
293298
}
@@ -296,14 +301,53 @@ export function recommendAssetsRequestToJSON(
296301
recommendAssetsRequest: RecommendAssetsRequest,
297302
): RecommendAssetsRequestJSON {
298303
return {
299-
source_asset_denom: recommendAssetsRequest.sourceAssetDenom,
300-
source_asset_chain_id: recommendAssetsRequest.sourceAssetChainID,
301-
dest_chain_id: recommendAssetsRequest.destChainID,
302-
reason: recommendAssetsRequest.reason,
304+
requests: recommendAssetsRequest.requests.map(
305+
assetRecommendationRequestToJSON,
306+
),
303307
client_id: recommendAssetsRequest.clientID,
304308
};
305309
}
306310

311+
export function recommendAssetsResponseFromJSON(
312+
value: RecommendAssetsResponseJSON,
313+
): RecommendAssetsResponse {
314+
return {
315+
recommendations: value.recommendations.map(assetRecommendationFromJSON),
316+
recommendationEntries: value.recommendation_entries.map(
317+
recommendationEntryFromJSON,
318+
),
319+
};
320+
}
321+
322+
export function recommendAssetsResponseToJSON(
323+
value: RecommendAssetsResponse,
324+
): RecommendAssetsResponseJSON {
325+
return {
326+
recommendations: value.recommendations.map(assetRecommendationToJSON),
327+
recommendation_entries: value.recommendationEntries.map(
328+
recommendationEntryToJSON,
329+
),
330+
};
331+
}
332+
333+
export function recommendationEntryFromJSON(
334+
value: RecommendationEntryJSON,
335+
): RecommendationEntry {
336+
return {
337+
recommendations: value.recommendations.map(assetRecommendationFromJSON),
338+
error: value.error,
339+
};
340+
}
341+
342+
export function recommendationEntryToJSON(
343+
value: RecommendationEntry,
344+
): RecommendationEntryJSON {
345+
return {
346+
recommendations: value.recommendations.map(assetRecommendationToJSON),
347+
error: value.error,
348+
};
349+
}
350+
307351
export function swapVenueFromJSON(swapVenueJSON: SwapVenueJSON): SwapVenue {
308352
return {
309353
name: swapVenueJSON.name,
@@ -1367,3 +1411,25 @@ export function assetsBetweenChainsResponseFromJSON(
13671411
),
13681412
};
13691413
}
1414+
1415+
export function assetRecommendationRequestFromJSON(
1416+
value: AssetRecommendationRequestJSON,
1417+
): AssetRecommendationRequest {
1418+
return {
1419+
sourceAssetDenom: value.source_asset_denom,
1420+
sourceAssetChainID: value.source_asset_chain_id,
1421+
destChainID: value.dest_chain_id,
1422+
reason: value.reason,
1423+
};
1424+
}
1425+
1426+
export function assetRecommendationRequestToJSON(
1427+
value: AssetRecommendationRequest,
1428+
): AssetRecommendationRequestJSON {
1429+
return {
1430+
source_asset_denom: value.sourceAssetDenom,
1431+
source_asset_chain_id: value.sourceAssetChainID,
1432+
dest_chain_id: value.destChainID,
1433+
reason: value.reason,
1434+
};
1435+
}

0 commit comments

Comments
 (0)