feat(swapHelpers): add batchSize option to FetchRoutesImpl factories

This commit is contained in:
c4605
2025-03-18 15:38:33 +01:00
parent 1e6e1bbb9e
commit ef6522f7cb
6 changed files with 60 additions and 56 deletions

View File

@@ -16,7 +16,7 @@
"@stacks/stacks-blockchain-api-types": "^7.14.1",
"@stacks/transactions": "^7.0.5",
"@xlink-network/xlink-sdk": "file:../..",
"alex-sdk": "github:alexgo-io/alex-sdk#feat/detailed-swap-route-info",
"alex-sdk": "^3.2.0",
"c32check": "^2.0.0",
"lodash-es": "^4.17.21",
"react": "^19.0.0",

View File

@@ -27,8 +27,8 @@ importers:
specifier: file:../..
version: file:../..(@stacks/common@7.0.2)(typescript@5.8.2)
alex-sdk:
specifier: github:alexgo-io/alex-sdk#feat/detailed-swap-route-info
version: https://codeload.github.com/alexgo-io/alex-sdk/tar.gz/15171aec2fec824ce3593982ba254748588c1303(@stacks/common@7.0.2)(@stacks/network@7.0.2)(@stacks/transactions@7.0.5)
specifier: ^3.2.0
version: 3.2.0(@stacks/common@7.0.2)(@stacks/network@7.0.2)(@stacks/transactions@7.0.5)
c32check:
specifier: ^2.0.0
version: 2.0.0
@@ -550,9 +550,8 @@ packages:
zod:
optional: true
alex-sdk@https://codeload.github.com/alexgo-io/alex-sdk/tar.gz/15171aec2fec824ce3593982ba254748588c1303:
resolution: {tarball: https://codeload.github.com/alexgo-io/alex-sdk/tar.gz/15171aec2fec824ce3593982ba254748588c1303}
version: 3.0.4
alex-sdk@3.2.0:
resolution: {integrity: sha512-5Y83pTK3T7wN/SzgFQdjddzYutUuarTsKV6Wt7l4j081RECMYteeiga320iR17MY4R7Jekkw+Rsb0KtvuGnO4Q==}
engines: {node: '>=10'}
peerDependencies:
'@stacks/network': ^7.0.2
@@ -1578,7 +1577,7 @@ snapshots:
optionalDependencies:
typescript: 5.8.2
alex-sdk@https://codeload.github.com/alexgo-io/alex-sdk/tar.gz/15171aec2fec824ce3593982ba254748588c1303(@stacks/common@7.0.2)(@stacks/network@7.0.2)(@stacks/transactions@7.0.5):
alex-sdk@3.2.0(@stacks/common@7.0.2)(@stacks/network@7.0.2)(@stacks/transactions@7.0.5):
dependencies:
'@stacks/network': 7.0.2
'@stacks/transactions': 7.0.5

View File

@@ -7,23 +7,18 @@ import {
XLinkSDK,
} from "@xlink-network/xlink-sdk"
import { AlexSDK } from "alex-sdk"
import { FC, Fragment, useEffect, useState } from "react"
import { FC, Fragment, useState } from "react"
import { useQuery } from "react-query"
import { useDebouncedValue } from "../hooks/useDebouncedValue"
import { formatXLinkSDKChainName } from "../utils/formatXLinkSDKChainName"
import { getAvailableRoutes } from "../utils/getAvailableRoutes"
import { getSwapRoutesViaALEX } from "../utils/getSwapRoutesViaALEX"
import { getSwapRoutesViaEVMDEX } from "../utils/getSwapRoutesViaEVMDEX"
import { formatXLinkSDKChainName } from "../utils/formatXLinkSDKChainName"
import { useDebouncedValue } from "../hooks/useDebouncedValue"
const STORAGE_KEY = "xlink_matcha_api_key"
export const SwapRouteSelector: FC<{
alexSDK: AlexSDK
xlinkSDK: XLinkSDK
}> = ({ alexSDK, xlinkSDK }) => {
const [matchaAPIKey, setMatchaAPIKey] = useState(() => {
return localStorage.getItem(STORAGE_KEY) || ""
})
const [swapAmount, setSwapAmount] = useState("")
const [selectedRoute, setSelectedRoute] = useState<null | KnownRoute>(null)
const [selectedSwapRoute, setSelectedSwapRoute] =
@@ -31,11 +26,6 @@ export const SwapRouteSelector: FC<{
const debouncedSwapAmount = useDebouncedValue(swapAmount, 500)
const debouncedRoute = useDebouncedValue(selectedRoute, 500)
const debouncedAPIKey = useDebouncedValue(matchaAPIKey, 500)
useEffect(() => {
localStorage.setItem(STORAGE_KEY, matchaAPIKey)
}, [matchaAPIKey])
const availableRoutes = useQuery({
queryKey: ["availableRoutes"],
@@ -72,7 +62,7 @@ export const SwapRouteSelector: FC<{
})
const evmDexRoutes = useQuery({
enabled: !!debouncedRoute && !!debouncedSwapAmount && !!debouncedAPIKey,
enabled: !!debouncedRoute && !!debouncedSwapAmount,
queryKey: [
"evmDexRoutes",
JSON.stringify(debouncedRoute),
@@ -82,9 +72,6 @@ export const SwapRouteSelector: FC<{
if (debouncedRoute == null) {
throw new Error("No route selected")
}
if (!debouncedAPIKey) {
throw new Error("No matcha API key")
}
if (!isNumber(debouncedSwapAmount)) {
throw new Error("No swap amount")
}
@@ -92,7 +79,6 @@ export const SwapRouteSelector: FC<{
return getSwapRoutesViaEVMDEX(
{
xlinkSDK: xlinkSDK,
matchaAPIKey: debouncedAPIKey,
},
{
...debouncedRoute,
@@ -163,18 +149,6 @@ export const SwapRouteSelector: FC<{
</div>
)}
<div className="section">
<h2>Basic Information</h2>
<div className="input-group">
<input
type="text"
placeholder="Enter 0x API Key"
value={matchaAPIKey}
onChange={e => setMatchaAPIKey(e.target.value)}
/>
</div>
</div>
<div className="section">
<h2>Swap Settings</h2>
<div className="swap-group">

View File

@@ -7,15 +7,14 @@ import {
XLinkSDK,
} from "@xlink-network/xlink-sdk"
import {
fetchIceScreamSwapPossibleRoutesFactory,
getDexAggregatorRoutes,
getPossibleEVMDexAggregatorSwapParameters,
fetchMatchaPossibleRoutesFactory,
} from "@xlink-network/xlink-sdk/swapHelpers"
export async function getSwapRoutesViaEVMDEX(
context: {
xlinkSDK: XLinkSDK
matchaAPIKey: string
},
swapRequest: KnownRoute & {
amount: SDKNumber
@@ -38,10 +37,7 @@ export async function getSwapRoutesViaEVMDEX(
}
const routes = await getDexAggregatorRoutes(xlinkSDK, {
routeFetcher: fetchMatchaPossibleRoutesFactory({
baseUrl: "/api/matcha",
apiKey: context.matchaAPIKey,
}),
routeFetcher: fetchIceScreamSwapPossibleRoutesFactory({}),
routes: possibleSwapParameters.map(p => ({
evmChain: p.evmChain,
fromToken: p.fromToken,

View File

@@ -1,4 +1,5 @@
import { toSDKNumberOrUndefined } from "../../../xlinkSdkUtils/types"
import { arraySplit } from "../../arrayHelpers"
import { BigNumber } from "../../BigNumber"
import { XLinkSDKErrorBase } from "../../errors"
import { FetchRoutesImpl, QueryableRoute } from "./helpers"
@@ -10,6 +11,12 @@ export class FetchIceScreamSwapPossibleRoutesFailedError extends XLinkSDKErrorBa
}
export const fetchIceScreamSwapPossibleRoutesFactory = (options: {
/**
* The maximum number of routes to fetch in same time
*
* @default 1
*/
batchSize?: number
baseUrl?: string
debug?: boolean
}): FetchRoutesImpl => {
@@ -20,17 +27,26 @@ export const fetchIceScreamSwapPossibleRoutesFactory = (options: {
const baseUrl = options.baseUrl ?? "https://aggregator.icecreamswap.com"
const batchSize = options.batchSize ?? 1
return async info => {
const res: Awaited<ReturnType<FetchRoutesImpl>> = []
for (const route of info.possibleRoutes) {
const batches = arraySplit(
(_, idx) => Math.floor(idx / batchSize),
info.possibleRoutes,
)
const res: Awaited<ReturnType<FetchRoutesImpl>>[] = []
for (const batch of batches) {
res.push(
...(await fetchIceScreamSwapPossibleRouteImpl(
{ debugLog, baseUrl },
route,
...(await Promise.all(
batch.map(route =>
fetchIceScreamSwapPossibleRouteImpl({ debugLog, baseUrl }, route),
),
)),
)
}
return res
return res.flat()
}
}

View File

@@ -1,16 +1,23 @@
import { toSDKNumberOrUndefined } from "../../../xlinkSdkUtils/types"
import { arraySplit } from "../../arrayHelpers"
import { BigNumber } from "../../BigNumber"
import { XLinkSDKErrorBase } from "../../errors"
import { FetchRoutesImpl, QueryableRoute } from "./helpers"
export class FetchMatchaPossibleRoutesFailedError extends XLinkSDKErrorBase {
constructor(message: null | string, options: ErrorConstructorOptions) {
super(message ?? "Request Matcha.xyz api failed", options)
super(message ?? "Request 0x.org api failed", options)
}
}
export const fetchMatchaPossibleRoutesFactory = (options: {
apiKey: string
/**
* The maximum number of routes to fetch in same time
*
* @default 10 (0x.org api limit, see https://0x.org/docs/developer-resources/rate-limits#what-are-the-rate-limits-for-the-0x-apis)
*/
batchSize?: number
baseUrl?: string
debug?: boolean
}): FetchRoutesImpl => {
@@ -21,17 +28,29 @@ export const fetchMatchaPossibleRoutesFactory = (options: {
const baseUrl = options.baseUrl ?? "https://api.0x.org"
const batchSize = options.batchSize ?? 10
return async info => {
const res: Awaited<ReturnType<FetchRoutesImpl>> = []
for (const route of info.possibleRoutes) {
const batches = arraySplit(
(_, idx) => Math.floor(idx / batchSize),
info.possibleRoutes,
)
const res: Awaited<ReturnType<FetchRoutesImpl>>[] = []
for (const batch of batches) {
res.push(
...(await fetchMatchaPossibleRouteImpl(
{ apiKey: options.apiKey, baseUrl, debugLog },
route,
...(await Promise.all(
batch.map(route =>
fetchMatchaPossibleRouteImpl(
{ debugLog, baseUrl, apiKey: options.apiKey },
route,
),
),
)),
)
}
return res
return res.flat()
}
}