Skip to content

Commit adb6efd

Browse files
committed
refactor swap manager
1 parent 1977611 commit adb6efd

File tree

1 file changed

+117
-156
lines changed

1 file changed

+117
-156
lines changed

packages/swap/src/manager.ts

+117-156
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Api, Portfolio, Swap} from '@yoroi/types'
2-
import {isLeft} from '@yoroi/common'
2+
import {isLeft, isRight} from '@yoroi/common'
33
import {freeze} from 'immer'
44

55
import {dexhunterApiMaker} from './adapters/api/dexhunter/api-maker'
@@ -41,7 +41,6 @@ export const swapManagerMaker: Swap.ManagerMaker = ({
4141
[Swap.Aggregator.Muesliswap]: muesliswapApi,
4242
},
4343
config,
44-
primaryTokenInfo.id,
4544
),
4645
assignConfig: (v: Swap.ManagerConfig): Swap.ManagerConfig =>
4746
Object.assign(config, v),
@@ -54,41 +53,42 @@ export const swapManagerMaker: Swap.ManagerMaker = ({
5453
const apiManagerMaker = (
5554
adapters: Record<Swap.Aggregator, Swap.Api>,
5655
config: Swap.ManagerConfig,
57-
ptId: Portfolio.Token.Id,
5856
): Swap.Api => {
59-
const dhTokenList = new Set<Portfolio.Token.Id>([ptId])
60-
const msTokenList = new Set<Portfolio.Token.Id>([ptId])
61-
6257
return freeze(
6358
{
6459
async tokens() {
65-
const [dexhunterResponse, muesliswapResponse] = await Promise.all([
66-
config.routingPreference === 'auto' ||
67-
config.routingPreference.includes('dexhunter')
68-
? adapters.dexhunter.tokens()
69-
: excluded,
70-
config.routingPreference === 'auto' ||
71-
config.routingPreference.includes('muesliswap')
72-
? adapters.muesliswap.tokens()
73-
: excluded,
74-
])
60+
const aggregatorPromises: Record<
61+
Swap.Aggregator,
62+
Promise<Api.Response<Portfolio.Token.Info[]>>
63+
> = {
64+
dexhunter: adapters.dexhunter.tokens(),
65+
muesliswap: adapters.muesliswap.tokens(),
66+
}
67+
68+
const responses: Array<Api.Response<Portfolio.Token.Info[]>> =
69+
await Promise.all(
70+
Object.entries(aggregatorPromises).map(([key, promise]) =>
71+
config.routingPreference === 'auto' ||
72+
config.routingPreference.includes(key as Swap.Aggregator)
73+
? promise
74+
: excluded,
75+
),
76+
)
7577

76-
warnAllLeft(dexhunterResponse, muesliswapResponse)
78+
warnAllLeft(...responses)
7779

78-
if (isLeft(dexhunterResponse)) return muesliswapResponse
79-
if (isLeft(muesliswapResponse)) return dexhunterResponse
80+
if (responses.every(isLeft)) return invalid
8081

8182
const merged: Record<Portfolio.Token.Id, Portfolio.Token.Info> = {}
82-
const append =
83-
(tokenList: Set<Portfolio.Token.Id>) =>
84-
(tokenInfo: Portfolio.Token.Info) => {
85-
tokenList.add(tokenInfo.id)
86-
if (merged[tokenInfo.id] === undefined)
87-
merged[tokenInfo.id] = tokenInfo
88-
}
83+
const append = (tokenInfo: Portfolio.Token.Info) => {
84+
if (merged[tokenInfo.id] === undefined)
85+
merged[tokenInfo.id] = tokenInfo
86+
}
8987

90-
dexhunterResponse.value.data.forEach(append(dhTokenList))
91-
muesliswapResponse.value.data.forEach(append(msTokenList))
88+
responses
89+
.filter(isRight)
90+
.flatMap(({value}) => value.data)
91+
.forEach(append)
9292

9393
return {
9494
tag: 'right',
@@ -100,15 +100,14 @@ const apiManagerMaker = (
100100
},
101101

102102
async orders() {
103-
const [dexhunterResponse, muesliswapResponse] = await Promise.all([
104-
adapters.dexhunter.orders(),
103+
const responses = await Promise.all([
105104
adapters.muesliswap.orders(),
105+
adapters.dexhunter.orders(),
106106
])
107107

108-
warnAllLeft(dexhunterResponse, muesliswapResponse)
108+
warnAllLeft(...responses)
109109

110-
if (isLeft(dexhunterResponse)) return muesliswapResponse
111-
if (isLeft(muesliswapResponse)) return dexhunterResponse
110+
if (responses.every(isLeft)) return invalid
112111

113112
const merged: Record<Swap.Order['txHash'], Swap.Order> = {}
114113
const append = (order: Swap.Order) => {
@@ -119,8 +118,10 @@ const apiManagerMaker = (
119118
merged[order.txHash] = order
120119
}
121120

122-
muesliswapResponse.value.data.forEach(append)
123-
dexhunterResponse.value.data.forEach(append)
121+
responses
122+
.filter(isRight)
123+
.flatMap(({value}) => value.data)
124+
.forEach(append)
124125

125126
return {
126127
tag: 'right',
@@ -135,84 +136,67 @@ const apiManagerMaker = (
135136
},
136137

137138
async protocols() {
138-
const [dexhunterResponse, muesliswapResponse] = await Promise.all([
139-
config.routingPreference === 'auto' ||
140-
config.routingPreference.includes('dexhunter')
141-
? adapters.dexhunter.protocols()
142-
: excluded,
143-
config.routingPreference === 'auto' ||
144-
config.routingPreference.includes('muesliswap')
145-
? adapters.muesliswap.protocols()
146-
: excluded,
147-
])
139+
const aggregatorPromises: Record<
140+
Swap.Aggregator,
141+
Promise<Api.Response<Swap.AggregatorProtocol[]>>
142+
> = {
143+
dexhunter: adapters.dexhunter.protocols(),
144+
muesliswap: adapters.muesliswap.protocols(),
145+
}
148146

149-
warnAllLeft(dexhunterResponse, muesliswapResponse)
147+
const responses: Array<Api.Response<Swap.AggregatorProtocol[]>> =
148+
await Promise.all(
149+
Object.entries(aggregatorPromises).map(([key, promise]) =>
150+
config.routingPreference === 'auto' ||
151+
config.routingPreference.includes(key as Swap.Aggregator)
152+
? promise
153+
: excluded,
154+
),
155+
)
150156

151-
if (isLeft(dexhunterResponse)) return muesliswapResponse
152-
if (isLeft(muesliswapResponse)) return dexhunterResponse
157+
warnAllLeft(...responses)
158+
159+
if (responses.every(isLeft))
160+
return responses.find((res) => res.error.status !== 3) ?? invalid
153161

154162
return {
155163
tag: 'right',
156164
value: {
157165
status: Api.HttpStatusCode.Ok,
158-
data: [
159-
...dexhunterResponse.value.data,
160-
...muesliswapResponse.value.data,
161-
],
166+
data: responses.filter(isRight).flatMap(({value}) => value.data),
162167
},
163168
}
164169
},
165170

166171
async estimate(body: Swap.EstimateRequest) {
167-
const isDHValid = hasTokens(dhTokenList, body)
168-
const isMSValid = hasTokens(msTokenList, body)
169-
170-
if (!isDHValid || !isMSValid) {
171-
if (isDHValid) return adapters.dexhunter.estimate(body)
172-
if (isMSValid) return adapters.muesliswap.estimate(body)
173-
return {
174-
tag: 'left',
175-
error: {
176-
status: -3,
177-
message: 'Tokens not found in aggregators',
178-
responseData: {},
179-
},
180-
}
172+
const aggregatorPromises: Record<
173+
Swap.Aggregator,
174+
Promise<Api.Response<Swap.EstimateResponse>>
175+
> = {
176+
dexhunter: adapters.dexhunter.estimate(body),
177+
muesliswap: adapters.muesliswap.estimate(body),
181178
}
182179

183-
const [dexhunterResponse, muesliswapResponse] = await Promise.all([
184-
config.routingPreference === 'auto' ||
185-
config.routingPreference.includes('dexhunter')
186-
? adapters.dexhunter.estimate(body)
187-
: excluded,
188-
config.routingPreference === 'auto' ||
189-
config.routingPreference.includes('muesliswap')
190-
? adapters.muesliswap.estimate(body)
191-
: excluded,
192-
])
180+
const responses: Array<Api.Response<Swap.EstimateResponse>> =
181+
await Promise.all(
182+
Object.entries(aggregatorPromises).map(([key, promise]) =>
183+
config.routingPreference === 'auto' ||
184+
config.routingPreference.includes(key as Swap.Aggregator)
185+
? promise
186+
: excluded,
187+
),
188+
)
189+
190+
warnAllLeft(...responses)
191+
192+
if (responses.every(isLeft))
193+
return responses.find((res) => res.error.status !== 3) ?? invalid
194+
195+
const estimates = responses
196+
.filter(isRight)
197+
.flatMap(({value}) => value.data)
193198

194-
warnAllLeft(dexhunterResponse, muesliswapResponse)
195-
196-
if (
197-
isLeft(dexhunterResponse) &&
198-
isLeft(muesliswapResponse) &&
199-
dexhunterResponse.error.status === -3
200-
)
201-
return muesliswapResponse
202-
if (
203-
isLeft(dexhunterResponse) &&
204-
isLeft(muesliswapResponse) &&
205-
muesliswapResponse.error.status === -3
206-
)
207-
return dexhunterResponse
208-
209-
if (isLeft(dexhunterResponse)) return muesliswapResponse
210-
if (isLeft(muesliswapResponse)) return dexhunterResponse
211-
212-
const bestEstimate = [
213-
dexhunterResponse.value.data,
214-
muesliswapResponse.value.data,
215-
].reduce(getBestSwap, dexhunterResponse.value.data)
199+
const bestEstimate = estimates.reduce(getBestSwap, estimates[0]!)
216200

217201
return {
218202
tag: 'right',
@@ -224,55 +208,32 @@ const apiManagerMaker = (
224208
},
225209

226210
async create(body: Swap.CreateRequest) {
227-
const isDHValid = hasTokens(dhTokenList, body)
228-
const isMSValid = hasTokens(msTokenList, body)
229-
230-
if (!isDHValid || !isMSValid) {
231-
if (isDHValid) return adapters.dexhunter.create(body)
232-
if (isMSValid) return adapters.muesliswap.create(body)
233-
return {
234-
tag: 'left',
235-
error: {
236-
status: -3,
237-
message: 'Tokens not found in aggregators',
238-
responseData: {},
239-
},
240-
}
211+
const aggregatorPromises: Record<
212+
Swap.Aggregator,
213+
Promise<Api.Response<Swap.CreateResponse>>
214+
> = {
215+
dexhunter: adapters.dexhunter.create(body),
216+
muesliswap: adapters.muesliswap.create(body),
241217
}
242218

243-
const [dexhunterResponse, muesliswapResponse] = await Promise.all([
244-
config.routingPreference === 'auto' ||
245-
config.routingPreference.includes('dexhunter')
246-
? adapters.dexhunter.create(body)
247-
: excluded,
248-
config.routingPreference === 'auto' ||
249-
config.routingPreference.includes('muesliswap')
250-
? adapters.muesliswap.create(body)
251-
: excluded,
252-
])
219+
const responses: Array<Api.Response<Swap.CreateResponse>> =
220+
await Promise.all(
221+
Object.entries(aggregatorPromises).map(([key, promise]) =>
222+
config.routingPreference === 'auto' ||
223+
config.routingPreference.includes(key as Swap.Aggregator)
224+
? promise
225+
: excluded,
226+
),
227+
)
228+
229+
warnAllLeft(...responses)
230+
231+
if (responses.every(isLeft))
232+
return responses.find((res) => res.error.status !== 3) ?? invalid
253233

254-
warnAllLeft(dexhunterResponse, muesliswapResponse)
255-
256-
if (
257-
isLeft(dexhunterResponse) &&
258-
isLeft(muesliswapResponse) &&
259-
dexhunterResponse.error.status === -3
260-
)
261-
return muesliswapResponse
262-
if (
263-
isLeft(dexhunterResponse) &&
264-
isLeft(muesliswapResponse) &&
265-
muesliswapResponse.error.status === -3
266-
)
267-
return dexhunterResponse
268-
269-
if (isLeft(dexhunterResponse)) return muesliswapResponse
270-
if (isLeft(muesliswapResponse)) return dexhunterResponse
271-
272-
const bestCreate = [
273-
dexhunterResponse.value.data,
274-
muesliswapResponse.value.data,
275-
].reduce(getBestSwap, dexhunterResponse.value.data)
234+
const creates = responses.filter(isRight).map(({value}) => value.data)
235+
236+
const bestCreate = creates.reduce(getBestSwap, creates[0]!)
276237

277238
return {
278239
tag: 'right',
@@ -305,22 +266,22 @@ const excluded: Api.Response<any> = freeze(
305266
true,
306267
)
307268

269+
const invalid: Api.Response<any> = freeze(
270+
{
271+
tag: 'left',
272+
error: {
273+
status: -3,
274+
message: 'Unknown error',
275+
responseData: {},
276+
},
277+
},
278+
true,
279+
)
280+
308281
const warnAllLeft = (...responses: Array<Api.Response<any>>) => {
309282
if (responses.every(isLeft))
310283
console.warn(
311284
'Swap Manager all left >> ',
312285
responses.map((response) => response.error.message),
313286
)
314287
}
315-
316-
const hasTokens = (
317-
tokenList: Set<Portfolio.Token.Id>,
318-
body: Swap.CreateRequest | Swap.EstimateRequest,
319-
): boolean => {
320-
const {tokenIn, tokenOut} = body
321-
322-
if (!tokenList.has(tokenIn)) return false
323-
if (!tokenList.has(tokenOut)) return false
324-
325-
return true
326-
}

0 commit comments

Comments
 (0)