@cetusprotocol/aggregator-sdk 0.3.20 → 0.3.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lockb +0 -0
- package/dist/index.d.mts +8 -3
- package/dist/index.d.ts +8 -3
- package/dist/index.js +161 -46
- package/dist/index.mjs +161 -47
- package/dist/src/client.d.ts +7 -2
- package/dist/src/transaction/haedal_pmm.d.ts +2 -4
- package/package.json +1 -1
- package/src/api.ts +2 -2
- package/src/client.ts +232 -58
- package/src/transaction/haedal.ts +1 -4
- package/src/transaction/haedal_pmm.ts +33 -24
- package/src/transaction/index.ts +9 -4
- package/tests/router.test.ts +25 -11
package/src/client.ts
CHANGED
|
@@ -43,7 +43,10 @@ import { Bluefin } from "./transaction/bluefin"
|
|
|
43
43
|
import { HaedalPmm } from "./transaction/haedal_pmm"
|
|
44
44
|
import { Alphafi } from "./transaction/alphafi"
|
|
45
45
|
import { CoinUtils } from "./types/CoinAssist"
|
|
46
|
-
|
|
46
|
+
import {
|
|
47
|
+
SuiPriceServiceConnection,
|
|
48
|
+
SuiPythClient,
|
|
49
|
+
} from "@pythnetwork/pyth-sui-js"
|
|
47
50
|
|
|
48
51
|
export const CETUS = "CETUS"
|
|
49
52
|
export const DEEPBOOKV2 = "DEEPBOOK"
|
|
@@ -116,6 +119,12 @@ export interface SwapInPoolsParams {
|
|
|
116
119
|
pools: string[]
|
|
117
120
|
}
|
|
118
121
|
|
|
122
|
+
interface PythConfig {
|
|
123
|
+
connections: SuiPriceServiceConnection[]
|
|
124
|
+
wormholeStateId: string
|
|
125
|
+
pythStateId: string
|
|
126
|
+
}
|
|
127
|
+
|
|
119
128
|
export interface SwapInPoolsResult {
|
|
120
129
|
isExceed: boolean
|
|
121
130
|
routeData?: RouterData
|
|
@@ -124,13 +133,13 @@ export interface SwapInPoolsResult {
|
|
|
124
133
|
function isBuilderRouterSwapParams(
|
|
125
134
|
params: BuildRouterSwapParams | BuildRouterSwapParamsV2
|
|
126
135
|
): params is BuildRouterSwapParams {
|
|
127
|
-
return Array.isArray((params as BuildRouterSwapParams).routers)
|
|
136
|
+
return Array.isArray((params as BuildRouterSwapParams).routers)
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
function isBuilderFastRouterSwapParams(
|
|
131
140
|
params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2
|
|
132
141
|
): params is BuildFastRouterSwapParams {
|
|
133
|
-
return Array.isArray((params as BuildFastRouterSwapParams).routers)
|
|
142
|
+
return Array.isArray((params as BuildFastRouterSwapParams).routers)
|
|
134
143
|
}
|
|
135
144
|
|
|
136
145
|
export class AggregatorClient {
|
|
@@ -140,6 +149,38 @@ export class AggregatorClient {
|
|
|
140
149
|
public env: Env
|
|
141
150
|
private allCoins: Map<string, CoinAsset[]>
|
|
142
151
|
|
|
152
|
+
private pythConnections: SuiPriceServiceConnection[]
|
|
153
|
+
private pythClient: SuiPythClient
|
|
154
|
+
|
|
155
|
+
private static readonly CONFIG: Record<Env, PythConfig> = {
|
|
156
|
+
[Env.Testnet]: {
|
|
157
|
+
connections: [
|
|
158
|
+
new SuiPriceServiceConnection("https://hermes-beta.pyth.network"),
|
|
159
|
+
],
|
|
160
|
+
wormholeStateId:
|
|
161
|
+
"0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
|
162
|
+
pythStateId:
|
|
163
|
+
"0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c",
|
|
164
|
+
},
|
|
165
|
+
[Env.Mainnet]: {
|
|
166
|
+
connections: [
|
|
167
|
+
new SuiPriceServiceConnection(
|
|
168
|
+
"https://cetus.liquify.com/api=X9LTVPQD7Y3R5N2A/hermes",
|
|
169
|
+
{
|
|
170
|
+
timeout: 3000,
|
|
171
|
+
}
|
|
172
|
+
),
|
|
173
|
+
new SuiPriceServiceConnection("https://hermes.pyth.network", {
|
|
174
|
+
timeout: 3000,
|
|
175
|
+
}),
|
|
176
|
+
],
|
|
177
|
+
wormholeStateId:
|
|
178
|
+
"0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
|
179
|
+
pythStateId:
|
|
180
|
+
"0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8",
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
|
|
143
184
|
constructor(
|
|
144
185
|
endpoint?: string,
|
|
145
186
|
signer?: string,
|
|
@@ -151,6 +192,14 @@ export class AggregatorClient {
|
|
|
151
192
|
this.signer = signer || ""
|
|
152
193
|
this.env = env || Env.Mainnet
|
|
153
194
|
this.allCoins = new Map<string, CoinAsset[]>()
|
|
195
|
+
|
|
196
|
+
const config = AggregatorClient.CONFIG[this.env]
|
|
197
|
+
this.pythConnections = config.connections
|
|
198
|
+
this.pythClient = new SuiPythClient(
|
|
199
|
+
this.client,
|
|
200
|
+
config.pythStateId,
|
|
201
|
+
config.wormholeStateId
|
|
202
|
+
)
|
|
154
203
|
}
|
|
155
204
|
|
|
156
205
|
async getCoins(
|
|
@@ -205,6 +254,7 @@ export class AggregatorClient {
|
|
|
205
254
|
inputCoin: TransactionObjectArgument,
|
|
206
255
|
routers: Router[],
|
|
207
256
|
amountOutLimit: BN,
|
|
257
|
+
pythPriceIDs: Map<string, string>,
|
|
208
258
|
partner?: string,
|
|
209
259
|
deepbookv3DeepFee?: TransactionObjectArgument,
|
|
210
260
|
packages?: Map<string, string>
|
|
@@ -223,16 +273,31 @@ export class AggregatorClient {
|
|
|
223
273
|
}
|
|
224
274
|
let nextCoin = inputCoins[i] as TransactionObjectArgument
|
|
225
275
|
for (const path of routers[i].path) {
|
|
226
|
-
const dex = this.newDex(path.provider, partner)
|
|
227
|
-
nextCoin = await dex.swap(
|
|
276
|
+
const dex = this.newDex(path.provider, pythPriceIDs, partner)
|
|
277
|
+
nextCoin = await dex.swap(
|
|
278
|
+
this,
|
|
279
|
+
txb,
|
|
280
|
+
path,
|
|
281
|
+
nextCoin,
|
|
282
|
+
packages,
|
|
283
|
+
deepbookv3DeepFee
|
|
284
|
+
)
|
|
228
285
|
}
|
|
229
286
|
|
|
230
287
|
outputCoins.push(nextCoin)
|
|
231
288
|
}
|
|
232
289
|
|
|
233
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
290
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
291
|
+
this.publishedAtV2(),
|
|
292
|
+
packages
|
|
293
|
+
)
|
|
234
294
|
|
|
235
|
-
this.transferOrDestoryCoin(
|
|
295
|
+
this.transferOrDestoryCoin(
|
|
296
|
+
txb,
|
|
297
|
+
inputCoin,
|
|
298
|
+
inputCoinType,
|
|
299
|
+
this.publishedAtV2()
|
|
300
|
+
)
|
|
236
301
|
const mergedTargetCointhis = this.checkCoinThresholdAndMergeCoin(
|
|
237
302
|
txb,
|
|
238
303
|
outputCoins,
|
|
@@ -255,7 +320,10 @@ export class AggregatorClient {
|
|
|
255
320
|
const targetCoins = []
|
|
256
321
|
const dex = new Cetus(this.env, partner)
|
|
257
322
|
|
|
258
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
323
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
324
|
+
this.publishedAtV2(),
|
|
325
|
+
packages
|
|
326
|
+
)
|
|
259
327
|
|
|
260
328
|
for (let i = 0; i < routers.length; i++) {
|
|
261
329
|
const router = routers[i]
|
|
@@ -280,7 +348,12 @@ export class AggregatorClient {
|
|
|
280
348
|
if (j === 0) {
|
|
281
349
|
inputCoin = repayResult
|
|
282
350
|
} else {
|
|
283
|
-
this.transferOrDestoryCoin(
|
|
351
|
+
this.transferOrDestoryCoin(
|
|
352
|
+
txb,
|
|
353
|
+
repayResult,
|
|
354
|
+
path.from,
|
|
355
|
+
aggregatorV2PublishedAt
|
|
356
|
+
)
|
|
284
357
|
}
|
|
285
358
|
if (j === router.path.length - 1) {
|
|
286
359
|
targetCoins.push(nextRepayCoin)
|
|
@@ -288,7 +361,12 @@ export class AggregatorClient {
|
|
|
288
361
|
}
|
|
289
362
|
}
|
|
290
363
|
const inputCoinType = routers[0].path[0].from
|
|
291
|
-
this.transferOrDestoryCoin(
|
|
364
|
+
this.transferOrDestoryCoin(
|
|
365
|
+
txb,
|
|
366
|
+
inputCoin,
|
|
367
|
+
inputCoinType,
|
|
368
|
+
aggregatorV2PublishedAt
|
|
369
|
+
)
|
|
292
370
|
if (targetCoins.length > 1) {
|
|
293
371
|
const vec = txb.makeMoveVec({ elements: targetCoins.slice(1) })
|
|
294
372
|
txb.moveCall({
|
|
@@ -317,19 +395,13 @@ export class AggregatorClient {
|
|
|
317
395
|
async routerSwap(
|
|
318
396
|
params: BuildRouterSwapParams | BuildRouterSwapParamsV2
|
|
319
397
|
): Promise<TransactionObjectArgument> {
|
|
320
|
-
const {
|
|
321
|
-
|
|
322
|
-
inputCoin,
|
|
323
|
-
slippage,
|
|
324
|
-
txb,
|
|
325
|
-
partner,
|
|
326
|
-
deepbookv3DeepFee,
|
|
327
|
-
} = params
|
|
398
|
+
const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } =
|
|
399
|
+
params
|
|
328
400
|
|
|
329
401
|
const routerData = Array.isArray(routers) ? routers : routers.routes
|
|
330
|
-
const byAmountIn = isBuilderRouterSwapParams(params)
|
|
331
|
-
|
|
332
|
-
|
|
402
|
+
const byAmountIn = isBuilderRouterSwapParams(params)
|
|
403
|
+
? params.byAmountIn
|
|
404
|
+
: params.routers.byAmountIn
|
|
333
405
|
|
|
334
406
|
const amountIn = routerData.reduce(
|
|
335
407
|
(acc, router) => acc.add(router.amountIn),
|
|
@@ -346,11 +418,23 @@ export class AggregatorClient {
|
|
|
346
418
|
slippage
|
|
347
419
|
)
|
|
348
420
|
|
|
349
|
-
const packages = isBuilderRouterSwapParams(params)
|
|
421
|
+
const packages = isBuilderRouterSwapParams(params)
|
|
422
|
+
? undefined
|
|
423
|
+
: params.routers.packages
|
|
350
424
|
|
|
351
425
|
console.log("packages11", packages)
|
|
352
426
|
|
|
353
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
427
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
428
|
+
this.publishedAtV2(),
|
|
429
|
+
packages
|
|
430
|
+
)
|
|
431
|
+
|
|
432
|
+
const priceIDs = findPythPriceIDs(routerData)
|
|
433
|
+
|
|
434
|
+
const priceInfoObjectIds =
|
|
435
|
+
priceIDs.length > 0
|
|
436
|
+
? await this.updatePythPriceIDs(priceIDs, txb)
|
|
437
|
+
: new Map<string, string>()
|
|
354
438
|
|
|
355
439
|
if (byAmountIn) {
|
|
356
440
|
const targetCoin = await this.expectInputSwap(
|
|
@@ -358,9 +442,10 @@ export class AggregatorClient {
|
|
|
358
442
|
inputCoin,
|
|
359
443
|
routerData,
|
|
360
444
|
amountLimit,
|
|
445
|
+
priceInfoObjectIds,
|
|
361
446
|
partner,
|
|
362
447
|
deepbookv3DeepFee,
|
|
363
|
-
packages
|
|
448
|
+
packages
|
|
364
449
|
)
|
|
365
450
|
return targetCoin
|
|
366
451
|
}
|
|
@@ -369,7 +454,12 @@ export class AggregatorClient {
|
|
|
369
454
|
const splitedInputCoins = txb.splitCoins(inputCoin, [
|
|
370
455
|
amountLimit.toString(),
|
|
371
456
|
])
|
|
372
|
-
this.transferOrDestoryCoin(
|
|
457
|
+
this.transferOrDestoryCoin(
|
|
458
|
+
txb,
|
|
459
|
+
inputCoin,
|
|
460
|
+
routerData[0].path[0].from,
|
|
461
|
+
aggregatorV2PublishedAt
|
|
462
|
+
)
|
|
373
463
|
const targetCoin = await this.expectOutputSwap(
|
|
374
464
|
txb,
|
|
375
465
|
splitedInputCoins[0],
|
|
@@ -381,7 +471,9 @@ export class AggregatorClient {
|
|
|
381
471
|
|
|
382
472
|
// auto build input coin
|
|
383
473
|
// auto merge, transfer or destory target coin.
|
|
384
|
-
async fastRouterSwap(
|
|
474
|
+
async fastRouterSwap(
|
|
475
|
+
params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2
|
|
476
|
+
) {
|
|
385
477
|
const {
|
|
386
478
|
routers,
|
|
387
479
|
slippage,
|
|
@@ -395,7 +487,8 @@ export class AggregatorClient {
|
|
|
395
487
|
const fromCoinType = routerData[0].path[0].from
|
|
396
488
|
let fromCoins = await this.getCoins(fromCoinType, refreshAllCoins)
|
|
397
489
|
|
|
398
|
-
const targetCoinType =
|
|
490
|
+
const targetCoinType =
|
|
491
|
+
routerData[0].path[routerData[0].path.length - 1].target
|
|
399
492
|
const amountIn = routerData.reduce(
|
|
400
493
|
(acc, router) => acc.add(router.amountIn),
|
|
401
494
|
new BN(0)
|
|
@@ -405,7 +498,9 @@ export class AggregatorClient {
|
|
|
405
498
|
new BN(0)
|
|
406
499
|
)
|
|
407
500
|
|
|
408
|
-
const byAmountIn = isBuilderFastRouterSwapParams(params)
|
|
501
|
+
const byAmountIn = isBuilderFastRouterSwapParams(params)
|
|
502
|
+
? params.byAmountIn
|
|
503
|
+
: params.routers.byAmountIn
|
|
409
504
|
const amountLimit = CalculateAmountLimit(
|
|
410
505
|
byAmountIn ? amountOut : amountIn,
|
|
411
506
|
byAmountIn,
|
|
@@ -430,23 +525,25 @@ export class AggregatorClient {
|
|
|
430
525
|
).targetCoin
|
|
431
526
|
}
|
|
432
527
|
|
|
433
|
-
const routerSwapParams = isBuilderFastRouterSwapParams(params)
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
528
|
+
const routerSwapParams = isBuilderFastRouterSwapParams(params)
|
|
529
|
+
? {
|
|
530
|
+
routers: routerData,
|
|
531
|
+
inputCoin: buildFromCoinRes.targetCoin,
|
|
532
|
+
slippage,
|
|
533
|
+
byAmountIn,
|
|
534
|
+
txb,
|
|
535
|
+
partner,
|
|
536
|
+
deepbookv3DeepFee: deepCoin,
|
|
537
|
+
}
|
|
538
|
+
: {
|
|
539
|
+
routers: params.routers,
|
|
540
|
+
inputCoin: buildFromCoinRes.targetCoin,
|
|
541
|
+
slippage,
|
|
542
|
+
byAmountIn,
|
|
543
|
+
txb,
|
|
544
|
+
partner,
|
|
545
|
+
deepbookv3DeepFee: deepCoin,
|
|
546
|
+
}
|
|
450
547
|
|
|
451
548
|
const targetCoin = await this.routerSwap(routerSwapParams)
|
|
452
549
|
|
|
@@ -460,10 +557,15 @@ export class AggregatorClient {
|
|
|
460
557
|
BigInt(0),
|
|
461
558
|
targetCoinType
|
|
462
559
|
)
|
|
463
|
-
|
|
464
|
-
const packages = isBuilderFastRouterSwapParams(params)
|
|
465
|
-
|
|
466
|
-
|
|
560
|
+
|
|
561
|
+
const packages = isBuilderFastRouterSwapParams(params)
|
|
562
|
+
? undefined
|
|
563
|
+
: params.routers.packages
|
|
564
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
565
|
+
this.publishedAtV2(),
|
|
566
|
+
packages
|
|
567
|
+
)
|
|
568
|
+
|
|
467
569
|
txb.mergeCoins(targetCoinRes.targetCoin, [targetCoin])
|
|
468
570
|
if (targetCoinRes.isMintZeroCoin) {
|
|
469
571
|
this.transferOrDestoryCoin(
|
|
@@ -479,9 +581,10 @@ export class AggregatorClient {
|
|
|
479
581
|
// Include cetus、deepbookv2、flowxv2 & v3、kriyav2 & v3、turbos、aftermath、haedal、afsui、volo、bluemove
|
|
480
582
|
publishedAtV2(): string {
|
|
481
583
|
if (this.env === Env.Mainnet) {
|
|
482
|
-
return "0x3fb42ddf908af45f9fc3c59eab227888ff24ba2e137b3b55bf80920fd47e11af" // version 6
|
|
584
|
+
// return "0x3fb42ddf908af45f9fc3c59eab227888ff24ba2e137b3b55bf80920fd47e11af" // version 6
|
|
483
585
|
// return "0x4069913c4953297b7f08f67f6722e3b04aa5ab2976b4e1b8a456b81590b34ab4"
|
|
484
|
-
|
|
586
|
+
return "0xf9c6f78322ed667909e05f6b42b2f5a67af6297503c905335e02a15148e9440d"
|
|
587
|
+
// return "0x803db8dfcc86fc1afbc7d2212bd14ec9690978ddebea0d590e01147d6b17aa06" // pre
|
|
485
588
|
} else {
|
|
486
589
|
// return "0x0ed287d6c3fe4962d0994ffddc1d19a15fba6a81533f3f0dcc2bbcedebce0637" // version 2
|
|
487
590
|
return "0x52eae33adeb44de55cfb3f281d4cc9e02d976181c0952f5323648b5717b33934"
|
|
@@ -497,7 +600,7 @@ export class AggregatorClient {
|
|
|
497
600
|
// return "0x3b6d71bdeb8ce5b06febfd3cfc29ecd60d50da729477c8b8038ecdae34541b91" // version 5, add bluefin
|
|
498
601
|
// return "0x81ade554cb24a7564ca43a4bfb7381b08d9e5c5f375162c95215b696ab903502" // version 6, force upgrade scallop
|
|
499
602
|
// return "0x347dd58bbd11cd82c8b386b344729717c04a998da73386e82a239cc196d5706b" // version 7
|
|
500
|
-
return "0xf2fcea41dc217385019828375764fa06d9bd25e8e4726ba1962680849fb8d613"
|
|
603
|
+
return "0xf2fcea41dc217385019828375764fa06d9bd25e8e4726ba1962680849fb8d613" // version 8
|
|
501
604
|
} else {
|
|
502
605
|
return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78"
|
|
503
606
|
}
|
|
@@ -550,7 +653,11 @@ export class AggregatorClient {
|
|
|
550
653
|
return targetCoin
|
|
551
654
|
}
|
|
552
655
|
|
|
553
|
-
newDex(
|
|
656
|
+
newDex(
|
|
657
|
+
provider: string,
|
|
658
|
+
pythPriceIDs: Map<string, string>,
|
|
659
|
+
partner?: string
|
|
660
|
+
): Dex {
|
|
554
661
|
switch (provider) {
|
|
555
662
|
case CETUS:
|
|
556
663
|
return new Cetus(this.env, partner)
|
|
@@ -587,7 +694,7 @@ export class AggregatorClient {
|
|
|
587
694
|
case BLUEFIN:
|
|
588
695
|
return new Bluefin(this.env)
|
|
589
696
|
case HAEDALPMM:
|
|
590
|
-
return new HaedalPmm(this.env,
|
|
697
|
+
return new HaedalPmm(this.env, pythPriceIDs)
|
|
591
698
|
case ALPHAFI:
|
|
592
699
|
return new Alphafi(this.env)
|
|
593
700
|
default:
|
|
@@ -633,9 +740,74 @@ export class AggregatorClient {
|
|
|
633
740
|
}
|
|
634
741
|
return null
|
|
635
742
|
}
|
|
743
|
+
|
|
744
|
+
async updatePythPriceIDs(
|
|
745
|
+
priceIDs: string[],
|
|
746
|
+
txb: Transaction
|
|
747
|
+
): Promise<Map<string, string>> {
|
|
748
|
+
let priceUpdateData: Buffer[] | null = null
|
|
749
|
+
let lastError: Error | null = null
|
|
750
|
+
|
|
751
|
+
for (const connection of this.pythConnections) {
|
|
752
|
+
try {
|
|
753
|
+
priceUpdateData = await connection.getPriceFeedsUpdateData(priceIDs)
|
|
754
|
+
break
|
|
755
|
+
} catch (e) {
|
|
756
|
+
lastError = e as Error
|
|
757
|
+
console.log("Error: ", e)
|
|
758
|
+
continue
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
if (priceUpdateData == null) {
|
|
763
|
+
throw new Error(
|
|
764
|
+
`No pyth price seeds update data found: ${lastError?.message}`
|
|
765
|
+
)
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
let priceInfoObjectIds = []
|
|
769
|
+
try {
|
|
770
|
+
priceInfoObjectIds = await this.pythClient.updatePriceFeeds(
|
|
771
|
+
txb,
|
|
772
|
+
priceUpdateData,
|
|
773
|
+
priceIDs
|
|
774
|
+
)
|
|
775
|
+
} catch (e) {
|
|
776
|
+
throw new Error(`Failed to update price feeds: ${e}`)
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
let priceInfoObjectIdsMap = new Map<string, string>()
|
|
780
|
+
for (let i = 0; i < priceIDs.length; i++) {
|
|
781
|
+
priceInfoObjectIdsMap.set(priceIDs[i], priceInfoObjectIds[i])
|
|
782
|
+
}
|
|
783
|
+
return priceInfoObjectIdsMap
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export function findPythPriceIDs(routes: Router[]): string[] {
|
|
788
|
+
const priceIDs = new Set<string>()
|
|
789
|
+
|
|
790
|
+
for (const route of routes) {
|
|
791
|
+
for (const path of route.path) {
|
|
792
|
+
if (path.provider === HAEDALPMM) {
|
|
793
|
+
if (
|
|
794
|
+
path.extendedDetails &&
|
|
795
|
+
path.extendedDetails.haedalPmmBasePriceSeed &&
|
|
796
|
+
path.extendedDetails.haedalPmmQuotePriceSeed
|
|
797
|
+
) {
|
|
798
|
+
priceIDs.add(path.extendedDetails.haedalPmmBasePriceSeed)
|
|
799
|
+
priceIDs.add(path.extendedDetails.haedalPmmQuotePriceSeed)
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
return Array.from(priceIDs)
|
|
636
805
|
}
|
|
637
806
|
|
|
638
|
-
export function parseRouterResponse(
|
|
807
|
+
export function parseRouterResponse(
|
|
808
|
+
data: any,
|
|
809
|
+
byAmountIn: boolean
|
|
810
|
+
): RouterData {
|
|
639
811
|
let totalDeepFee = 0
|
|
640
812
|
for (const route of data.routes) {
|
|
641
813
|
for (const path of route.path) {
|
|
@@ -673,7 +845,7 @@ export function parseRouterResponse(data: any, byAmountIn: boolean): RouterData
|
|
|
673
845
|
path.provider === AFTERMATH ||
|
|
674
846
|
path.provider === CETUS ||
|
|
675
847
|
path.provider === DEEPBOOKV3 ||
|
|
676
|
-
path.provider === SCALLOP ||
|
|
848
|
+
path.provider === SCALLOP ||
|
|
677
849
|
path.provider === HAEDALPMM
|
|
678
850
|
) {
|
|
679
851
|
extendedDetails = {
|
|
@@ -684,8 +856,10 @@ export function parseRouterResponse(data: any, byAmountIn: boolean): RouterData
|
|
|
684
856
|
deepbookv3DeepFee: path.extended_details?.deepbookv3_deep_fee,
|
|
685
857
|
scallopScoinTreasury:
|
|
686
858
|
path.extended_details?.scallop_scoin_treasury,
|
|
687
|
-
haedalPmmBasePriceSeed:
|
|
688
|
-
|
|
859
|
+
haedalPmmBasePriceSeed:
|
|
860
|
+
path.extended_details?.haedal_pmm_base_price_seed,
|
|
861
|
+
haedalPmmQuotePriceSeed:
|
|
862
|
+
path.extended_details?.haedal_pmm_quote_price_seed,
|
|
689
863
|
}
|
|
690
864
|
}
|
|
691
865
|
|
|
@@ -19,10 +19,7 @@ export class Haedal implements Dex {
|
|
|
19
19
|
packages?: Map<string, string>
|
|
20
20
|
): Promise<TransactionObjectArgument> {
|
|
21
21
|
const { direction } = path
|
|
22
|
-
|
|
23
|
-
throw new Error("Haedal not support b2a swap")
|
|
24
|
-
}
|
|
25
|
-
const func = "swap_a2b"
|
|
22
|
+
const func = direction ? "swap_a2b" : "swap_b2a"
|
|
26
23
|
const args = [txb.object(path.id), txb.object("0x5"), inputCoin]
|
|
27
24
|
const publishedAt = getAggregatorV2PublishedAt(client.publishedAtV2(), packages)
|
|
28
25
|
const res = txb.moveCall({
|
|
@@ -3,26 +3,23 @@ import {
|
|
|
3
3
|
TransactionArgument,
|
|
4
4
|
TransactionObjectArgument,
|
|
5
5
|
} from "@mysten/sui/transactions"
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import {
|
|
7
|
+
AggregatorClient,
|
|
8
|
+
CLOCK_ADDRESS,
|
|
9
|
+
Dex,
|
|
10
|
+
Env,
|
|
11
|
+
getAggregatorV2ExtendPublishedAt,
|
|
12
|
+
Path,
|
|
13
|
+
} from ".."
|
|
9
14
|
|
|
10
15
|
export class HaedalPmm implements Dex {
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
constructor(env: Env, suiClient: SuiClient) {
|
|
16
|
+
private pythPriceIDs: Map<string, string>
|
|
17
|
+
|
|
18
|
+
constructor(env: Env, pythPriceIDs: Map<string, string>) {
|
|
15
19
|
if (env === Env.Testnet) {
|
|
16
|
-
|
|
17
|
-
const wormholeStateId = "0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790";
|
|
18
|
-
const pythStateId = "0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c";
|
|
19
|
-
this.pythClient = new SuiPythClient(suiClient, pythStateId, wormholeStateId)
|
|
20
|
-
} else {
|
|
21
|
-
this.connection = new SuiPriceServiceConnection("https://hermes.pyth.network")
|
|
22
|
-
const wormholeStateId = "0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c";
|
|
23
|
-
const pythStateId = "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8";
|
|
24
|
-
this.pythClient = new SuiPythClient(suiClient, pythStateId, wormholeStateId)
|
|
20
|
+
throw new Error("HaedalPmm is not supported on testnet")
|
|
25
21
|
}
|
|
22
|
+
this.pythPriceIDs = pythPriceIDs
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
async swap(
|
|
@@ -36,31 +33,43 @@ export class HaedalPmm implements Dex {
|
|
|
36
33
|
const [func, coinAType, coinBType] = direction
|
|
37
34
|
? ["swap_a2b", from, target]
|
|
38
35
|
: ["swap_b2a", target, from]
|
|
39
|
-
|
|
36
|
+
|
|
40
37
|
let basePriceSeed: string
|
|
41
38
|
let quotePriceSeed: string
|
|
42
39
|
|
|
43
40
|
if (path.extendedDetails == null) {
|
|
44
41
|
throw new Error("Extended details not supported haedal pmm")
|
|
45
42
|
} else {
|
|
46
|
-
if (
|
|
43
|
+
if (
|
|
44
|
+
!path.extendedDetails.haedalPmmBasePriceSeed ||
|
|
45
|
+
!path.extendedDetails.haedalPmmQuotePriceSeed
|
|
46
|
+
) {
|
|
47
47
|
throw new Error("Base price seed or quote price seed not supported")
|
|
48
48
|
}
|
|
49
49
|
basePriceSeed = path.extendedDetails.haedalPmmBasePriceSeed
|
|
50
50
|
quotePriceSeed = path.extendedDetails.haedalPmmQuotePriceSeed
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
53
|
+
const basePriceInfoObjectId = this.pythPriceIDs.get(basePriceSeed)
|
|
54
|
+
const quotePriceInfoObjectId = this.pythPriceIDs.get(quotePriceSeed)
|
|
55
|
+
|
|
56
|
+
if (!basePriceInfoObjectId || !quotePriceInfoObjectId) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
"Base price info object id or quote price info object id not found"
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
56
62
|
const args = [
|
|
57
63
|
txb.object(path.id),
|
|
58
|
-
txb.object(
|
|
59
|
-
txb.object(
|
|
64
|
+
txb.object(basePriceInfoObjectId),
|
|
65
|
+
txb.object(quotePriceInfoObjectId),
|
|
60
66
|
inputCoin,
|
|
61
67
|
txb.object(CLOCK_ADDRESS),
|
|
62
68
|
]
|
|
63
|
-
const publishedAt = getAggregatorV2ExtendPublishedAt(
|
|
69
|
+
const publishedAt = getAggregatorV2ExtendPublishedAt(
|
|
70
|
+
client.publishedAtV2Extend(),
|
|
71
|
+
packages
|
|
72
|
+
)
|
|
64
73
|
const res = txb.moveCall({
|
|
65
74
|
target: `${publishedAt}::haedalpmm::${func}`,
|
|
66
75
|
typeArguments: [coinAType, coinBType],
|
package/src/transaction/index.ts
CHANGED
|
@@ -10,14 +10,20 @@ export const CLOCK_ADDRESS =
|
|
|
10
10
|
export const AGGREGATOR_V2 = "aggregator_v2"
|
|
11
11
|
export const AGGREGATOR_V2_EXTEND = "aggregator_v2_extend"
|
|
12
12
|
|
|
13
|
-
export function getAggregatorV2PublishedAt(
|
|
13
|
+
export function getAggregatorV2PublishedAt(
|
|
14
|
+
aggregatorV2PublishedAt: string,
|
|
15
|
+
packages?: Map<string, string> | Record<string, string>
|
|
16
|
+
) {
|
|
14
17
|
if (packages instanceof Map) {
|
|
15
18
|
return packages.get(AGGREGATOR_V2) ?? aggregatorV2PublishedAt
|
|
16
19
|
}
|
|
17
20
|
return aggregatorV2PublishedAt
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
export function getAggregatorV2ExtendPublishedAt(
|
|
23
|
+
export function getAggregatorV2ExtendPublishedAt(
|
|
24
|
+
aggregatorV2ExtendPublishedAt: string,
|
|
25
|
+
packages?: Map<string, string> | Record<string, string>
|
|
26
|
+
) {
|
|
21
27
|
if (packages instanceof Map) {
|
|
22
28
|
return packages.get(AGGREGATOR_V2_EXTEND) ?? aggregatorV2ExtendPublishedAt
|
|
23
29
|
}
|
|
@@ -31,7 +37,6 @@ export interface Dex {
|
|
|
31
37
|
path: Path,
|
|
32
38
|
inputCoin: TransactionObjectArgument,
|
|
33
39
|
packages?: Map<string, string>,
|
|
34
|
-
deepbookv3DeepFee?: TransactionObjectArgument
|
|
40
|
+
deepbookv3DeepFee?: TransactionObjectArgument
|
|
35
41
|
): Promise<TransactionObjectArgument>
|
|
36
42
|
}
|
|
37
|
-
|