@cetusprotocol/aggregator-sdk 0.4.1 → 0.4.3
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.js +1 -1
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/.env.example +0 -4
- package/bun.lockb +0 -0
- package/dist/src/api.d.ts +0 -104
- package/dist/src/client.d.ts +0 -118
- package/dist/src/const.d.ts +0 -8
- package/dist/src/errors.d.ts +0 -40
- package/dist/src/index.d.ts +0 -9
- package/dist/src/math.d.ts +0 -6
- package/dist/src/transaction/afsui.d.ts +0 -10
- package/dist/src/transaction/aftermath.d.ts +0 -13
- package/dist/src/transaction/alphafi.d.ts +0 -7
- package/dist/src/transaction/bluefin.d.ts +0 -7
- package/dist/src/transaction/bluemove.d.ts +0 -7
- package/dist/src/transaction/cetus.d.ts +0 -15
- package/dist/src/transaction/deepbook_v2.d.ts +0 -14
- package/dist/src/transaction/deepbook_v3.d.ts +0 -12
- package/dist/src/transaction/flowx_v2.d.ts +0 -7
- package/dist/src/transaction/flowx_v3.d.ts +0 -8
- package/dist/src/transaction/haedal.d.ts +0 -6
- package/dist/src/transaction/haedal_pmm.d.ts +0 -7
- package/dist/src/transaction/index.d.ts +0 -10
- package/dist/src/transaction/kriya_v2.d.ts +0 -6
- package/dist/src/transaction/kriya_v3.d.ts +0 -7
- package/dist/src/transaction/metastable.d.ts +0 -8
- package/dist/src/transaction/obric.d.ts +0 -8
- package/dist/src/transaction/scallop.d.ts +0 -8
- package/dist/src/transaction/steamm.d.ts +0 -6
- package/dist/src/transaction/suilend.d.ts +0 -7
- package/dist/src/transaction/swap.d.ts +0 -4
- package/dist/src/transaction/turbos.d.ts +0 -7
- package/dist/src/transaction/volo.d.ts +0 -8
- package/dist/src/types/CoinAssist.d.ts +0 -122
- package/dist/src/types/sui.d.ts +0 -112
- package/dist/src/utils/api.d.ts +0 -1
- package/dist/src/utils/coin.d.ts +0 -11
- package/dist/src/utils/contracts.d.ts +0 -16
- package/dist/src/utils/index.d.ts +0 -5
- package/dist/src/utils/msafe.d.ts +0 -2
- package/dist/src/utils/transaction.d.ts +0 -3
- package/dist/tests/math.test.d.ts +0 -1
- package/dist/tests/router/alphafi.test.d.ts +0 -2
- package/dist/tests/router/metastable.test.d.ts +0 -2
- package/dist/tests/router/obric.test.d.ts +0 -2
- package/dist/tests/router/scallop.test.d.ts +0 -2
- package/dist/tests/router/steamm.test.d.ts +0 -2
- package/dist/tests/router.test.d.ts +0 -2
- package/dist/tests/test_data.test.d.ts +0 -18
- package/dist/tests/wallet.test.d.ts +0 -1
- package/example/package.json +0 -17
- package/example/swap.ts +0 -21
- package/example/tsconfig.json +0 -12
- package/jest.config.mjs +0 -13
- package/src/api.ts +0 -325
- package/src/client.ts +0 -1081
- package/src/const.ts +0 -15
- package/src/errors.ts +0 -77
- package/src/index.ts +0 -10
- package/src/math.ts +0 -66
- package/src/transaction/afsui.ts +0 -62
- package/src/transaction/aftermath.ts +0 -88
- package/src/transaction/alphafi.ts +0 -50
- package/src/transaction/bluefin.ts +0 -46
- package/src/transaction/bluemove.ts +0 -42
- package/src/transaction/cetus.ts +0 -118
- package/src/transaction/deepbook_v2.ts +0 -122
- package/src/transaction/deepbook_v3.ts +0 -60
- package/src/transaction/flowx_v2.ts +0 -42
- package/src/transaction/flowx_v3.ts +0 -52
- package/src/transaction/haedal.ts +0 -33
- package/src/transaction/haedal_pmm.ts +0 -80
- package/src/transaction/index.ts +0 -42
- package/src/transaction/kriya_v2.ts +0 -37
- package/src/transaction/kriya_v3.ts +0 -47
- package/src/transaction/metastable.ts +0 -141
- package/src/transaction/obric.ts +0 -90
- package/src/transaction/scallop.ts +0 -64
- package/src/transaction/steamm.ts +0 -77
- package/src/transaction/suilend.ts +0 -48
- package/src/transaction/swap.ts +0 -162
- package/src/transaction/turbos.ts +0 -56
- package/src/transaction/volo.ts +0 -53
- package/src/types/CoinAssist.ts +0 -217
- package/src/types/sui.ts +0 -148
- package/src/utils/api.ts +0 -6
- package/src/utils/coin.ts +0 -136
- package/src/utils/contracts.ts +0 -136
- package/src/utils/index.ts +0 -5
- package/src/utils/msafe.ts +0 -40
- package/src/utils/transaction.ts +0 -20
- package/tests/math.test.ts +0 -21
- package/tests/router/alphafi.test.ts +0 -132
- package/tests/router/metastable.test.ts +0 -383
- package/tests/router/obric.test.ts +0 -203
- package/tests/router/scallop.test.ts +0 -133
- package/tests/router/steamm.test.ts +0 -130
- package/tests/router.test.ts +0 -379
- package/tests/test_data.test.ts +0 -28
- package/tests/wallet.test.ts +0 -21
- package/tsup.config.ts +0 -23
- package/version.mjs +0 -28
package/src/client.ts
DELETED
|
@@ -1,1081 +0,0 @@
|
|
|
1
|
-
import Decimal from "decimal.js"
|
|
2
|
-
import { getFullnodeUrl, SuiClient } from "@mysten/sui/client"
|
|
3
|
-
import {
|
|
4
|
-
Transaction,
|
|
5
|
-
TransactionObjectArgument,
|
|
6
|
-
} from "@mysten/sui/transactions"
|
|
7
|
-
import { Signer } from "@mysten/sui/cryptography"
|
|
8
|
-
import BN from "bn.js"
|
|
9
|
-
import { SUI_FRAMEWORK_ADDRESS } from "@mysten/sui/utils"
|
|
10
|
-
import {
|
|
11
|
-
Dex,
|
|
12
|
-
Env,
|
|
13
|
-
extractStructTagFromType,
|
|
14
|
-
FindRouterParams,
|
|
15
|
-
getRouterResult,
|
|
16
|
-
Router,
|
|
17
|
-
RouterData,
|
|
18
|
-
getDeepbookV3Config,
|
|
19
|
-
processEndpoint,
|
|
20
|
-
DeepbookV3Config,
|
|
21
|
-
getAggregatorV2PublishedAt,
|
|
22
|
-
} from "."
|
|
23
|
-
import { Aftermath } from "./transaction/aftermath"
|
|
24
|
-
import { DeepbookV2 } from "./transaction/deepbook_v2"
|
|
25
|
-
import { KriyaV2 } from "./transaction/kriya_v2"
|
|
26
|
-
import { KriyaV3 } from "./transaction/kriya_v3"
|
|
27
|
-
import { FlowxV2 } from "./transaction/flowx_v2"
|
|
28
|
-
import { FlowxV3 } from "./transaction/flowx_v3"
|
|
29
|
-
import { Turbos } from "./transaction/turbos"
|
|
30
|
-
import { Cetus } from "./transaction/cetus"
|
|
31
|
-
import { swapInPools } from "./transaction/swap"
|
|
32
|
-
import { CalculateAmountLimit, CalculateAmountLimitBN } from "./math"
|
|
33
|
-
import { Haedal } from "./transaction/haedal"
|
|
34
|
-
import { Afsui } from "./transaction/afsui"
|
|
35
|
-
import { Volo } from "./transaction/volo"
|
|
36
|
-
import { Bluemove } from "./transaction/bluemove"
|
|
37
|
-
import { CoinAsset } from "./types/sui"
|
|
38
|
-
import { buildInputCoin } from "./utils/coin"
|
|
39
|
-
import { DeepbookV3 } from "./transaction/deepbook_v3"
|
|
40
|
-
import { Scallop } from "./transaction/scallop"
|
|
41
|
-
import { Suilend } from "./transaction/suilend"
|
|
42
|
-
import { Bluefin } from "./transaction/bluefin"
|
|
43
|
-
import { HaedalPmm } from "./transaction/haedal_pmm"
|
|
44
|
-
import { Alphafi } from "./transaction/alphafi"
|
|
45
|
-
import { CoinUtils } from "./types/CoinAssist"
|
|
46
|
-
import {
|
|
47
|
-
SuiPriceServiceConnection,
|
|
48
|
-
SuiPythClient,
|
|
49
|
-
} from "@pythnetwork/pyth-sui-js"
|
|
50
|
-
import { Steamm } from "./transaction/steamm"
|
|
51
|
-
import { Metastable } from "./transaction/metastable"
|
|
52
|
-
import { Obric } from "./transaction/obric"
|
|
53
|
-
|
|
54
|
-
export const CETUS = "CETUS"
|
|
55
|
-
export const DEEPBOOKV2 = "DEEPBOOK"
|
|
56
|
-
export const KRIYA = "KRIYA"
|
|
57
|
-
export const FLOWXV2 = "FLOWX"
|
|
58
|
-
export const FLOWXV3 = "FLOWXV3"
|
|
59
|
-
export const KRIYAV3 = "KRIYAV3"
|
|
60
|
-
export const TURBOS = "TURBOS"
|
|
61
|
-
export const AFTERMATH = "AFTERMATH"
|
|
62
|
-
export const HAEDAL = "HAEDAL"
|
|
63
|
-
export const VOLO = "VOLO"
|
|
64
|
-
export const AFSUI = "AFSUI"
|
|
65
|
-
export const BLUEMOVE = "BLUEMOVE"
|
|
66
|
-
export const DEEPBOOKV3 = "DEEPBOOKV3"
|
|
67
|
-
export const SCALLOP = "SCALLOP"
|
|
68
|
-
export const SUILEND = "SUILEND"
|
|
69
|
-
export const BLUEFIN = "BLUEFIN"
|
|
70
|
-
export const HAEDALPMM = "HAEDALPMM"
|
|
71
|
-
export const ALPHAFI = "ALPHAFI"
|
|
72
|
-
export const SPRINGSUI = "SPRINGSUI"
|
|
73
|
-
export const STEAMM = "STEAMM"
|
|
74
|
-
export const METASTABLE = "METASTABLE"
|
|
75
|
-
export const OBRIC = "OBRIC"
|
|
76
|
-
export const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2"
|
|
77
|
-
|
|
78
|
-
export type BuildRouterSwapParams = {
|
|
79
|
-
routers: Router[]
|
|
80
|
-
byAmountIn: boolean
|
|
81
|
-
inputCoin: TransactionObjectArgument
|
|
82
|
-
slippage: number
|
|
83
|
-
txb: Transaction
|
|
84
|
-
partner?: string
|
|
85
|
-
// This parameter is used to pass the Deep token object. When using the DeepBook V3 provider,
|
|
86
|
-
// users must pay fees with Deep tokens in non-whitelisted pools.
|
|
87
|
-
deepbookv3DeepFee?: TransactionObjectArgument
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export type BuildFastRouterSwapParams = {
|
|
91
|
-
routers: Router[]
|
|
92
|
-
byAmountIn: boolean
|
|
93
|
-
slippage: number
|
|
94
|
-
txb: Transaction
|
|
95
|
-
partner?: string
|
|
96
|
-
refreshAllCoins?: boolean
|
|
97
|
-
payDeepFeeAmount?: number
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export type BuildRouterSwapParamsV2 = {
|
|
101
|
-
routers: RouterData
|
|
102
|
-
inputCoin: TransactionObjectArgument
|
|
103
|
-
slippage: number
|
|
104
|
-
txb: Transaction
|
|
105
|
-
partner?: string
|
|
106
|
-
// This parameter is used to pass the Deep token object. When using the DeepBook V3 provider,
|
|
107
|
-
// users must pay fees with Deep tokens in non-whitelisted pools.
|
|
108
|
-
deepbookv3DeepFee?: TransactionObjectArgument
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export type BuildFastRouterSwapParamsV2 = {
|
|
112
|
-
routers: RouterData
|
|
113
|
-
slippage: number
|
|
114
|
-
txb: Transaction
|
|
115
|
-
partner?: string
|
|
116
|
-
refreshAllCoins?: boolean
|
|
117
|
-
payDeepFeeAmount?: number
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export interface SwapInPoolsParams {
|
|
121
|
-
from: string
|
|
122
|
-
target: string
|
|
123
|
-
amount: BN
|
|
124
|
-
byAmountIn: boolean
|
|
125
|
-
pools: string[]
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
interface PythConfig {
|
|
129
|
-
wormholeStateId: string
|
|
130
|
-
pythStateId: string
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export interface SwapInPoolsResult {
|
|
134
|
-
isExceed: boolean
|
|
135
|
-
routeData?: RouterData
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
function isBuilderRouterSwapParams(
|
|
139
|
-
params: BuildRouterSwapParams | BuildRouterSwapParamsV2
|
|
140
|
-
): params is BuildRouterSwapParams {
|
|
141
|
-
return Array.isArray((params as BuildRouterSwapParams).routers)
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function isBuilderFastRouterSwapParams(
|
|
145
|
-
params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2
|
|
146
|
-
): params is BuildFastRouterSwapParams {
|
|
147
|
-
return Array.isArray((params as BuildFastRouterSwapParams).routers)
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export type AggregatorClientParams = {
|
|
151
|
-
endpoint?: string
|
|
152
|
-
signer?: string
|
|
153
|
-
client?: SuiClient
|
|
154
|
-
env?: Env
|
|
155
|
-
pythUrls?: string[]
|
|
156
|
-
apiKey?: string
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
export class AggregatorClient {
|
|
160
|
-
public endpoint: string
|
|
161
|
-
public signer: string
|
|
162
|
-
public client: SuiClient
|
|
163
|
-
public env: Env
|
|
164
|
-
public apiKey: string
|
|
165
|
-
private allCoins: Map<string, CoinAsset[]>
|
|
166
|
-
|
|
167
|
-
private pythConnections: SuiPriceServiceConnection[]
|
|
168
|
-
private pythClient: SuiPythClient
|
|
169
|
-
|
|
170
|
-
private static readonly CONFIG: Record<Env, PythConfig> = {
|
|
171
|
-
[Env.Testnet]: {
|
|
172
|
-
wormholeStateId:
|
|
173
|
-
"0x31358d198147da50db32eda2562951d53973a0c0ad5ed738e9b17d88b213d790",
|
|
174
|
-
pythStateId:
|
|
175
|
-
"0x243759059f4c3111179da5878c12f68d612c21a8d54d85edc86164bb18be1c7c",
|
|
176
|
-
},
|
|
177
|
-
[Env.Mainnet]: {
|
|
178
|
-
wormholeStateId:
|
|
179
|
-
"0xaeab97f96cf9877fee2883315d459552b2b921edc16d7ceac6eab944dd88919c",
|
|
180
|
-
pythStateId:
|
|
181
|
-
"0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8",
|
|
182
|
-
},
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
constructor(params: AggregatorClientParams) {
|
|
186
|
-
this.endpoint = params.endpoint ? processEndpoint(params.endpoint) : DEFAULT_ENDPOINT
|
|
187
|
-
this.client = params.client || new SuiClient({ url: getFullnodeUrl("mainnet") })
|
|
188
|
-
this.signer = params.signer || ""
|
|
189
|
-
this.env = params.env || Env.Mainnet
|
|
190
|
-
this.allCoins = new Map<string, CoinAsset[]>()
|
|
191
|
-
|
|
192
|
-
const config = AggregatorClient.CONFIG[this.env]
|
|
193
|
-
this.pythConnections = this.newPythClients(params.pythUrls ?? [])
|
|
194
|
-
this.pythClient = new SuiPythClient(
|
|
195
|
-
this.client,
|
|
196
|
-
config.pythStateId,
|
|
197
|
-
config.wormholeStateId
|
|
198
|
-
)
|
|
199
|
-
this.apiKey = params.apiKey || ""
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
newPythClients(pythUrls: string[]) {
|
|
203
|
-
if (!pythUrls.includes("https://hermes.pyth.network")) {
|
|
204
|
-
pythUrls.push("https://hermes.pyth.network")
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const connections = pythUrls.map(url => new SuiPriceServiceConnection(url, { timeout: 3000 }))
|
|
208
|
-
return connections
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
async getCoins(
|
|
212
|
-
coinType: string,
|
|
213
|
-
refresh: boolean = true
|
|
214
|
-
): Promise<CoinAsset[]> {
|
|
215
|
-
if (this.signer === "") {
|
|
216
|
-
throw new Error("Signer is required, but not provided.")
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
let cursor = null
|
|
220
|
-
let limit = 50
|
|
221
|
-
|
|
222
|
-
if (!refresh) {
|
|
223
|
-
const gotFromCoins = this.allCoins.get(coinType)
|
|
224
|
-
if (gotFromCoins) {
|
|
225
|
-
return gotFromCoins
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const allCoins: CoinAsset[] = []
|
|
230
|
-
while (true) {
|
|
231
|
-
try {
|
|
232
|
-
const gotCoins = await this.client.getCoins({
|
|
233
|
-
owner: this.signer,
|
|
234
|
-
coinType,
|
|
235
|
-
cursor,
|
|
236
|
-
limit,
|
|
237
|
-
})
|
|
238
|
-
for (const coin of gotCoins.data) {
|
|
239
|
-
allCoins.push({
|
|
240
|
-
coinAddress: extractStructTagFromType(coin.coinType).source_address,
|
|
241
|
-
coinObjectId: coin.coinObjectId,
|
|
242
|
-
balance: BigInt(coin.balance),
|
|
243
|
-
})
|
|
244
|
-
}
|
|
245
|
-
if (gotCoins.data.length < limit) {
|
|
246
|
-
break
|
|
247
|
-
}
|
|
248
|
-
cursor = gotCoins.data[limit - 1].coinObjectId
|
|
249
|
-
} catch (e) {
|
|
250
|
-
console.error("getCoins error:", e)
|
|
251
|
-
break
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
this.allCoins.set(coinType, allCoins)
|
|
256
|
-
return allCoins
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
async findRouters(params: FindRouterParams): Promise<RouterData | null> {
|
|
260
|
-
return getRouterResult(this.endpoint, this.apiKey, params)
|
|
261
|
-
}
|
|
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
|
-
|
|
335
|
-
async expectInputSwap(
|
|
336
|
-
txb: Transaction,
|
|
337
|
-
inputCoin: TransactionObjectArgument,
|
|
338
|
-
routers: Router[],
|
|
339
|
-
amountOutLimit: BN,
|
|
340
|
-
pythPriceIDs: Map<string, string>,
|
|
341
|
-
partner?: string,
|
|
342
|
-
deepbookv3DeepFee?: TransactionObjectArgument,
|
|
343
|
-
packages?: Map<string, string>
|
|
344
|
-
) {
|
|
345
|
-
if (routers.length === 0) {
|
|
346
|
-
throw new Error("No router found")
|
|
347
|
-
}
|
|
348
|
-
const splitAmounts = routers.map((router) => router.amountIn.toString())
|
|
349
|
-
const inputCoinType = routers[0].path[0].from
|
|
350
|
-
const outputCoinType = routers[0].path[routers[0].path.length - 1].target
|
|
351
|
-
const inputCoins = txb.splitCoins(inputCoin, splitAmounts)
|
|
352
|
-
const outputCoins = []
|
|
353
|
-
for (let i = 0; i < routers.length; i++) {
|
|
354
|
-
if (routers[i].path.length === 0) {
|
|
355
|
-
throw new Error("Empty path")
|
|
356
|
-
}
|
|
357
|
-
let nextCoin = inputCoins[i] as TransactionObjectArgument
|
|
358
|
-
for (const path of routers[i].path) {
|
|
359
|
-
const dex = this.newDex(path.provider, pythPriceIDs, partner)
|
|
360
|
-
nextCoin = await dex.swap(
|
|
361
|
-
this,
|
|
362
|
-
txb,
|
|
363
|
-
path,
|
|
364
|
-
nextCoin,
|
|
365
|
-
packages,
|
|
366
|
-
deepbookv3DeepFee
|
|
367
|
-
)
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
outputCoins.push(nextCoin)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
374
|
-
this.publishedAtV2(),
|
|
375
|
-
packages
|
|
376
|
-
)
|
|
377
|
-
|
|
378
|
-
this.transferOrDestoryCoin(
|
|
379
|
-
txb,
|
|
380
|
-
inputCoin,
|
|
381
|
-
inputCoinType,
|
|
382
|
-
this.publishedAtV2()
|
|
383
|
-
)
|
|
384
|
-
const mergedTargetCointhis = this.checkCoinThresholdAndMergeCoin(
|
|
385
|
-
txb,
|
|
386
|
-
outputCoins,
|
|
387
|
-
outputCoinType,
|
|
388
|
-
amountOutLimit,
|
|
389
|
-
aggregatorV2PublishedAt
|
|
390
|
-
)
|
|
391
|
-
return mergedTargetCointhis
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
async expectOutputSwap(
|
|
395
|
-
txb: Transaction,
|
|
396
|
-
inputCoin: TransactionObjectArgument,
|
|
397
|
-
routers: Router[],
|
|
398
|
-
partner?: string,
|
|
399
|
-
packages?: Map<string, string>
|
|
400
|
-
): Promise<TransactionObjectArgument> {
|
|
401
|
-
const returnCoins: TransactionObjectArgument[] = []
|
|
402
|
-
const receipts: TransactionObjectArgument[] = []
|
|
403
|
-
const targetCoins = []
|
|
404
|
-
const dex = new Cetus(this.env, partner)
|
|
405
|
-
|
|
406
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
407
|
-
this.publishedAtV2(),
|
|
408
|
-
packages
|
|
409
|
-
)
|
|
410
|
-
|
|
411
|
-
for (let i = 0; i < routers.length; i++) {
|
|
412
|
-
const router = routers[i]
|
|
413
|
-
for (let j = router.path.length - 1; j >= 0; j--) {
|
|
414
|
-
const path = router.path[j]
|
|
415
|
-
const flashSwapResult = dex.flash_swap(this, txb, path, false)
|
|
416
|
-
returnCoins.unshift(flashSwapResult.targetCoin)
|
|
417
|
-
receipts.unshift(flashSwapResult.flashReceipt)
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
let nextRepayCoin = inputCoin
|
|
421
|
-
for (let j = 0; j < router.path.length; j++) {
|
|
422
|
-
const path = router.path[j]
|
|
423
|
-
const repayResult = dex.repay_flash_swap(
|
|
424
|
-
this,
|
|
425
|
-
txb,
|
|
426
|
-
path,
|
|
427
|
-
nextRepayCoin,
|
|
428
|
-
receipts[j]
|
|
429
|
-
)
|
|
430
|
-
nextRepayCoin = returnCoins[j]
|
|
431
|
-
if (j === 0) {
|
|
432
|
-
inputCoin = repayResult
|
|
433
|
-
} else {
|
|
434
|
-
this.transferOrDestoryCoin(
|
|
435
|
-
txb,
|
|
436
|
-
repayResult,
|
|
437
|
-
path.from,
|
|
438
|
-
aggregatorV2PublishedAt
|
|
439
|
-
)
|
|
440
|
-
}
|
|
441
|
-
if (j === router.path.length - 1) {
|
|
442
|
-
targetCoins.push(nextRepayCoin)
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
const inputCoinType = routers[0].path[0].from
|
|
447
|
-
this.transferOrDestoryCoin(
|
|
448
|
-
txb,
|
|
449
|
-
inputCoin,
|
|
450
|
-
inputCoinType,
|
|
451
|
-
aggregatorV2PublishedAt
|
|
452
|
-
)
|
|
453
|
-
if (targetCoins.length > 1) {
|
|
454
|
-
const vec = txb.makeMoveVec({ elements: targetCoins.slice(1) })
|
|
455
|
-
txb.moveCall({
|
|
456
|
-
target: `${SUI_FRAMEWORK_ADDRESS}::pay::join_vec`,
|
|
457
|
-
typeArguments: [routers[0].path[routers[0].path.length - 1].target],
|
|
458
|
-
arguments: [targetCoins[0], vec],
|
|
459
|
-
})
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
return targetCoins[0]
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
async swapInPools(
|
|
466
|
-
params: SwapInPoolsParams
|
|
467
|
-
): Promise<SwapInPoolsResult | null> {
|
|
468
|
-
let result
|
|
469
|
-
try {
|
|
470
|
-
result = await swapInPools(this.client, params, this.signer, this.env)
|
|
471
|
-
} catch (e) {
|
|
472
|
-
console.error("swapInPools error:", e)
|
|
473
|
-
return null
|
|
474
|
-
}
|
|
475
|
-
return result
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
async routerSwap(
|
|
479
|
-
params: BuildRouterSwapParams | BuildRouterSwapParamsV2
|
|
480
|
-
): Promise<TransactionObjectArgument> {
|
|
481
|
-
const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } =
|
|
482
|
-
params
|
|
483
|
-
|
|
484
|
-
const routerData = Array.isArray(routers) ? routers : routers.routes
|
|
485
|
-
const byAmountIn = isBuilderRouterSwapParams(params)
|
|
486
|
-
? params.byAmountIn
|
|
487
|
-
: params.routers.byAmountIn
|
|
488
|
-
|
|
489
|
-
const amountIn = routerData.reduce(
|
|
490
|
-
(acc, router) => acc.add(router.amountIn),
|
|
491
|
-
new BN(0)
|
|
492
|
-
)
|
|
493
|
-
const amountOut = routerData.reduce(
|
|
494
|
-
(acc, router) => acc.add(router.amountOut),
|
|
495
|
-
new BN(0)
|
|
496
|
-
)
|
|
497
|
-
|
|
498
|
-
const amountLimit = CalculateAmountLimitBN(
|
|
499
|
-
byAmountIn ? amountOut : amountIn,
|
|
500
|
-
byAmountIn,
|
|
501
|
-
slippage
|
|
502
|
-
)
|
|
503
|
-
|
|
504
|
-
const packages = isBuilderRouterSwapParams(params)
|
|
505
|
-
? undefined
|
|
506
|
-
: params.routers.packages
|
|
507
|
-
|
|
508
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
509
|
-
this.publishedAtV2(),
|
|
510
|
-
packages
|
|
511
|
-
)
|
|
512
|
-
|
|
513
|
-
const priceIDs = findPythPriceIDs(routerData)
|
|
514
|
-
|
|
515
|
-
const priceInfoObjectIds =
|
|
516
|
-
priceIDs.length > 0
|
|
517
|
-
? await this.updatePythPriceIDs(priceIDs, txb)
|
|
518
|
-
: new Map<string, string>()
|
|
519
|
-
|
|
520
|
-
if (byAmountIn) {
|
|
521
|
-
const targetCoin = await this.expectInputSwap(
|
|
522
|
-
txb,
|
|
523
|
-
inputCoin,
|
|
524
|
-
routerData,
|
|
525
|
-
amountLimit,
|
|
526
|
-
priceInfoObjectIds,
|
|
527
|
-
partner,
|
|
528
|
-
deepbookv3DeepFee,
|
|
529
|
-
packages
|
|
530
|
-
)
|
|
531
|
-
return targetCoin
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// When exact output, we will set slippage limit in split coin.
|
|
535
|
-
const splitedInputCoins = txb.splitCoins(inputCoin, [
|
|
536
|
-
amountLimit.toString(),
|
|
537
|
-
])
|
|
538
|
-
this.transferOrDestoryCoin(
|
|
539
|
-
txb,
|
|
540
|
-
inputCoin,
|
|
541
|
-
routerData[0].path[0].from,
|
|
542
|
-
aggregatorV2PublishedAt
|
|
543
|
-
)
|
|
544
|
-
const targetCoin = await this.expectOutputSwap(
|
|
545
|
-
txb,
|
|
546
|
-
splitedInputCoins[0],
|
|
547
|
-
routerData,
|
|
548
|
-
partner
|
|
549
|
-
)
|
|
550
|
-
return targetCoin
|
|
551
|
-
}
|
|
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
|
-
|
|
616
|
-
// auto build input coin
|
|
617
|
-
// auto merge, transfer or destory target coin.
|
|
618
|
-
async fastRouterSwap(
|
|
619
|
-
params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2
|
|
620
|
-
) {
|
|
621
|
-
const {
|
|
622
|
-
routers,
|
|
623
|
-
slippage,
|
|
624
|
-
txb,
|
|
625
|
-
partner,
|
|
626
|
-
refreshAllCoins,
|
|
627
|
-
payDeepFeeAmount,
|
|
628
|
-
} = params
|
|
629
|
-
|
|
630
|
-
const routerData = Array.isArray(routers) ? routers : routers.routes
|
|
631
|
-
const fromCoinType = routerData[0].path[0].from
|
|
632
|
-
let fromCoins = await this.getCoins(fromCoinType, refreshAllCoins)
|
|
633
|
-
|
|
634
|
-
const targetCoinType =
|
|
635
|
-
routerData[0].path[routerData[0].path.length - 1].target
|
|
636
|
-
const amountIn = routerData.reduce(
|
|
637
|
-
(acc, router) => acc.add(router.amountIn),
|
|
638
|
-
new BN(0)
|
|
639
|
-
)
|
|
640
|
-
const amountOut = routerData.reduce(
|
|
641
|
-
(acc, router) => acc.add(router.amountOut),
|
|
642
|
-
new BN(0)
|
|
643
|
-
)
|
|
644
|
-
|
|
645
|
-
const byAmountIn = isBuilderFastRouterSwapParams(params)
|
|
646
|
-
? params.byAmountIn
|
|
647
|
-
: params.routers.byAmountIn
|
|
648
|
-
const amountLimit = CalculateAmountLimit(
|
|
649
|
-
byAmountIn ? amountOut : amountIn,
|
|
650
|
-
byAmountIn,
|
|
651
|
-
slippage
|
|
652
|
-
)
|
|
653
|
-
const amount = byAmountIn ? amountIn : amountLimit
|
|
654
|
-
const buildFromCoinRes = buildInputCoin(
|
|
655
|
-
txb,
|
|
656
|
-
fromCoins,
|
|
657
|
-
BigInt(amount.toString()),
|
|
658
|
-
fromCoinType
|
|
659
|
-
)
|
|
660
|
-
|
|
661
|
-
let deepCoin
|
|
662
|
-
if (payDeepFeeAmount && payDeepFeeAmount > 0) {
|
|
663
|
-
let deepCoins = await this.getCoins(this.deepbookv3DeepFeeType())
|
|
664
|
-
deepCoin = buildInputCoin(
|
|
665
|
-
txb,
|
|
666
|
-
deepCoins,
|
|
667
|
-
BigInt(payDeepFeeAmount),
|
|
668
|
-
this.deepbookv3DeepFeeType()
|
|
669
|
-
).targetCoin
|
|
670
|
-
}
|
|
671
|
-
|
|
672
|
-
const routerSwapParams = isBuilderFastRouterSwapParams(params)
|
|
673
|
-
? {
|
|
674
|
-
routers: routerData,
|
|
675
|
-
inputCoin: buildFromCoinRes.targetCoin,
|
|
676
|
-
slippage,
|
|
677
|
-
byAmountIn,
|
|
678
|
-
txb,
|
|
679
|
-
partner,
|
|
680
|
-
deepbookv3DeepFee: deepCoin,
|
|
681
|
-
}
|
|
682
|
-
: {
|
|
683
|
-
routers: params.routers,
|
|
684
|
-
inputCoin: buildFromCoinRes.targetCoin,
|
|
685
|
-
slippage,
|
|
686
|
-
byAmountIn,
|
|
687
|
-
txb,
|
|
688
|
-
partner,
|
|
689
|
-
deepbookv3DeepFee: deepCoin,
|
|
690
|
-
}
|
|
691
|
-
|
|
692
|
-
const targetCoin = await this.routerSwap(routerSwapParams)
|
|
693
|
-
|
|
694
|
-
if (CoinUtils.isSuiCoin(targetCoinType)) {
|
|
695
|
-
txb.mergeCoins(txb.gas, [targetCoin])
|
|
696
|
-
} else {
|
|
697
|
-
let targetCoins = await this.getCoins(targetCoinType, refreshAllCoins)
|
|
698
|
-
const targetCoinRes = buildInputCoin(
|
|
699
|
-
txb,
|
|
700
|
-
targetCoins,
|
|
701
|
-
BigInt(0),
|
|
702
|
-
targetCoinType
|
|
703
|
-
)
|
|
704
|
-
|
|
705
|
-
const packages = isBuilderFastRouterSwapParams(params)
|
|
706
|
-
? undefined
|
|
707
|
-
: params.routers.packages
|
|
708
|
-
const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
|
|
709
|
-
this.publishedAtV2(),
|
|
710
|
-
packages
|
|
711
|
-
)
|
|
712
|
-
|
|
713
|
-
txb.mergeCoins(targetCoinRes.targetCoin, [targetCoin])
|
|
714
|
-
if (targetCoinRes.isMintZeroCoin) {
|
|
715
|
-
this.transferOrDestoryCoin(
|
|
716
|
-
txb,
|
|
717
|
-
targetCoinRes.targetCoin,
|
|
718
|
-
targetCoinType,
|
|
719
|
-
aggregatorV2PublishedAt
|
|
720
|
-
)
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
// Include cetus、deepbookv2、flowxv2 & v3、kriyav2 & v3、turbos、aftermath、haedal、afsui、volo、bluemove
|
|
726
|
-
publishedAtV2(): string {
|
|
727
|
-
if (this.env === Env.Mainnet) {
|
|
728
|
-
// return "0x3fb42ddf908af45f9fc3c59eab227888ff24ba2e137b3b55bf80920fd47e11af" // version 6
|
|
729
|
-
// return "0xf9c6f78322ed667909e05f6b42b2f5a67af6297503c905335e02a15148e9440d" // version 7
|
|
730
|
-
// return "0x2485feb9d42c7c3bcb8ecde555ad40f1b073d9fb4faf354fa2d30a0b183a23ce" // version 8
|
|
731
|
-
return "0x3864c7c59a4889fec05d1aae4bc9dba5a0e0940594b424fbed44cb3f6ac4c032" // version 9
|
|
732
|
-
// return "0x803db8dfcc86fc1afbc7d2212bd14ec9690978ddebea0d590e01147d6b17aa06" // pre
|
|
733
|
-
} else {
|
|
734
|
-
// return "0x0ed287d6c3fe4962d0994ffddc1d19a15fba6a81533f3f0dcc2bbcedebce0637" // version 2
|
|
735
|
-
return "0x52eae33adeb44de55cfb3f281d4cc9e02d976181c0952f5323648b5717b33934"
|
|
736
|
-
}
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
// Include deepbookv3, scallop, bluefin
|
|
740
|
-
publishedAtV2Extend(): string {
|
|
741
|
-
if (this.env === Env.Mainnet) {
|
|
742
|
-
// return "0x43811be4677f5a5de7bf2dac740c10abddfaa524aee6b18e910eeadda8a2f6ae" // version 1, deepbookv3
|
|
743
|
-
// return "0x6d70ffa7aa3f924c3f0b573d27d29895a0ee666aaff821073f75cb14af7fd01a" // version 3, deepbookv3 & scallop
|
|
744
|
-
// return "0x16d9418726c26d8cb4ce8c9dd75917fa9b1c7bf47d38d7a1a22603135f0f2a56" // version 4, add suilend
|
|
745
|
-
// return "0x3b6d71bdeb8ce5b06febfd3cfc29ecd60d50da729477c8b8038ecdae34541b91" // version 5, add bluefin
|
|
746
|
-
// return "0x81ade554cb24a7564ca43a4bfb7381b08d9e5c5f375162c95215b696ab903502" // version 6, force upgrade scallop
|
|
747
|
-
// return "0x347dd58bbd11cd82c8b386b344729717c04a998da73386e82a239cc196d5706b" // version 7
|
|
748
|
-
// return "0xf2fcea41dc217385019828375764fa06d9bd25e8e4726ba1962680849fb8d613" // version 8
|
|
749
|
-
// return "0xa2d8a4279d69d8fec04b2fea8852d0d467d3cc0d39c5890180d439ae7a9953ed" // version 9
|
|
750
|
-
// return "0x34ef25b60b51f9d07cd9b7dc5b08dfdf26c7b0ff00c57bb17454c161fa6b6b83" // version 10
|
|
751
|
-
// return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc" // version 11
|
|
752
|
-
return "0x200e762fa2c49f3dc150813038fbf22fd4f894ac6f23ebe1085c62f2ef97f1ca" // version 12
|
|
753
|
-
} else {
|
|
754
|
-
return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78"
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
deepbookv3DeepFeeType(): string {
|
|
759
|
-
if (this.env === Env.Mainnet) {
|
|
760
|
-
return "0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP"
|
|
761
|
-
} else {
|
|
762
|
-
return "0x36dbef866a1d62bf7328989a10fb2f07d769f4ee587c0de4a0a256e57e0a58a8::deep::DEEP"
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
transferOrDestoryCoin(
|
|
767
|
-
txb: Transaction,
|
|
768
|
-
coin: TransactionObjectArgument,
|
|
769
|
-
coinType: string,
|
|
770
|
-
aggregatorV2PublishedAt: string
|
|
771
|
-
) {
|
|
772
|
-
txb.moveCall({
|
|
773
|
-
target: `${aggregatorV2PublishedAt}::utils::transfer_or_destroy_coin`,
|
|
774
|
-
typeArguments: [coinType],
|
|
775
|
-
arguments: [coin],
|
|
776
|
-
})
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
checkCoinThresholdAndMergeCoin(
|
|
780
|
-
txb: Transaction,
|
|
781
|
-
coins: TransactionObjectArgument[],
|
|
782
|
-
coinType: string,
|
|
783
|
-
amountLimit: BN,
|
|
784
|
-
aggregatorV2PublishedAt: string
|
|
785
|
-
) {
|
|
786
|
-
let targetCoin = coins[0]
|
|
787
|
-
if (coins.length > 1) {
|
|
788
|
-
let vec = txb.makeMoveVec({ elements: coins.slice(1) })
|
|
789
|
-
txb.moveCall({
|
|
790
|
-
target: `${SUI_FRAMEWORK_ADDRESS}::pay::join_vec`,
|
|
791
|
-
typeArguments: [coinType],
|
|
792
|
-
arguments: [coins[0], vec],
|
|
793
|
-
})
|
|
794
|
-
targetCoin = coins[0]
|
|
795
|
-
}
|
|
796
|
-
|
|
797
|
-
txb.moveCall({
|
|
798
|
-
target: `${aggregatorV2PublishedAt}::utils::check_coin_threshold`,
|
|
799
|
-
typeArguments: [coinType],
|
|
800
|
-
arguments: [targetCoin, txb.pure.u64(amountLimit.toString())],
|
|
801
|
-
})
|
|
802
|
-
return targetCoin
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
newDex(
|
|
806
|
-
provider: string,
|
|
807
|
-
pythPriceIDs: Map<string, string>,
|
|
808
|
-
partner?: string
|
|
809
|
-
): Dex {
|
|
810
|
-
switch (provider) {
|
|
811
|
-
case CETUS:
|
|
812
|
-
return new Cetus(this.env, partner)
|
|
813
|
-
case DEEPBOOKV2:
|
|
814
|
-
return new DeepbookV2(this.env)
|
|
815
|
-
case DEEPBOOKV3:
|
|
816
|
-
return new DeepbookV3(this.env)
|
|
817
|
-
case KRIYA:
|
|
818
|
-
return new KriyaV2(this.env)
|
|
819
|
-
case KRIYAV3:
|
|
820
|
-
return new KriyaV3(this.env)
|
|
821
|
-
case FLOWXV2:
|
|
822
|
-
return new FlowxV2(this.env)
|
|
823
|
-
case FLOWXV3:
|
|
824
|
-
return new FlowxV3(this.env)
|
|
825
|
-
case TURBOS:
|
|
826
|
-
return new Turbos(this.env)
|
|
827
|
-
case AFTERMATH:
|
|
828
|
-
return new Aftermath(this.env)
|
|
829
|
-
case HAEDAL:
|
|
830
|
-
return new Haedal(this.env)
|
|
831
|
-
case AFSUI:
|
|
832
|
-
return new Afsui(this.env)
|
|
833
|
-
case VOLO:
|
|
834
|
-
return new Volo(this.env)
|
|
835
|
-
case BLUEMOVE:
|
|
836
|
-
return new Bluemove(this.env)
|
|
837
|
-
case SCALLOP:
|
|
838
|
-
return new Scallop(this.env)
|
|
839
|
-
case SUILEND:
|
|
840
|
-
return new Suilend(this.env)
|
|
841
|
-
case SPRINGSUI:
|
|
842
|
-
return new Suilend(this.env)
|
|
843
|
-
case BLUEFIN:
|
|
844
|
-
return new Bluefin(this.env)
|
|
845
|
-
case HAEDALPMM:
|
|
846
|
-
return new HaedalPmm(this.env, pythPriceIDs)
|
|
847
|
-
case ALPHAFI:
|
|
848
|
-
return new Alphafi(this.env)
|
|
849
|
-
case STEAMM:
|
|
850
|
-
return new Steamm(this.env)
|
|
851
|
-
case METASTABLE:
|
|
852
|
-
return new Metastable(this.env, pythPriceIDs)
|
|
853
|
-
case OBRIC:
|
|
854
|
-
return new Obric(this.env, pythPriceIDs)
|
|
855
|
-
default:
|
|
856
|
-
throw new Error(`Unsupported dex ${provider}`)
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
async signAndExecuteTransaction(txb: Transaction, signer: Signer) {
|
|
861
|
-
const res = await this.client.signAndExecuteTransaction({
|
|
862
|
-
transaction: txb,
|
|
863
|
-
signer,
|
|
864
|
-
options: {
|
|
865
|
-
showEffects: true,
|
|
866
|
-
showEvents: true,
|
|
867
|
-
showInput: true,
|
|
868
|
-
showBalanceChanges: true,
|
|
869
|
-
},
|
|
870
|
-
})
|
|
871
|
-
return res
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
async devInspectTransactionBlock(txb: Transaction) {
|
|
875
|
-
const res = await this.client.devInspectTransactionBlock({
|
|
876
|
-
transactionBlock: txb,
|
|
877
|
-
sender: this.signer,
|
|
878
|
-
})
|
|
879
|
-
|
|
880
|
-
return res
|
|
881
|
-
}
|
|
882
|
-
|
|
883
|
-
async sendTransaction(txb: Transaction, signer: Signer) {
|
|
884
|
-
const res = await this.client.signAndExecuteTransaction({
|
|
885
|
-
transaction: txb,
|
|
886
|
-
signer,
|
|
887
|
-
})
|
|
888
|
-
return res
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
async getDeepbookV3Config(): Promise<DeepbookV3Config | null> {
|
|
892
|
-
const res = await getDeepbookV3Config(this.endpoint)
|
|
893
|
-
if (res) {
|
|
894
|
-
return res.data
|
|
895
|
-
}
|
|
896
|
-
return null
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
async updatePythPriceIDs(
|
|
900
|
-
priceIDs: string[],
|
|
901
|
-
txb: Transaction
|
|
902
|
-
): Promise<Map<string, string>> {
|
|
903
|
-
let priceUpdateData: Buffer[] | null = null
|
|
904
|
-
let lastError: Error | null = null
|
|
905
|
-
|
|
906
|
-
for (const connection of this.pythConnections) {
|
|
907
|
-
try {
|
|
908
|
-
priceUpdateData = await connection.getPriceFeedsUpdateData(priceIDs)
|
|
909
|
-
break
|
|
910
|
-
} catch (e) {
|
|
911
|
-
lastError = e as Error
|
|
912
|
-
console.log("Error: ", e)
|
|
913
|
-
continue
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
if (priceUpdateData == null) {
|
|
918
|
-
throw new Error(
|
|
919
|
-
`All Pyth price nodes are unavailable. Cannot fetch price data. Please switch to or add new available Pyth nodes. Detailed error: ${lastError?.message}`
|
|
920
|
-
)
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
let priceInfoObjectIds = []
|
|
924
|
-
try {
|
|
925
|
-
priceInfoObjectIds = await this.pythClient.updatePriceFeeds(
|
|
926
|
-
txb,
|
|
927
|
-
priceUpdateData,
|
|
928
|
-
priceIDs
|
|
929
|
-
)
|
|
930
|
-
} catch (e) {
|
|
931
|
-
throw new Error(`All Pyth price nodes are unavailable. Cannot fetch price data. Please switch to or add new available Pyth nodes in the pythUrls parameter when initializing AggregatorClient, for example: new AggregatorClient({ pythUrls: ["https://your-pyth-node-url"] }). Detailed error: ${e}`)
|
|
932
|
-
}
|
|
933
|
-
|
|
934
|
-
let priceInfoObjectIdsMap = new Map<string, string>()
|
|
935
|
-
for (let i = 0; i < priceIDs.length; i++) {
|
|
936
|
-
priceInfoObjectIdsMap.set(priceIDs[i], priceInfoObjectIds[i])
|
|
937
|
-
}
|
|
938
|
-
return priceInfoObjectIdsMap
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
export function findPythPriceIDs(routes: Router[]): string[] {
|
|
943
|
-
const priceIDs = new Set<string>()
|
|
944
|
-
|
|
945
|
-
for (const route of routes) {
|
|
946
|
-
for (const path of route.path) {
|
|
947
|
-
if (path.provider === HAEDALPMM) {
|
|
948
|
-
if (
|
|
949
|
-
path.extendedDetails &&
|
|
950
|
-
path.extendedDetails.haedalPmmBasePriceSeed &&
|
|
951
|
-
path.extendedDetails.haedalPmmQuotePriceSeed
|
|
952
|
-
) {
|
|
953
|
-
priceIDs.add(path.extendedDetails.haedalPmmBasePriceSeed)
|
|
954
|
-
priceIDs.add(path.extendedDetails.haedalPmmQuotePriceSeed)
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
if (path.provider === METASTABLE) {
|
|
958
|
-
if (path.extendedDetails && path.extendedDetails.metastablePriceSeed) {
|
|
959
|
-
priceIDs.add(path.extendedDetails.metastablePriceSeed)
|
|
960
|
-
}
|
|
961
|
-
if (path.extendedDetails && path.extendedDetails.metastableETHPriceSeed) {
|
|
962
|
-
priceIDs.add(path.extendedDetails.metastableETHPriceSeed)
|
|
963
|
-
}
|
|
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
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
return Array.from(priceIDs)
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
export function parseRouterResponse(
|
|
979
|
-
data: any,
|
|
980
|
-
byAmountIn: boolean
|
|
981
|
-
): RouterData {
|
|
982
|
-
let totalDeepFee = 0
|
|
983
|
-
for (const route of data.routes) {
|
|
984
|
-
for (const path of route.path) {
|
|
985
|
-
if (path.extended_details && path.extended_details.deepbookv3_deep_fee) {
|
|
986
|
-
totalDeepFee += Number(path.extended_details.deepbookv3_deep_fee)
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
|
|
991
|
-
let packages = undefined
|
|
992
|
-
if (data.packages != null) {
|
|
993
|
-
packages = new Map<string, string>()
|
|
994
|
-
for (const [key, value] of Object.entries(data.packages)) {
|
|
995
|
-
packages.set(key, value as string)
|
|
996
|
-
}
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
let routerData: RouterData = {
|
|
1000
|
-
amountIn: new BN(data.amount_in.toString()),
|
|
1001
|
-
amountOut: new BN(data.amount_out.toString()),
|
|
1002
|
-
byAmountIn,
|
|
1003
|
-
insufficientLiquidity: false,
|
|
1004
|
-
routes: data.routes.map((route: any) => {
|
|
1005
|
-
return {
|
|
1006
|
-
path: route.path.map((path: any) => {
|
|
1007
|
-
let version
|
|
1008
|
-
if (path.provider === AFTERMATH) {
|
|
1009
|
-
version =
|
|
1010
|
-
path.extended_details.aftermath_pool_flatness === 0 ? "v2" : "v3"
|
|
1011
|
-
}
|
|
1012
|
-
|
|
1013
|
-
let extendedDetails
|
|
1014
|
-
if (
|
|
1015
|
-
path.provider === TURBOS ||
|
|
1016
|
-
path.provider === AFTERMATH ||
|
|
1017
|
-
path.provider === CETUS ||
|
|
1018
|
-
path.provider === DEEPBOOKV3 ||
|
|
1019
|
-
path.provider === SCALLOP ||
|
|
1020
|
-
path.provider === HAEDALPMM ||
|
|
1021
|
-
path.provider === STEAMM ||
|
|
1022
|
-
path.provider === METASTABLE ||
|
|
1023
|
-
path.provider === OBRIC
|
|
1024
|
-
) {
|
|
1025
|
-
extendedDetails = {
|
|
1026
|
-
aftermathLpSupplyType:
|
|
1027
|
-
path.extended_details?.aftermath_lp_supply_type,
|
|
1028
|
-
turbosFeeType: path.extended_details?.turbos_fee_type,
|
|
1029
|
-
afterSqrtPrice: path.extended_details?.after_sqrt_price,
|
|
1030
|
-
deepbookv3DeepFee: path.extended_details?.deepbookv3_deep_fee,
|
|
1031
|
-
scallopScoinTreasury:
|
|
1032
|
-
path.extended_details?.scallop_scoin_treasury,
|
|
1033
|
-
haedalPmmBasePriceSeed:
|
|
1034
|
-
path.extended_details?.haedal_pmm_base_price_seed,
|
|
1035
|
-
haedalPmmQuotePriceSeed:
|
|
1036
|
-
path.extended_details?.haedal_pmm_quote_price_seed,
|
|
1037
|
-
steammBankA: path.extended_details?.steamm_bank_a,
|
|
1038
|
-
steammBankB: path.extended_details?.steamm_bank_b,
|
|
1039
|
-
steammLendingMarket: path.extended_details?.steamm_lending_market,
|
|
1040
|
-
steammLendingMarketType: path.extended_details?.steamm_lending_market_type,
|
|
1041
|
-
steammBCoinAType: path.extended_details?.steamm_btoken_a_type,
|
|
1042
|
-
steammBCoinBType: path.extended_details?.steamm_btoken_b_type,
|
|
1043
|
-
steammLPToken: path.extended_details?.steamm_lp_token_type,
|
|
1044
|
-
metastablePriceSeed: path.extended_details?.metastable_price_seed,
|
|
1045
|
-
metastableETHPriceSeed: path.extended_details?.metastable_eth_price_seed,
|
|
1046
|
-
metastableWhitelistedAppId: path.extended_details?.metastable_whitelisted_app_id,
|
|
1047
|
-
metastableCreateCapPkgId: path.extended_details?.metastable_create_cap_pkg_id,
|
|
1048
|
-
metastableCreateCapModule: path.extended_details?.metastable_create_cap_module,
|
|
1049
|
-
metastableCreateCapAllTypeParams: path.extended_details?.metastable_create_cap_all_type_params,
|
|
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,
|
|
1055
|
-
}
|
|
1056
|
-
}
|
|
1057
|
-
|
|
1058
|
-
return {
|
|
1059
|
-
id: path.id,
|
|
1060
|
-
direction: path.direction,
|
|
1061
|
-
provider: path.provider,
|
|
1062
|
-
from: path.from,
|
|
1063
|
-
target: path.target,
|
|
1064
|
-
feeRate: path.fee_rate,
|
|
1065
|
-
amountIn: path.amount_in,
|
|
1066
|
-
amountOut: path.amount_out,
|
|
1067
|
-
extendedDetails,
|
|
1068
|
-
version,
|
|
1069
|
-
}
|
|
1070
|
-
}),
|
|
1071
|
-
amountIn: new BN(route.amount_in.toString()),
|
|
1072
|
-
amountOut: new BN(route.amount_out.toString()),
|
|
1073
|
-
initialPrice: new Decimal(route.initial_price.toString()),
|
|
1074
|
-
}
|
|
1075
|
-
}),
|
|
1076
|
-
totalDeepFee,
|
|
1077
|
-
packages,
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
return routerData
|
|
1081
|
-
}
|