@cetusprotocol/aggregator-sdk 0.0.0-experimental-20240719182939
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/.env.example +4 -0
- package/README.md +0 -0
- package/bun.lockb +0 -0
- package/dist/index.d.mts +267 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.js +6824 -0
- package/dist/index.mjs +6745 -0
- package/dist/src/client.d.ts +88 -0
- package/dist/src/config.d.ts +26 -0
- package/dist/src/const.d.ts +75 -0
- package/dist/src/errors.d.ts +31 -0
- package/dist/src/index.d.ts +5 -0
- package/dist/src/math.d.ts +5 -0
- package/dist/src/test_data.test.d.ts +8 -0
- package/dist/src/transaction/aftermath.d.ts +24 -0
- package/dist/src/transaction/cetus.d.ts +39 -0
- package/dist/src/transaction/common.d.ts +12 -0
- package/dist/src/transaction/deepbook.d.ts +21 -0
- package/dist/src/transaction/flowx.d.ts +20 -0
- package/dist/src/transaction/index.d.ts +1 -0
- package/dist/src/transaction/kriya.d.ts +21 -0
- package/dist/src/transaction/router.d.ts +6 -0
- package/dist/src/transaction/swap.d.ts +5 -0
- package/dist/src/transaction/turbos.d.ts +22 -0
- package/dist/src/types/CoinAssist.d.ts +122 -0
- package/dist/src/types/sui.d.ts +112 -0
- package/dist/src/utils/account_cap.d.ts +7 -0
- package/dist/src/utils/coin.d.ts +4 -0
- package/dist/src/utils/coin.spec.d.ts +1 -0
- package/dist/src/utils/contracts.d.ts +16 -0
- package/dist/src/utils/index.d.ts +1 -0
- package/dist/src/utils/transaction.d.ts +3 -0
- package/dist/tests/router.test.d.ts +2 -0
- package/dist/tests/wallet.test.d.ts +1 -0
- package/jest.config.mjs +13 -0
- package/package.json +41 -0
- package/src/client.ts +393 -0
- package/src/config.ts +65 -0
- package/src/const.ts +126 -0
- package/src/errors.ts +44 -0
- package/src/index.ts +5 -0
- package/src/math.ts +37 -0
- package/src/test_data.test.ts +17 -0
- package/src/transaction/aftermath.ts +142 -0
- package/src/transaction/cetus.ts +281 -0
- package/src/transaction/common.ts +169 -0
- package/src/transaction/deepbook.ts +126 -0
- package/src/transaction/flowx.ts +97 -0
- package/src/transaction/index.ts +1 -0
- package/src/transaction/kriya.ts +77 -0
- package/src/transaction/router.ts +341 -0
- package/src/transaction/swap.ts +164 -0
- package/src/transaction/turbos.ts +114 -0
- package/src/types/CoinAssist.ts +217 -0
- package/src/types/sui.ts +148 -0
- package/src/utils/account_cap.ts +62 -0
- package/src/utils/coin.spec.ts +10 -0
- package/src/utils/coin.ts +61 -0
- package/src/utils/contracts.ts +136 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/transaction.ts +20 -0
- package/tests/router.test.ts +255 -0
- package/tests/wallet.test.ts +21 -0
- package/tsconfig.json +22 -0
- package/tsup.config.ts +23 -0
- package/version.mjs +28 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransactionArgument,
|
|
3
|
+
Transaction,
|
|
4
|
+
TransactionObjectArgument,
|
|
5
|
+
} from "@mysten/sui/transactions"
|
|
6
|
+
import { AggregatorConfig } from "../config"
|
|
7
|
+
import {
|
|
8
|
+
AGGREGATOR,
|
|
9
|
+
CLOCK_ADDRESS,
|
|
10
|
+
DEEPBOOK_MODULE,
|
|
11
|
+
SWAP_A2B_FUNC,
|
|
12
|
+
SWAP_B2A_FUNC,
|
|
13
|
+
TRANSFER_ACCOUNT_CAP,
|
|
14
|
+
} from "../const"
|
|
15
|
+
import { ConfigErrorCode, TransactionErrorCode } from "../errors"
|
|
16
|
+
import { createTarget } from "../utils"
|
|
17
|
+
import { getOrCreateAccountCap } from "../utils/account_cap"
|
|
18
|
+
import { SuiClient } from "@mysten/sui/client"
|
|
19
|
+
|
|
20
|
+
export type DeepbookSwapParams = {
|
|
21
|
+
poolId: string
|
|
22
|
+
a2b: boolean
|
|
23
|
+
amount: TransactionArgument
|
|
24
|
+
amountLimit: number
|
|
25
|
+
coinA?: TransactionObjectArgument
|
|
26
|
+
coinB?: TransactionObjectArgument
|
|
27
|
+
useFullInputCoinAmount: boolean
|
|
28
|
+
coinAType: string
|
|
29
|
+
coinBType: string
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export type DeepbookSwapResult = {
|
|
33
|
+
targetCoin: TransactionObjectArgument
|
|
34
|
+
amountIn: TransactionArgument
|
|
35
|
+
amountOut: TransactionArgument
|
|
36
|
+
txb: Transaction
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export async function deepbookSwapMovecall(
|
|
40
|
+
swapParams: DeepbookSwapParams,
|
|
41
|
+
client: SuiClient,
|
|
42
|
+
txb: Transaction,
|
|
43
|
+
config: AggregatorConfig
|
|
44
|
+
): Promise<DeepbookSwapResult> {
|
|
45
|
+
const accountCapRes = await getOrCreateAccountCap(
|
|
46
|
+
txb,
|
|
47
|
+
client,
|
|
48
|
+
config.getWallet()
|
|
49
|
+
)
|
|
50
|
+
const accountCap = accountCapRes.accountCap
|
|
51
|
+
|
|
52
|
+
const aggregatorPackage = config.getPackage(AGGREGATOR)
|
|
53
|
+
if (aggregatorPackage == null) {
|
|
54
|
+
throw new AggregateError(
|
|
55
|
+
"Aggregator package not set",
|
|
56
|
+
ConfigErrorCode.MissAggregatorPackage
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
const aggregatorPublishedAt = aggregatorPackage.publishedAt
|
|
60
|
+
|
|
61
|
+
if (swapParams.a2b) {
|
|
62
|
+
if (swapParams.coinA == null) {
|
|
63
|
+
throw new AggregateError(
|
|
64
|
+
"coinA is required",
|
|
65
|
+
TransactionErrorCode.MissCoinA
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
} else {
|
|
69
|
+
if (swapParams.coinB == null) {
|
|
70
|
+
throw new AggregateError(
|
|
71
|
+
"coinB is required",
|
|
72
|
+
TransactionErrorCode.MissCoinB
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const args = swapParams.a2b
|
|
78
|
+
? [
|
|
79
|
+
txb.object(swapParams.poolId),
|
|
80
|
+
swapParams.amount,
|
|
81
|
+
txb.pure.u64(swapParams.amountLimit),
|
|
82
|
+
swapParams.coinA!,
|
|
83
|
+
accountCap,
|
|
84
|
+
txb.pure.bool(swapParams.useFullInputCoinAmount),
|
|
85
|
+
txb.object(CLOCK_ADDRESS),
|
|
86
|
+
]
|
|
87
|
+
: [
|
|
88
|
+
txb.object(swapParams.poolId),
|
|
89
|
+
swapParams.amount,
|
|
90
|
+
txb.pure.u64(swapParams.amountLimit),
|
|
91
|
+
swapParams.coinB!,
|
|
92
|
+
accountCap,
|
|
93
|
+
txb.pure.bool(swapParams.useFullInputCoinAmount),
|
|
94
|
+
txb.object(CLOCK_ADDRESS),
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
let func = swapParams.a2b ? SWAP_A2B_FUNC : SWAP_B2A_FUNC
|
|
98
|
+
const target = createTarget(aggregatorPublishedAt, DEEPBOOK_MODULE, func)
|
|
99
|
+
|
|
100
|
+
const res = txb.moveCall({
|
|
101
|
+
target,
|
|
102
|
+
typeArguments: [swapParams.coinAType, swapParams.coinBType],
|
|
103
|
+
arguments: args,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
if (accountCapRes.isCreate) {
|
|
107
|
+
const target = createTarget(
|
|
108
|
+
aggregatorPublishedAt,
|
|
109
|
+
DEEPBOOK_MODULE,
|
|
110
|
+
TRANSFER_ACCOUNT_CAP
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
const res = txb.moveCall({
|
|
114
|
+
target,
|
|
115
|
+
typeArguments: [],
|
|
116
|
+
arguments: [accountCap],
|
|
117
|
+
})
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
targetCoin: res[0],
|
|
122
|
+
amountIn: res[1],
|
|
123
|
+
amountOut: res[2],
|
|
124
|
+
txb,
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransactionArgument,
|
|
3
|
+
Transaction,
|
|
4
|
+
TransactionObjectArgument,
|
|
5
|
+
} from "@mysten/sui/transactions"
|
|
6
|
+
import { AggregatorConfig, ENV } from "../config"
|
|
7
|
+
import {
|
|
8
|
+
AGGREGATOR,
|
|
9
|
+
FLOWX_AMM_MODULE,
|
|
10
|
+
MAINNET_FLOWX_AMM_CONTAINER_ID,
|
|
11
|
+
SWAP_A2B_FUNC,
|
|
12
|
+
SWAP_B2A_FUNC,
|
|
13
|
+
TESTNET_FLOWX_AMM_CONTAINER_ID,
|
|
14
|
+
} from "../const"
|
|
15
|
+
import { ConfigErrorCode, TransactionErrorCode } from "../errors"
|
|
16
|
+
import { createTarget } from "../utils"
|
|
17
|
+
|
|
18
|
+
export type FlowxSwapParams = {
|
|
19
|
+
amount: TransactionArgument
|
|
20
|
+
amountLimit: number
|
|
21
|
+
a2b: boolean
|
|
22
|
+
byAmountIn: boolean
|
|
23
|
+
coinA?: TransactionObjectArgument
|
|
24
|
+
coinB?: TransactionObjectArgument
|
|
25
|
+
useFullInputCoinAmount: boolean
|
|
26
|
+
coinAType: string
|
|
27
|
+
coinBType: string
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type FlowxSwapResult = {
|
|
31
|
+
targetCoin: TransactionObjectArgument
|
|
32
|
+
amountIn: TransactionArgument
|
|
33
|
+
amountOut: TransactionArgument
|
|
34
|
+
txb: Transaction
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function flowxAmmSwapMovecall(
|
|
38
|
+
swapParams: FlowxSwapParams,
|
|
39
|
+
txb: Transaction,
|
|
40
|
+
config: AggregatorConfig
|
|
41
|
+
): Promise<FlowxSwapResult> {
|
|
42
|
+
const aggregatorPackage = config.getPackage(AGGREGATOR)
|
|
43
|
+
if (aggregatorPackage == null) {
|
|
44
|
+
throw new AggregateError(
|
|
45
|
+
"Aggregator package not set",
|
|
46
|
+
ConfigErrorCode.MissAggregatorPackage
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
const aggregatorPublishedAt = aggregatorPackage.publishedAt
|
|
50
|
+
|
|
51
|
+
if (swapParams.a2b) {
|
|
52
|
+
if (swapParams.coinA == null) {
|
|
53
|
+
throw new AggregateError(
|
|
54
|
+
"coinA is required",
|
|
55
|
+
TransactionErrorCode.MissCoinA
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
} else {
|
|
59
|
+
if (swapParams.coinB == null) {
|
|
60
|
+
throw new AggregateError(
|
|
61
|
+
"coinB is required",
|
|
62
|
+
TransactionErrorCode.MissCoinB
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const containerID =
|
|
68
|
+
config.getENV() === ENV.MAINNET
|
|
69
|
+
? MAINNET_FLOWX_AMM_CONTAINER_ID
|
|
70
|
+
: TESTNET_FLOWX_AMM_CONTAINER_ID
|
|
71
|
+
|
|
72
|
+
const swapCoin = swapParams.a2b ? swapParams.coinA! : swapParams.coinB!
|
|
73
|
+
|
|
74
|
+
const args = [
|
|
75
|
+
txb.object(containerID),
|
|
76
|
+
swapParams.amount,
|
|
77
|
+
txb.pure.u64(swapParams.amountLimit),
|
|
78
|
+
swapCoin,
|
|
79
|
+
txb.pure.bool(swapParams.useFullInputCoinAmount),
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
const func = swapParams.a2b ? SWAP_A2B_FUNC : SWAP_B2A_FUNC
|
|
83
|
+
|
|
84
|
+
const target = createTarget(aggregatorPublishedAt, FLOWX_AMM_MODULE, func)
|
|
85
|
+
|
|
86
|
+
const res = txb.moveCall({
|
|
87
|
+
target,
|
|
88
|
+
typeArguments: [swapParams.coinAType, swapParams.coinBType],
|
|
89
|
+
arguments: args,
|
|
90
|
+
})
|
|
91
|
+
return {
|
|
92
|
+
targetCoin: res[0],
|
|
93
|
+
amountIn: res[1],
|
|
94
|
+
amountOut: res[2],
|
|
95
|
+
txb,
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./router"
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { TransactionArgument, Transaction, TransactionObjectArgument } from "@mysten/sui/transactions"
|
|
2
|
+
import { AggregatorConfig } from "../config"
|
|
3
|
+
import { AGGREGATOR, KRIYA_MODULE, SWAP_A2B_FUNC, SWAP_B2A_FUNC } from "../const"
|
|
4
|
+
import { ConfigErrorCode, TransactionErrorCode } from "../errors"
|
|
5
|
+
import { createTarget } from "../utils"
|
|
6
|
+
|
|
7
|
+
export type KriyaSwapParams = {
|
|
8
|
+
poolId: string
|
|
9
|
+
amount: TransactionArgument
|
|
10
|
+
amountLimit: number
|
|
11
|
+
a2b: boolean
|
|
12
|
+
byAmountIn: boolean
|
|
13
|
+
coinA?: TransactionObjectArgument
|
|
14
|
+
coinB?: TransactionObjectArgument
|
|
15
|
+
useFullInputCoinAmount: boolean
|
|
16
|
+
coinAType: string
|
|
17
|
+
coinBType: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type KriyaSwapResult = {
|
|
21
|
+
targetCoin: TransactionObjectArgument
|
|
22
|
+
amountIn: TransactionArgument
|
|
23
|
+
amountOut: TransactionArgument
|
|
24
|
+
txb: Transaction
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function kriyaSwapMovecall(
|
|
28
|
+
swapParams: KriyaSwapParams,
|
|
29
|
+
txb: Transaction,
|
|
30
|
+
config: AggregatorConfig,
|
|
31
|
+
): Promise<KriyaSwapResult> {
|
|
32
|
+
const aggregatorPackage = config.getPackage(AGGREGATOR)
|
|
33
|
+
if (aggregatorPackage == null) {
|
|
34
|
+
throw new AggregateError("Aggregator package not set", ConfigErrorCode.MissAggregatorPackage)
|
|
35
|
+
}
|
|
36
|
+
const aggregatorPublishedAt = aggregatorPackage.publishedAt
|
|
37
|
+
|
|
38
|
+
if (swapParams.a2b) {
|
|
39
|
+
if (swapParams.coinA == null) {
|
|
40
|
+
throw new AggregateError("coinA is required", TransactionErrorCode.MissCoinA)
|
|
41
|
+
}
|
|
42
|
+
} else {
|
|
43
|
+
if (swapParams.coinB == null) {
|
|
44
|
+
throw new AggregateError("coinB is required", TransactionErrorCode.MissCoinB)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const args = swapParams.a2b ? [
|
|
49
|
+
txb.object(swapParams.poolId),
|
|
50
|
+
swapParams.amount,
|
|
51
|
+
txb.pure.u64(swapParams.amountLimit),
|
|
52
|
+
swapParams.coinA!,
|
|
53
|
+
txb.pure.bool(swapParams.useFullInputCoinAmount)
|
|
54
|
+
] : [
|
|
55
|
+
txb.object(swapParams.poolId),
|
|
56
|
+
swapParams.amount,
|
|
57
|
+
txb.pure.u64(swapParams.amountLimit),
|
|
58
|
+
swapParams.coinB!,
|
|
59
|
+
txb.pure.bool(swapParams.useFullInputCoinAmount)
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
const func = swapParams.a2b ? SWAP_A2B_FUNC : SWAP_B2A_FUNC
|
|
63
|
+
|
|
64
|
+
const target = createTarget(aggregatorPublishedAt, KRIYA_MODULE, func)
|
|
65
|
+
|
|
66
|
+
const res = txb.moveCall({
|
|
67
|
+
target,
|
|
68
|
+
typeArguments: [swapParams.coinAType, swapParams.coinBType],
|
|
69
|
+
arguments: args,
|
|
70
|
+
})
|
|
71
|
+
return {
|
|
72
|
+
targetCoin: res[0],
|
|
73
|
+
amountIn: res[1],
|
|
74
|
+
amountOut: res[2],
|
|
75
|
+
txb
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
import {
|
|
2
|
+
TransactionArgument,
|
|
3
|
+
Transaction,
|
|
4
|
+
TransactionObjectArgument,
|
|
5
|
+
} from "@mysten/sui/transactions"
|
|
6
|
+
import type { BuildRouterSwapParams } from "../client"
|
|
7
|
+
import { AggregatorConfig } from "../config"
|
|
8
|
+
import {
|
|
9
|
+
AFTERMATH_AMM,
|
|
10
|
+
CETUS_DEX,
|
|
11
|
+
DEEPBOOK_DEX,
|
|
12
|
+
FLOWX_AMM,
|
|
13
|
+
KRIYA_DEX,
|
|
14
|
+
TURBOS_DEX,
|
|
15
|
+
U64_MAX,
|
|
16
|
+
} from "../const"
|
|
17
|
+
import { deepbookSwapMovecall } from "./deepbook"
|
|
18
|
+
import { SuiClient } from "@mysten/sui/client"
|
|
19
|
+
import { kriyaSwapMovecall } from "./kriya"
|
|
20
|
+
import {
|
|
21
|
+
cetusFlashSwapMovecall,
|
|
22
|
+
cetusRepayFlashSwapMovecall,
|
|
23
|
+
cetusSwapWithOutLimit,
|
|
24
|
+
} from "./cetus"
|
|
25
|
+
import { transferOrDestoryCoin } from "./common"
|
|
26
|
+
import { GetDefaultSqrtPriceLimit } from "../math"
|
|
27
|
+
import { flowxAmmSwapMovecall } from "./flowx"
|
|
28
|
+
import { turbosSwapMovecall } from "./turbos"
|
|
29
|
+
import { AftermathAmmSwapMovecall } from "./aftermath"
|
|
30
|
+
import { TransactionErrorCode } from "~/errors"
|
|
31
|
+
|
|
32
|
+
export async function expectInputRouterSwap(
|
|
33
|
+
client: SuiClient,
|
|
34
|
+
params: BuildRouterSwapParams,
|
|
35
|
+
txb: Transaction,
|
|
36
|
+
fromCoin: TransactionObjectArgument,
|
|
37
|
+
config: AggregatorConfig,
|
|
38
|
+
partner?: string
|
|
39
|
+
): Promise<TransactionObjectArgument[]> {
|
|
40
|
+
const splitAmounts = params.routers.map((router) =>
|
|
41
|
+
router.amountIn.toString()
|
|
42
|
+
)
|
|
43
|
+
const targetCoins = []
|
|
44
|
+
const fromCoins = txb.splitCoins(fromCoin, splitAmounts)
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < params.routers.length; i++) {
|
|
47
|
+
const router = params.routers[i]
|
|
48
|
+
let intermediateTargetCoin: TransactionObjectArgument
|
|
49
|
+
let nextFromCoin = fromCoins[i] as TransactionObjectArgument
|
|
50
|
+
|
|
51
|
+
let nextFlashAmount: TransactionArgument = txb.pure.u64(splitAmounts[i])
|
|
52
|
+
|
|
53
|
+
for (let j = 0; j < router.path.length; j++) {
|
|
54
|
+
const firstPathPool = j === 0
|
|
55
|
+
const path = router.path[j]
|
|
56
|
+
|
|
57
|
+
if (path.provider === CETUS_DEX) {
|
|
58
|
+
const swapParams = {
|
|
59
|
+
poolId: path.id,
|
|
60
|
+
amount: nextFlashAmount,
|
|
61
|
+
amountLimit: "0",
|
|
62
|
+
a2b: path.a2b,
|
|
63
|
+
byAmountIn: true,
|
|
64
|
+
sqrtPriceLimit: GetDefaultSqrtPriceLimit(path.a2b),
|
|
65
|
+
partner: partner!,
|
|
66
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
67
|
+
coinBType: path.a2b ? path.target : path.from,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const returnPayAmount = firstPathPool && router.path.length > 1
|
|
71
|
+
const swapResult = await cetusSwapWithOutLimit(
|
|
72
|
+
swapParams,
|
|
73
|
+
nextFromCoin,
|
|
74
|
+
txb,
|
|
75
|
+
config
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
transferOrDestoryCoin(
|
|
79
|
+
txb,
|
|
80
|
+
swapResult.repayTargetCoin,
|
|
81
|
+
path.from,
|
|
82
|
+
config
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
intermediateTargetCoin = swapResult.flashTargetCoin!
|
|
86
|
+
nextFromCoin = intermediateTargetCoin
|
|
87
|
+
nextFlashAmount = swapResult.nextInputAmount!
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (path.provider === DEEPBOOK_DEX) {
|
|
91
|
+
const coinA = path.a2b ? nextFromCoin : undefined
|
|
92
|
+
const coinB = path.a2b ? undefined : nextFromCoin
|
|
93
|
+
|
|
94
|
+
const swapParams = {
|
|
95
|
+
poolId: path.id,
|
|
96
|
+
a2b: path.a2b,
|
|
97
|
+
amount: nextFlashAmount,
|
|
98
|
+
amountLimit: 0,
|
|
99
|
+
coinA,
|
|
100
|
+
coinB,
|
|
101
|
+
useFullInputCoinAmount: !firstPathPool,
|
|
102
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
103
|
+
coinBType: path.a2b ? params.targetCoinType : path.from,
|
|
104
|
+
}
|
|
105
|
+
const deepbookSwapResult = await deepbookSwapMovecall(
|
|
106
|
+
swapParams,
|
|
107
|
+
client,
|
|
108
|
+
txb,
|
|
109
|
+
config
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
intermediateTargetCoin = deepbookSwapResult.targetCoin
|
|
113
|
+
nextFromCoin = intermediateTargetCoin
|
|
114
|
+
nextFlashAmount = deepbookSwapResult.amountOut
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (path.provider === KRIYA_DEX) {
|
|
118
|
+
const coinA = path.a2b ? nextFromCoin : undefined
|
|
119
|
+
const coinB = path.a2b ? undefined : nextFromCoin
|
|
120
|
+
|
|
121
|
+
const swapParams = {
|
|
122
|
+
poolId: path.id,
|
|
123
|
+
amount: nextFlashAmount,
|
|
124
|
+
amountLimit: 0,
|
|
125
|
+
a2b: path.a2b,
|
|
126
|
+
byAmountIn: true,
|
|
127
|
+
coinA,
|
|
128
|
+
coinB,
|
|
129
|
+
useFullInputCoinAmount: !firstPathPool,
|
|
130
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
131
|
+
coinBType: path.a2b ? path.target : path.from,
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const swapResult = await kriyaSwapMovecall(swapParams, txb, config)
|
|
135
|
+
|
|
136
|
+
intermediateTargetCoin = swapResult.targetCoin
|
|
137
|
+
nextFromCoin = intermediateTargetCoin
|
|
138
|
+
nextFlashAmount = swapResult.amountOut
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (path.provider === FLOWX_AMM) {
|
|
142
|
+
const coinA = path.a2b ? nextFromCoin : undefined
|
|
143
|
+
const coinB = path.a2b ? undefined : nextFromCoin
|
|
144
|
+
|
|
145
|
+
const swapParams = {
|
|
146
|
+
amount: nextFlashAmount,
|
|
147
|
+
amountLimit: 0,
|
|
148
|
+
a2b: path.a2b,
|
|
149
|
+
byAmountIn: true,
|
|
150
|
+
coinA,
|
|
151
|
+
coinB,
|
|
152
|
+
useFullInputCoinAmount: !firstPathPool,
|
|
153
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
154
|
+
coinBType: path.a2b ? path.target : path.from,
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const swapResult = await flowxAmmSwapMovecall(swapParams, txb, config)
|
|
158
|
+
|
|
159
|
+
intermediateTargetCoin = swapResult.targetCoin
|
|
160
|
+
nextFromCoin = intermediateTargetCoin
|
|
161
|
+
nextFlashAmount = swapResult.amountOut
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (path.provider === TURBOS_DEX) {
|
|
165
|
+
const coinA = path.a2b ? nextFromCoin : undefined
|
|
166
|
+
const coinB = path.a2b ? undefined : nextFromCoin
|
|
167
|
+
|
|
168
|
+
let feeType = ""
|
|
169
|
+
if (
|
|
170
|
+
path.extendedDetails != null &&
|
|
171
|
+
path.extendedDetails.turbosFeeType != null
|
|
172
|
+
) {
|
|
173
|
+
feeType = path.extendedDetails.turbosFeeType
|
|
174
|
+
} else {
|
|
175
|
+
throw new AggregateError(
|
|
176
|
+
"Build turbos swap movecall error: ",
|
|
177
|
+
TransactionErrorCode.MissTurbosFeeType
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const swapParams = {
|
|
182
|
+
poolId: path.id,
|
|
183
|
+
amount: nextFlashAmount,
|
|
184
|
+
amountLimit: 0,
|
|
185
|
+
a2b: path.a2b,
|
|
186
|
+
byAmountIn: true,
|
|
187
|
+
coinA,
|
|
188
|
+
coinB,
|
|
189
|
+
useFullInputCoinAmount: !firstPathPool,
|
|
190
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
191
|
+
coinBType: path.a2b ? path.target : path.from,
|
|
192
|
+
feeType,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const swapResult = await turbosSwapMovecall(swapParams, txb, config)
|
|
196
|
+
|
|
197
|
+
intermediateTargetCoin = swapResult.targetCoin
|
|
198
|
+
nextFromCoin = intermediateTargetCoin
|
|
199
|
+
nextFlashAmount = swapResult.amountOut
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (path.provider === AFTERMATH_AMM) {
|
|
203
|
+
const coinA = path.a2b ? nextFromCoin : undefined
|
|
204
|
+
const coinB = path.a2b ? undefined : nextFromCoin
|
|
205
|
+
|
|
206
|
+
let lpSupplyType = ""
|
|
207
|
+
|
|
208
|
+
if (
|
|
209
|
+
path.extendedDetails != null &&
|
|
210
|
+
path.extendedDetails.aftermathLpSupplyType != null
|
|
211
|
+
) {
|
|
212
|
+
lpSupplyType = path.extendedDetails.aftermathLpSupplyType
|
|
213
|
+
} else {
|
|
214
|
+
throw new AggregateError(
|
|
215
|
+
"Build aftermath swap movecall error: ",
|
|
216
|
+
TransactionErrorCode.MissAftermathLpSupplyType
|
|
217
|
+
)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const swapParams = {
|
|
221
|
+
poolId: path.id,
|
|
222
|
+
amount: nextFlashAmount,
|
|
223
|
+
amountOut: path.amountOut,
|
|
224
|
+
amountLimit: 0,
|
|
225
|
+
a2b: path.a2b,
|
|
226
|
+
byAmountIn: true,
|
|
227
|
+
coinA,
|
|
228
|
+
coinB,
|
|
229
|
+
useFullInputCoinAmount: !firstPathPool,
|
|
230
|
+
coinAType: path.a2b ? path.from : path.target,
|
|
231
|
+
coinBType: path.a2b ? path.target : path.from,
|
|
232
|
+
slippage: params.slippage,
|
|
233
|
+
lpSupplyType,
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const swapResult = await AftermathAmmSwapMovecall(
|
|
237
|
+
swapParams,
|
|
238
|
+
txb,
|
|
239
|
+
config
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
intermediateTargetCoin = swapResult.targetCoin
|
|
243
|
+
nextFromCoin = intermediateTargetCoin
|
|
244
|
+
nextFlashAmount = swapResult.amountOut
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
targetCoins.push(nextFromCoin)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
transferOrDestoryCoin(txb, fromCoin, params.fromCoinType, config)
|
|
251
|
+
|
|
252
|
+
return targetCoins
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export async function expectOutputRouterSwap(
|
|
256
|
+
params: BuildRouterSwapParams,
|
|
257
|
+
txb: Transaction,
|
|
258
|
+
fromCoin: TransactionObjectArgument,
|
|
259
|
+
config: AggregatorConfig,
|
|
260
|
+
partner?: string
|
|
261
|
+
): Promise<TransactionObjectArgument[]> {
|
|
262
|
+
const splitAmounts = params.routers.map((router) =>
|
|
263
|
+
router.amountOut.toString()
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
const returnCoins: TransactionObjectArgument[] = []
|
|
267
|
+
const receipts: TransactionObjectArgument[] = []
|
|
268
|
+
|
|
269
|
+
const targetCoins = []
|
|
270
|
+
|
|
271
|
+
for (let i = 0; i < params.routers.length; i++) {
|
|
272
|
+
const router = params.routers[i]
|
|
273
|
+
|
|
274
|
+
let nextFlashAmount: TransactionArgument = txb.pure.u64(splitAmounts[i])
|
|
275
|
+
for (let j = router.path.length - 1; j >= 0; j--) {
|
|
276
|
+
const path = router.path[j]
|
|
277
|
+
|
|
278
|
+
const coinAType = path.a2b ? path.from : path.target
|
|
279
|
+
const coinBType = path.a2b ? path.target : path.from
|
|
280
|
+
|
|
281
|
+
const swapParams = {
|
|
282
|
+
poolId: path.id,
|
|
283
|
+
amount: nextFlashAmount,
|
|
284
|
+
amountLimit: U64_MAX,
|
|
285
|
+
a2b: path.a2b,
|
|
286
|
+
byAmountIn: false,
|
|
287
|
+
sqrtPriceLimit: GetDefaultSqrtPriceLimit(path.a2b), //
|
|
288
|
+
partner,
|
|
289
|
+
coinAType,
|
|
290
|
+
coinBType,
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const flashSwapResult = cetusFlashSwapMovecall(swapParams, txb, config)
|
|
294
|
+
nextFlashAmount = flashSwapResult.payAmount
|
|
295
|
+
returnCoins.unshift(flashSwapResult.targetCoin)
|
|
296
|
+
receipts.unshift(flashSwapResult.flashReceipt)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
let nextRepayCoin = fromCoin
|
|
300
|
+
for (let j = 0; j < router.path.length; j++) {
|
|
301
|
+
const path = router.path[j]
|
|
302
|
+
|
|
303
|
+
const coinAType = path.a2b ? path.from : path.target
|
|
304
|
+
const coinBType = path.a2b ? path.target : path.from
|
|
305
|
+
|
|
306
|
+
const repayParams = {
|
|
307
|
+
poolId: path.id,
|
|
308
|
+
a2b: path.a2b,
|
|
309
|
+
partner: partner,
|
|
310
|
+
coinA: path.a2b ? nextRepayCoin : undefined,
|
|
311
|
+
coinB: path.a2b ? undefined : nextRepayCoin,
|
|
312
|
+
receipt: receipts[j],
|
|
313
|
+
coinAType,
|
|
314
|
+
coinBType,
|
|
315
|
+
}
|
|
316
|
+
const repayResult = await cetusRepayFlashSwapMovecall(
|
|
317
|
+
repayParams,
|
|
318
|
+
txb,
|
|
319
|
+
config
|
|
320
|
+
)
|
|
321
|
+
nextRepayCoin = returnCoins[j]
|
|
322
|
+
if (j === 0) {
|
|
323
|
+
fromCoin = repayResult.repayTargetCoin
|
|
324
|
+
} else {
|
|
325
|
+
transferOrDestoryCoin(
|
|
326
|
+
txb,
|
|
327
|
+
repayResult.repayTargetCoin,
|
|
328
|
+
path.from,
|
|
329
|
+
config
|
|
330
|
+
)
|
|
331
|
+
}
|
|
332
|
+
if (j === router.path.length - 1) {
|
|
333
|
+
targetCoins.push(nextRepayCoin)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
transferOrDestoryCoin(txb, fromCoin, params.fromCoinType, config)
|
|
339
|
+
|
|
340
|
+
return targetCoins
|
|
341
|
+
}
|