@cetusprotocol/aggregator-sdk 0.3.31 → 0.4.0
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/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +219 -24
- package/dist/index.mjs +218 -24
- package/dist/src/api.d.ts +4 -0
- package/dist/src/client.d.ts +3 -0
- package/dist/src/errors.d.ts +2 -1
- package/dist/src/transaction/obric.d.ts +8 -0
- package/dist/tests/router/obric.test.d.ts +2 -0
- package/dist/tests/router/scallop.test.d.ts +2 -0
- package/package.json +1 -1
- package/src/api.ts +12 -5
- package/src/client.ts +156 -2
- package/src/errors.ts +4 -1
- package/src/transaction/obric.ts +90 -0
- package/src/utils/msafe.ts +27 -17
- package/tests/router/obric.test.ts +197 -0
- package/tests/router/scallop.test.ts +127 -0
package/src/client.ts
CHANGED
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
} from "@pythnetwork/pyth-sui-js"
|
|
50
50
|
import { Steamm } from "./transaction/steamm"
|
|
51
51
|
import { Metastable } from "./transaction/metastable"
|
|
52
|
+
import { Obric } from "./transaction/obric"
|
|
52
53
|
|
|
53
54
|
export const CETUS = "CETUS"
|
|
54
55
|
export const DEEPBOOKV2 = "DEEPBOOK"
|
|
@@ -71,6 +72,7 @@ export const ALPHAFI = "ALPHAFI"
|
|
|
71
72
|
export const SPRINGSUI = "SPRINGSUI"
|
|
72
73
|
export const STEAMM = "STEAMM"
|
|
73
74
|
export const METASTABLE = "METASTABLE"
|
|
75
|
+
export const OBRIC = "OBRIC"
|
|
74
76
|
export const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2"
|
|
75
77
|
|
|
76
78
|
export type BuildRouterSwapParams = {
|
|
@@ -258,6 +260,78 @@ export class AggregatorClient {
|
|
|
258
260
|
return getRouterResult(this.endpoint, params)
|
|
259
261
|
}
|
|
260
262
|
|
|
263
|
+
async executeFlexibleInputSwap(
|
|
264
|
+
txb: Transaction,
|
|
265
|
+
inputCoin: TransactionObjectArgument,
|
|
266
|
+
routers: Router[],
|
|
267
|
+
amountOutLimit: BN,
|
|
268
|
+
pythPriceIDs: Map<string, string>,
|
|
269
|
+
partner?: string,
|
|
270
|
+
deepbookv3DeepFee?: TransactionObjectArgument,
|
|
271
|
+
packages?: Map<string, string>
|
|
272
|
+
) {
|
|
273
|
+
if (routers.length === 0) {
|
|
274
|
+
throw new Error("No router found")
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const outputCoinType = routers[0].path[routers[0].path.length - 1].target
|
|
278
|
+
const outputCoins = []
|
|
279
|
+
|
|
280
|
+
for (let i = 0; i < routers.length - 1; i++) {
|
|
281
|
+
if (routers[i].path.length === 0) {
|
|
282
|
+
throw new Error("Empty path")
|
|
283
|
+
}
|
|
284
|
+
// 为每条路径分割所需的代币
|
|
285
|
+
const splitCoin = txb.splitCoins(inputCoin, [routers[i].amountIn.toString()])
|
|
286
|
+
let nextCoin = splitCoin[0] as TransactionObjectArgument
|
|
287
|
+
|
|
288
|
+
for (const path of routers[i].path) {
|
|
289
|
+
const dex = this.newDex(path.provider, pythPriceIDs, partner)
|
|
290
|
+
nextCoin = await dex.swap(
|
|
291
|
+
this,
|
|
292
|
+
txb,
|
|
293
|
+
path,
|
|
294
|
+
nextCoin,
|
|
295
|
+
packages,
|
|
296
|
+
deepbookv3DeepFee
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
outputCoins.push(nextCoin)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// 处理最后一条路径,使用剩余的所有代币
|
|
303
|
+
if (routers[routers.length - 1].path.length === 0) {
|
|
304
|
+
throw new Error("Empty path")
|
|
305
|
+
}
|
|
306
|
+
let lastCoin = inputCoin
|
|
307
|
+
for (const path of routers[routers.length - 1].path) {
|
|
308
|
+
const dex = this.newDex(path.provider, pythPriceIDs, partner)
|
|
309
|
+
lastCoin = await dex.swap(
|
|
310
|
+
this,
|
|
311
|
+
txb,
|
|
312
|
+
path,
|
|
313
|
+
lastCoin,
|
|
314
|
+
packages,
|
|
315
|
+
deepbookv3DeepFee
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
outputCoins.push(lastCoin)
|
|
319
|
+
|
|
320
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
321
|
+
this.publishedAtV2(),
|
|
322
|
+
packages
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
const mergedTargetCoin = this.checkCoinThresholdAndMergeCoin(
|
|
326
|
+
txb,
|
|
327
|
+
outputCoins,
|
|
328
|
+
outputCoinType,
|
|
329
|
+
amountOutLimit,
|
|
330
|
+
aggregatorV2PublishedAt
|
|
331
|
+
)
|
|
332
|
+
return mergedTargetCoin
|
|
333
|
+
}
|
|
334
|
+
|
|
261
335
|
async expectInputSwap(
|
|
262
336
|
txb: Transaction,
|
|
263
337
|
inputCoin: TransactionObjectArgument,
|
|
@@ -476,6 +550,69 @@ export class AggregatorClient {
|
|
|
476
550
|
return targetCoin
|
|
477
551
|
}
|
|
478
552
|
|
|
553
|
+
async fixableRouterSwap(
|
|
554
|
+
params: BuildRouterSwapParamsV2
|
|
555
|
+
): Promise<TransactionObjectArgument> {
|
|
556
|
+
const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } =
|
|
557
|
+
params
|
|
558
|
+
|
|
559
|
+
const routerData = Array.isArray(routers) ? routers : routers.routes
|
|
560
|
+
const byAmountIn = params.routers.byAmountIn
|
|
561
|
+
|
|
562
|
+
const amountIn = routerData.reduce(
|
|
563
|
+
(acc, router) => acc.add(router.amountIn),
|
|
564
|
+
new BN(0)
|
|
565
|
+
)
|
|
566
|
+
const amountOut = routerData.reduce(
|
|
567
|
+
(acc, router) => acc.add(router.amountOut),
|
|
568
|
+
new BN(0)
|
|
569
|
+
)
|
|
570
|
+
|
|
571
|
+
const amountLimit = CalculateAmountLimitBN(
|
|
572
|
+
byAmountIn ? amountOut : amountIn,
|
|
573
|
+
byAmountIn,
|
|
574
|
+
slippage
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
const packages = isBuilderRouterSwapParams(params)
|
|
578
|
+
? undefined
|
|
579
|
+
: params.routers.packages
|
|
580
|
+
|
|
581
|
+
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
582
|
+
this.publishedAtV2(),
|
|
583
|
+
packages
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
const priceIDs = findPythPriceIDs(routerData)
|
|
587
|
+
|
|
588
|
+
const priceInfoObjectIds =
|
|
589
|
+
priceIDs.length > 0
|
|
590
|
+
? await this.updatePythPriceIDs(priceIDs, txb)
|
|
591
|
+
: new Map<string, string>()
|
|
592
|
+
|
|
593
|
+
if (byAmountIn) {
|
|
594
|
+
const targetCoin = await this.executeFlexibleInputSwap(
|
|
595
|
+
txb,
|
|
596
|
+
inputCoin,
|
|
597
|
+
routerData,
|
|
598
|
+
amountLimit,
|
|
599
|
+
priceInfoObjectIds,
|
|
600
|
+
partner,
|
|
601
|
+
deepbookv3DeepFee,
|
|
602
|
+
packages
|
|
603
|
+
)
|
|
604
|
+
return targetCoin
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const targetCoin = await this.expectOutputSwap(
|
|
608
|
+
txb,
|
|
609
|
+
inputCoin,
|
|
610
|
+
routerData,
|
|
611
|
+
partner
|
|
612
|
+
)
|
|
613
|
+
return targetCoin
|
|
614
|
+
}
|
|
615
|
+
|
|
479
616
|
// auto build input coin
|
|
480
617
|
// auto merge, transfer or destory target coin.
|
|
481
618
|
async fastRouterSwap(
|
|
@@ -610,7 +747,9 @@ export class AggregatorClient {
|
|
|
610
747
|
// return "0x347dd58bbd11cd82c8b386b344729717c04a998da73386e82a239cc196d5706b" // version 7
|
|
611
748
|
// return "0xf2fcea41dc217385019828375764fa06d9bd25e8e4726ba1962680849fb8d613" // version 8
|
|
612
749
|
// return "0xa2d8a4279d69d8fec04b2fea8852d0d467d3cc0d39c5890180d439ae7a9953ed" // version 9
|
|
613
|
-
return "0x34ef25b60b51f9d07cd9b7dc5b08dfdf26c7b0ff00c57bb17454c161fa6b6b83" // version 10
|
|
750
|
+
// return "0x34ef25b60b51f9d07cd9b7dc5b08dfdf26c7b0ff00c57bb17454c161fa6b6b83" // version 10
|
|
751
|
+
// return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc" // version 11
|
|
752
|
+
return "0x200e762fa2c49f3dc150813038fbf22fd4f894ac6f23ebe1085c62f2ef97f1ca" // version 12
|
|
614
753
|
} else {
|
|
615
754
|
return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78"
|
|
616
755
|
}
|
|
@@ -711,6 +850,8 @@ export class AggregatorClient {
|
|
|
711
850
|
return new Steamm(this.env)
|
|
712
851
|
case METASTABLE:
|
|
713
852
|
return new Metastable(this.env, pythPriceIDs)
|
|
853
|
+
case OBRIC:
|
|
854
|
+
return new Obric(this.env, pythPriceIDs)
|
|
714
855
|
default:
|
|
715
856
|
throw new Error(`Unsupported dex ${provider}`)
|
|
716
857
|
}
|
|
@@ -821,6 +962,14 @@ export function findPythPriceIDs(routes: Router[]): string[] {
|
|
|
821
962
|
priceIDs.add(path.extendedDetails.metastableETHPriceSeed)
|
|
822
963
|
}
|
|
823
964
|
}
|
|
965
|
+
if (path.provider === OBRIC) {
|
|
966
|
+
if (path.extendedDetails && path.extendedDetails.obricCoinAPriceSeed) {
|
|
967
|
+
priceIDs.add(path.extendedDetails.obricCoinAPriceSeed)
|
|
968
|
+
}
|
|
969
|
+
if (path.extendedDetails && path.extendedDetails.obricCoinBPriceSeed) {
|
|
970
|
+
priceIDs.add(path.extendedDetails.obricCoinBPriceSeed)
|
|
971
|
+
}
|
|
972
|
+
}
|
|
824
973
|
}
|
|
825
974
|
}
|
|
826
975
|
return Array.from(priceIDs)
|
|
@@ -870,7 +1019,8 @@ export function parseRouterResponse(
|
|
|
870
1019
|
path.provider === SCALLOP ||
|
|
871
1020
|
path.provider === HAEDALPMM ||
|
|
872
1021
|
path.provider === STEAMM ||
|
|
873
|
-
path.provider === METASTABLE
|
|
1022
|
+
path.provider === METASTABLE ||
|
|
1023
|
+
path.provider === OBRIC
|
|
874
1024
|
) {
|
|
875
1025
|
extendedDetails = {
|
|
876
1026
|
aftermathLpSupplyType:
|
|
@@ -898,6 +1048,10 @@ export function parseRouterResponse(
|
|
|
898
1048
|
metastableCreateCapModule: path.extended_details?.metastable_create_cap_module,
|
|
899
1049
|
metastableCreateCapAllTypeParams: path.extended_details?.metastable_create_cap_all_type_params,
|
|
900
1050
|
metastableRegistryId: path.extended_details?.metastable_registry_id,
|
|
1051
|
+
obricCoinAPriceSeed: path.extended_details?.obric_coin_a_price_seed,
|
|
1052
|
+
obricCoinBPriceSeed: path.extended_details?.obric_coin_b_price_seed,
|
|
1053
|
+
obricCoinAPriceId: path.extended_details?.obric_coin_a_price_id,
|
|
1054
|
+
obricCoinBPriceId: path.extended_details?.obric_coin_b_price_id,
|
|
901
1055
|
}
|
|
902
1056
|
}
|
|
903
1057
|
|
package/src/errors.ts
CHANGED
|
@@ -51,7 +51,8 @@ export enum AggregatorServerErrorCode {
|
|
|
51
51
|
NumberTooLarge = 10001,
|
|
52
52
|
NoRouter = 10002,
|
|
53
53
|
InsufficientLiquidity = 10003,
|
|
54
|
-
HoneyPot = 10004
|
|
54
|
+
HoneyPot = 10004,
|
|
55
|
+
RateLimitExceeded = 10005,
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
export function getAggregatorServerErrorMessage(
|
|
@@ -68,6 +69,8 @@ export function getAggregatorServerErrorMessage(
|
|
|
68
69
|
return "Insufficient Liquidity"
|
|
69
70
|
case AggregatorServerErrorCode.HoneyPot:
|
|
70
71
|
return "Target token is detected as a HoneyPot scam"
|
|
72
|
+
case AggregatorServerErrorCode.RateLimitExceeded:
|
|
73
|
+
return "Too many requests. Please try again later"
|
|
71
74
|
default:
|
|
72
75
|
return "Unknown error"
|
|
73
76
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Transaction,
|
|
3
|
+
TransactionArgument,
|
|
4
|
+
TransactionObjectArgument,
|
|
5
|
+
} from "@mysten/sui/transactions"
|
|
6
|
+
import {
|
|
7
|
+
AggregatorClient,
|
|
8
|
+
CLOCK_ADDRESS,
|
|
9
|
+
Dex,
|
|
10
|
+
Env,
|
|
11
|
+
getAggregatorV2ExtendPublishedAt,
|
|
12
|
+
Path,
|
|
13
|
+
} from ".."
|
|
14
|
+
|
|
15
|
+
export class Obric implements Dex {
|
|
16
|
+
private pythPriceIDs: Map<string, string>
|
|
17
|
+
private pythStateObjectId: string
|
|
18
|
+
|
|
19
|
+
constructor(env: Env, pythPriceIDs: Map<string, string>) {
|
|
20
|
+
if (env === Env.Testnet) {
|
|
21
|
+
throw new Error("Obric is not supported on testnet")
|
|
22
|
+
}
|
|
23
|
+
this.pythPriceIDs = pythPriceIDs
|
|
24
|
+
this.pythStateObjectId = "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8"
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async swap(
|
|
28
|
+
client: AggregatorClient,
|
|
29
|
+
txb: Transaction,
|
|
30
|
+
path: Path,
|
|
31
|
+
inputCoin: TransactionObjectArgument,
|
|
32
|
+
packages?: Map<string, string>
|
|
33
|
+
): Promise<TransactionObjectArgument> {
|
|
34
|
+
const { direction, from, target } = path
|
|
35
|
+
const [func, coinAType, coinBType] = direction
|
|
36
|
+
? ["swap_a2b", from, target]
|
|
37
|
+
: ["swap_b2a", target, from]
|
|
38
|
+
|
|
39
|
+
let coinAPriceSeed
|
|
40
|
+
let coinBPriceSeed
|
|
41
|
+
|
|
42
|
+
let coinAPriceInfoObjectId
|
|
43
|
+
let coinBPriceInfoObjectId
|
|
44
|
+
|
|
45
|
+
if (path.extendedDetails == null) {
|
|
46
|
+
throw new Error("Extended details not supported in obric")
|
|
47
|
+
} else {
|
|
48
|
+
if (
|
|
49
|
+
path.extendedDetails.obricCoinAPriceSeed && path.extendedDetails.obricCoinBPriceSeed
|
|
50
|
+
) {
|
|
51
|
+
coinAPriceSeed = path.extendedDetails.obricCoinAPriceSeed
|
|
52
|
+
coinAPriceInfoObjectId = this.pythPriceIDs.get(coinAPriceSeed!)
|
|
53
|
+
coinBPriceSeed = path.extendedDetails.obricCoinBPriceSeed
|
|
54
|
+
coinBPriceInfoObjectId = this.pythPriceIDs.get(coinBPriceSeed!)
|
|
55
|
+
} else {
|
|
56
|
+
if (!path.extendedDetails.obricCoinAPriceId || !path.extendedDetails.obricCoinBPriceId) {
|
|
57
|
+
throw new Error("Base price id or quote price id not supported")
|
|
58
|
+
} else {
|
|
59
|
+
coinAPriceInfoObjectId = path.extendedDetails.obricCoinAPriceId
|
|
60
|
+
coinBPriceInfoObjectId = path.extendedDetails.obricCoinBPriceId
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!coinAPriceInfoObjectId || !coinBPriceInfoObjectId) {
|
|
66
|
+
throw new Error(
|
|
67
|
+
"Base price info object id or quote price info object id not found"
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const args = [
|
|
72
|
+
txb.object(path.id),
|
|
73
|
+
inputCoin,
|
|
74
|
+
txb.object(this.pythStateObjectId),
|
|
75
|
+
txb.object(coinAPriceInfoObjectId),
|
|
76
|
+
txb.object(coinBPriceInfoObjectId),
|
|
77
|
+
txb.object(CLOCK_ADDRESS),
|
|
78
|
+
]
|
|
79
|
+
const publishedAt = getAggregatorV2ExtendPublishedAt(
|
|
80
|
+
client.publishedAtV2Extend(),
|
|
81
|
+
packages
|
|
82
|
+
)
|
|
83
|
+
const res = txb.moveCall({
|
|
84
|
+
target: `${publishedAt}::obric::${func}`,
|
|
85
|
+
typeArguments: [coinAType, coinBType],
|
|
86
|
+
arguments: args,
|
|
87
|
+
}) as TransactionArgument
|
|
88
|
+
return res
|
|
89
|
+
}
|
|
90
|
+
}
|
package/src/utils/msafe.ts
CHANGED
|
@@ -3,28 +3,38 @@ import BN from 'bn.js'
|
|
|
3
3
|
import Decimal from "decimal.js"
|
|
4
4
|
|
|
5
5
|
export const dealWithFastRouterSwapParamsForMsafe = (data: any) => {
|
|
6
|
-
const result =
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
const result = {
|
|
7
|
+
...data,
|
|
8
|
+
amountIn: data?.amountIn?.toString(),
|
|
9
|
+
amountOut: data?.amountIn?.toString(),
|
|
10
|
+
routes: data?.routes?.map((item:any) => {
|
|
11
|
+
return {
|
|
12
|
+
...item,
|
|
13
|
+
amountIn: item?.amountIn?.toString(),
|
|
14
|
+
amountOut: item?.amountOut?.toString(),
|
|
15
|
+
initialPrice: item?.initialPrice?.toString()
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
}
|
|
14
19
|
|
|
15
20
|
return result
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
|
|
19
24
|
export const restituteMsafeFastRouterSwapParams = (data: any) => {
|
|
20
|
-
const result =
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
const result = {
|
|
26
|
+
...data,
|
|
27
|
+
amountIn: new BN(data?.amountIn),
|
|
28
|
+
amountOut: new BN(data?.amountIn),
|
|
29
|
+
routes: data?.routes?.map((item:any) => {
|
|
30
|
+
return {
|
|
31
|
+
...item,
|
|
32
|
+
amountIn: new BN(item?.amountIn),
|
|
33
|
+
amountOut: new BN(item?.amountOut),
|
|
34
|
+
initialPrice: new Decimal(item?.initialPrice?.toString())
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
}
|
|
28
38
|
|
|
29
39
|
return result
|
|
30
|
-
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { describe, test } from "@jest/globals"
|
|
2
|
+
import dotenv from "dotenv"
|
|
3
|
+
import { AggregatorClient } from "~/client"
|
|
4
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
|
|
5
|
+
import { printTransaction } from "~/utils/transaction"
|
|
6
|
+
import BN from "bn.js"
|
|
7
|
+
import { fromB64 } from "@mysten/sui/utils"
|
|
8
|
+
import { SuiClient } from "@mysten/sui/client"
|
|
9
|
+
import { Env } from "~/index"
|
|
10
|
+
import { Transaction } from "@mysten/sui/transactions"
|
|
11
|
+
|
|
12
|
+
dotenv.config()
|
|
13
|
+
|
|
14
|
+
export function buildTestAccount(): Ed25519Keypair {
|
|
15
|
+
const mnemonics = process.env.SUI_WALLET_MNEMONICS || ""
|
|
16
|
+
const testAccountObject = Ed25519Keypair.deriveKeypair(mnemonics)
|
|
17
|
+
return testAccountObject
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
describe("Test obric provider", () => {
|
|
21
|
+
let client: AggregatorClient
|
|
22
|
+
let keypair: Ed25519Keypair
|
|
23
|
+
|
|
24
|
+
const T_SUI = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
|
|
25
|
+
const WH_USDC = "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN"
|
|
26
|
+
const T_USDC = "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
|
|
27
|
+
|
|
28
|
+
beforeAll(() => {
|
|
29
|
+
const fullNodeURL = process.env.SUI_RPC!
|
|
30
|
+
const aggregatorURL = process.env.CETUS_AGGREGATOR!
|
|
31
|
+
const secret = process.env.SUI_WALLET_SECRET!
|
|
32
|
+
|
|
33
|
+
if (secret) {
|
|
34
|
+
keypair = Ed25519Keypair.fromSecretKey(fromB64(secret).slice(1, 33))
|
|
35
|
+
} else {
|
|
36
|
+
keypair = buildTestAccount()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// const wallet = keypair.getPublicKey().toSuiAddress()
|
|
40
|
+
|
|
41
|
+
const wallet = "0x935029ca5219502a47ac9b69f556ccf6e2198b5e7815cf50f68846f723739cbd" // has 80 eth
|
|
42
|
+
console.log("wallet: ", wallet)
|
|
43
|
+
|
|
44
|
+
const endpoint = aggregatorURL
|
|
45
|
+
|
|
46
|
+
const suiClient = new SuiClient({
|
|
47
|
+
url: fullNodeURL,
|
|
48
|
+
})
|
|
49
|
+
client = new AggregatorClient(endpoint, wallet, suiClient, Env.Mainnet)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
test("Find Routers --> SUI -> USDC, locked", async () => {
|
|
53
|
+
// const amounts = ["1000", "1000000", "100000000", "5000000000", "10000000000000"]
|
|
54
|
+
const amounts = ["9990", "5000000000"]
|
|
55
|
+
|
|
56
|
+
for (const amount of amounts) {
|
|
57
|
+
const res = await client.findRouters({
|
|
58
|
+
from: T_SUI,
|
|
59
|
+
target: WH_USDC,
|
|
60
|
+
amount: new BN(amount),
|
|
61
|
+
byAmountIn: true,
|
|
62
|
+
depth: 3,
|
|
63
|
+
splitCount: 1,
|
|
64
|
+
providers: ["OBRIC"],
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
if (res != null) {
|
|
68
|
+
console.log(JSON.stringify(res, null, 2))
|
|
69
|
+
}
|
|
70
|
+
console.log("amount in", res?.amountIn.toString())
|
|
71
|
+
console.log("amount out", res?.amountOut.toString())
|
|
72
|
+
|
|
73
|
+
const txb = new Transaction()
|
|
74
|
+
|
|
75
|
+
if (res != null) {
|
|
76
|
+
console.log(JSON.stringify(res, null, 2))
|
|
77
|
+
await client.fastRouterSwap({
|
|
78
|
+
routers: res,
|
|
79
|
+
txb,
|
|
80
|
+
slippage: 0.01,
|
|
81
|
+
refreshAllCoins: true,
|
|
82
|
+
payDeepFeeAmount: 0,
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
txb.setSender(client.signer)
|
|
86
|
+
const buildTxb = await txb.build({ client: client.client })
|
|
87
|
+
// const buildTxb = await txb.getData()
|
|
88
|
+
|
|
89
|
+
console.log("buildTxb", buildTxb)
|
|
90
|
+
printTransaction(txb)
|
|
91
|
+
|
|
92
|
+
let result = await client.devInspectTransactionBlock(txb)
|
|
93
|
+
console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
|
|
94
|
+
for (const event of result.events) {
|
|
95
|
+
console.log("event", JSON.stringify(event, null, 2))
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}, 50000)
|
|
100
|
+
|
|
101
|
+
test("Find Routers --> WUSDC --> SUI, no pyth mode", async () => {
|
|
102
|
+
// const amounts = ["1000", "1000000", "100000000", "5000000000", "10000000000000"]
|
|
103
|
+
// const amounts = ["1000", "1000000", "900000000"]
|
|
104
|
+
const amounts = ["90000000"]
|
|
105
|
+
|
|
106
|
+
for (const amount of amounts) {
|
|
107
|
+
const res = await client.findRouters({
|
|
108
|
+
from: T_USDC,
|
|
109
|
+
target: T_SUI,
|
|
110
|
+
amount: new BN(amount),
|
|
111
|
+
byAmountIn: true,
|
|
112
|
+
depth: 3,
|
|
113
|
+
splitCount: 1,
|
|
114
|
+
providers: ["OBRIC"],
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
if (res != null) {
|
|
118
|
+
console.log(JSON.stringify(res, null, 2))
|
|
119
|
+
}
|
|
120
|
+
console.log("amount in", res?.amountIn.toString())
|
|
121
|
+
console.log("amount out", res?.amountOut.toString())
|
|
122
|
+
|
|
123
|
+
const txb = new Transaction()
|
|
124
|
+
|
|
125
|
+
if (res != null) {
|
|
126
|
+
await client.fastRouterSwap({
|
|
127
|
+
routers: res,
|
|
128
|
+
txb,
|
|
129
|
+
slippage: 0.001,
|
|
130
|
+
refreshAllCoins: true,
|
|
131
|
+
payDeepFeeAmount: 0,
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
txb.setSender(client.signer)
|
|
135
|
+
const buildTxb = await txb.build({ client: client.client })
|
|
136
|
+
// const buildTxb = await txb.getData()
|
|
137
|
+
|
|
138
|
+
// printTransaction(txb)
|
|
139
|
+
|
|
140
|
+
let result = await client.devInspectTransactionBlock(txb)
|
|
141
|
+
console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
|
|
142
|
+
for (const event of result.events) {
|
|
143
|
+
console.log("event", JSON.stringify(event, null, 2))
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
test("Build Router TX", async () => {
|
|
150
|
+
const amount = "1000000"
|
|
151
|
+
|
|
152
|
+
const res = await client.findRouters({
|
|
153
|
+
from: T_USDC,
|
|
154
|
+
target: T_SUI,
|
|
155
|
+
amount: new BN(amount),
|
|
156
|
+
byAmountIn: true,
|
|
157
|
+
depth: 3,
|
|
158
|
+
providers: ["OBRIC"],
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
console.log("amount in", res?.amountIn.toString())
|
|
162
|
+
console.log("amount out", res?.amountOut.toString())
|
|
163
|
+
|
|
164
|
+
const txb = new Transaction()
|
|
165
|
+
|
|
166
|
+
if (res != null) {
|
|
167
|
+
console.log(JSON.stringify(res, null, 2))
|
|
168
|
+
await client.fastRouterSwap({
|
|
169
|
+
routers: res,
|
|
170
|
+
txb,
|
|
171
|
+
slippage: 0.01,
|
|
172
|
+
refreshAllCoins: true,
|
|
173
|
+
payDeepFeeAmount: 0,
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
txb.setSender(client.signer)
|
|
177
|
+
const buildTxb = await txb.build({ client: client.client })
|
|
178
|
+
// const buildTxb = await txb.getData()
|
|
179
|
+
|
|
180
|
+
console.log("buildTxb", buildTxb)
|
|
181
|
+
// printTransaction(txb)
|
|
182
|
+
|
|
183
|
+
let result = await client.devInspectTransactionBlock(txb)
|
|
184
|
+
console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
|
|
185
|
+
for (const event of result.events) {
|
|
186
|
+
console.log("event", JSON.stringify(event, null, 2))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// if (result.effects.status.status === "success") {
|
|
190
|
+
// const result = await client.signAndExecuteTransaction(txb, keypair)
|
|
191
|
+
// console.log("result", result)
|
|
192
|
+
// } else {
|
|
193
|
+
// console.log("result", result)
|
|
194
|
+
// }
|
|
195
|
+
}
|
|
196
|
+
}, 600000)
|
|
197
|
+
})
|