@7kprotocol/sdk-ts 3.4.1 → 3.4.2-beta.1
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/lib/cjs/features/limitDca/placeLimitOrder.js +8 -3
- package/lib/cjs/features/swap/buildTx.js +101 -66
- package/lib/cjs/features/swap/buildTxV2.js +225 -0
- package/lib/cjs/features/swap/config.js +13 -7
- package/lib/cjs/features/swap/getQuote.js +3 -2
- package/lib/cjs/features/swap/index.js +1 -0
- package/lib/cjs/index.js +6 -2
- package/lib/cjs/libs/protocols/cetus_dlmm.js +48 -0
- package/lib/cjs/libs/protocols/index.js +2 -0
- package/lib/cjs/types/features/limitDca/placeLimitOrder.d.ts +2 -1
- package/lib/cjs/types/features/limitDca/placeLimitOrder.d.ts.map +1 -1
- package/lib/cjs/types/features/swap/buildTx.d.ts +14 -1
- package/lib/cjs/types/features/swap/buildTx.d.ts.map +1 -1
- package/lib/cjs/types/features/swap/buildTxV2.d.ts +20 -0
- package/lib/cjs/types/features/swap/buildTxV2.d.ts.map +1 -0
- package/lib/cjs/types/features/swap/config.d.ts.map +1 -1
- package/lib/cjs/types/features/swap/getQuote.d.ts +3 -1
- package/lib/cjs/types/features/swap/getQuote.d.ts.map +1 -1
- package/lib/cjs/types/features/swap/index.d.ts +1 -0
- package/lib/cjs/types/features/swap/index.d.ts.map +1 -1
- package/lib/cjs/types/index.d.ts +4 -2
- package/lib/cjs/types/index.d.ts.map +1 -1
- package/lib/cjs/types/libs/protocols/base.d.ts +4 -5
- package/lib/cjs/types/libs/protocols/base.d.ts.map +1 -1
- package/lib/cjs/types/libs/protocols/cetus_dlmm.d.ts +9 -0
- package/lib/cjs/types/libs/protocols/cetus_dlmm.d.ts.map +1 -0
- package/lib/cjs/types/libs/protocols/index.d.ts +2 -0
- package/lib/cjs/types/libs/protocols/index.d.ts.map +1 -1
- package/lib/cjs/types/libs/protocols/steamm/index.d.ts +3 -12
- package/lib/cjs/types/libs/protocols/steamm/index.d.ts.map +1 -1
- package/lib/cjs/types/libs/swapWithRoute.d.ts +3 -4
- package/lib/cjs/types/libs/swapWithRoute.d.ts.map +1 -1
- package/lib/cjs/types/types/aggregator.d.ts +5 -1
- package/lib/cjs/types/types/aggregator.d.ts.map +1 -1
- package/lib/cjs/types/types/tx.d.ts +13 -0
- package/lib/cjs/types/types/tx.d.ts.map +1 -1
- package/lib/cjs/types/utils/sui.d.ts +1 -0
- package/lib/cjs/types/utils/sui.d.ts.map +1 -1
- package/lib/cjs/utils/sui.js +7 -0
- package/lib/esm/features/limitDca/placeLimitOrder.js +8 -3
- package/lib/esm/features/swap/buildTx.js +95 -66
- package/lib/esm/features/swap/buildTxV2.js +219 -0
- package/lib/esm/features/swap/config.js +13 -7
- package/lib/esm/features/swap/getQuote.js +3 -2
- package/lib/esm/features/swap/index.js +1 -0
- package/lib/esm/index.mjs +12 -10
- package/lib/esm/libs/protocols/cetus_dlmm.js +44 -0
- package/lib/esm/libs/protocols/index.js +2 -0
- package/lib/esm/types/features/limitDca/placeLimitOrder.d.ts +2 -1
- package/lib/esm/types/features/limitDca/placeLimitOrder.d.ts.map +1 -1
- package/lib/esm/types/features/swap/buildTx.d.ts +14 -1
- package/lib/esm/types/features/swap/buildTx.d.ts.map +1 -1
- package/lib/esm/types/features/swap/buildTxV2.d.ts +20 -0
- package/lib/esm/types/features/swap/buildTxV2.d.ts.map +1 -0
- package/lib/esm/types/features/swap/config.d.ts.map +1 -1
- package/lib/esm/types/features/swap/getQuote.d.ts +3 -1
- package/lib/esm/types/features/swap/getQuote.d.ts.map +1 -1
- package/lib/esm/types/features/swap/index.d.ts +1 -0
- package/lib/esm/types/features/swap/index.d.ts.map +1 -1
- package/lib/esm/types/index.d.ts +4 -2
- package/lib/esm/types/index.d.ts.map +1 -1
- package/lib/esm/types/libs/protocols/base.d.ts +4 -5
- package/lib/esm/types/libs/protocols/base.d.ts.map +1 -1
- package/lib/esm/types/libs/protocols/cetus_dlmm.d.ts +9 -0
- package/lib/esm/types/libs/protocols/cetus_dlmm.d.ts.map +1 -0
- package/lib/esm/types/libs/protocols/index.d.ts +2 -0
- package/lib/esm/types/libs/protocols/index.d.ts.map +1 -1
- package/lib/esm/types/libs/protocols/steamm/index.d.ts +3 -12
- package/lib/esm/types/libs/protocols/steamm/index.d.ts.map +1 -1
- package/lib/esm/types/libs/swapWithRoute.d.ts +3 -4
- package/lib/esm/types/libs/swapWithRoute.d.ts.map +1 -1
- package/lib/esm/types/types/aggregator.d.ts +5 -1
- package/lib/esm/types/types/aggregator.d.ts.map +1 -1
- package/lib/esm/types/types/tx.d.ts +13 -0
- package/lib/esm/types/types/tx.d.ts.map +1 -1
- package/lib/esm/types/utils/sui.d.ts +1 -0
- package/lib/esm/types/utils/sui.d.ts.map +1 -1
- package/lib/esm/utils/sui.js +7 -0
- package/package.json +3 -3
- package/lib/cjs/libs/getCoinOjectIdsByAmount.js +0 -65
- package/lib/cjs/libs/getSplitCoinForTx.js +0 -33
- package/lib/cjs/types/libs/getCoinOjectIdsByAmount.d.ts +0 -7
- package/lib/cjs/types/libs/getCoinOjectIdsByAmount.d.ts.map +0 -1
- package/lib/cjs/types/libs/getSplitCoinForTx.d.ts +0 -6
- package/lib/cjs/types/libs/getSplitCoinForTx.d.ts.map +0 -1
- package/lib/esm/libs/getCoinOjectIdsByAmount.js +0 -61
- package/lib/esm/libs/getSplitCoinForTx.js +0 -29
- package/lib/esm/types/libs/getCoinOjectIdsByAmount.d.ts +0 -7
- package/lib/esm/types/libs/getCoinOjectIdsByAmount.d.ts.map +0 -1
- package/lib/esm/types/libs/getSplitCoinForTx.d.ts +0 -6
- package/lib/esm/types/libs/getSplitCoinForTx.d.ts.map +0 -1
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.placeLimitOrder = placeLimitOrder;
|
|
4
|
-
const
|
|
5
|
-
const token_1 = require("../../utils/token");
|
|
4
|
+
const transactions_1 = require("@mysten/sui/transactions");
|
|
6
5
|
const constants_1 = require("./constants");
|
|
7
6
|
async function placeLimitOrder({ accountAddress, payCoinType, targetCoinType, payCoinAmount, rate, slippage, expireTs, devInspect, }) {
|
|
8
|
-
const
|
|
7
|
+
const tx = new transactions_1.Transaction();
|
|
8
|
+
const payCoin = tx.add((0, transactions_1.coinWithBalance)({
|
|
9
|
+
type: payCoinType,
|
|
10
|
+
balance: payCoinAmount,
|
|
11
|
+
useGasCoin: !devInspect,
|
|
12
|
+
}));
|
|
9
13
|
tx.moveCall({
|
|
10
14
|
target: `${constants_1.LIMIT_ORDER_MODULE_ID}::place_limit_order`,
|
|
11
15
|
arguments: [
|
|
@@ -18,5 +22,6 @@ async function placeLimitOrder({ accountAddress, payCoinType, targetCoinType, pa
|
|
|
18
22
|
],
|
|
19
23
|
typeArguments: [payCoinType, targetCoinType],
|
|
20
24
|
});
|
|
25
|
+
tx.setSenderIfNotSet(accountAddress);
|
|
21
26
|
return tx;
|
|
22
27
|
}
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildTx = void 0;
|
|
3
|
+
exports.buildBluefinXTx = exports.settle = exports.getExpectedReturn = exports.validateRoutes = exports.updatePythPriceFeedsIfAny = exports.getPythPriceFeeds = exports.buildTx = void 0;
|
|
4
4
|
const transactions_1 = require("@mysten/sui/transactions");
|
|
5
5
|
const utils_1 = require("@mysten/sui/utils");
|
|
6
6
|
const config_1 = require("../../config");
|
|
7
7
|
const _7k_1 = require("../../constants/_7k");
|
|
8
|
-
const getSplitCoinForTx_1 = require("../../libs/getSplitCoinForTx");
|
|
9
8
|
const groupSwapRoutes_1 = require("../../libs/groupSwapRoutes");
|
|
10
9
|
const client_1 = require("../../libs/protocols/bluefinx/client");
|
|
11
10
|
const types_1 = require("../../libs/protocols/bluefinx/types");
|
|
12
11
|
const swapWithRoute_1 = require("../../libs/swapWithRoute");
|
|
13
12
|
const aggregator_1 = require("../../types/aggregator");
|
|
14
13
|
const sui_1 = require("../../utils/sui");
|
|
15
|
-
const token_1 = require("../../utils/token");
|
|
16
14
|
const config_2 = require("./config");
|
|
17
15
|
const getQuote_1 = require("./getQuote");
|
|
18
16
|
const buildTx = async ({ quoteResponse, accountAddress, slippage, commission: __commission, devInspect, extendTx, isSponsored, }) => {
|
|
@@ -22,7 +20,7 @@ const buildTx = async ({ quoteResponse, accountAddress, slippage, commission: __
|
|
|
22
20
|
// commission is ignored for bluefinx
|
|
23
21
|
commissionBps: isBluefinX ? 0 : __commission.commissionBps,
|
|
24
22
|
};
|
|
25
|
-
const { tx: _tx, coinIn } = extendTx || {};
|
|
23
|
+
const { tx: _tx, coinIn: _coinIn } = extendTx || {};
|
|
26
24
|
let coinOut;
|
|
27
25
|
if (isBluefinX && devInspect) {
|
|
28
26
|
throw new Error("BluefinX tx is sponsored, skip devInspect");
|
|
@@ -38,18 +36,17 @@ const buildTx = async ({ quoteResponse, accountAddress, slippage, commission: __
|
|
|
38
36
|
}
|
|
39
37
|
const tx = _tx || new transactions_1.Transaction();
|
|
40
38
|
const routes = (0, groupSwapRoutes_1.groupSwapRoutes)(quoteResponse);
|
|
41
|
-
validateRoutes(routes, isSponsored);
|
|
39
|
+
(0, exports.validateRoutes)(routes, isSponsored);
|
|
42
40
|
const splits = routes.map((group) => group[0]?.amount ?? "0");
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const pythMap = await updatePythPriceFeedsIfAny(tx, quoteResponse);
|
|
41
|
+
const coinIn = _coinIn ||
|
|
42
|
+
tx.add((0, transactions_1.coinWithBalance)({
|
|
43
|
+
type: quoteResponse.tokenIn,
|
|
44
|
+
balance: BigInt(quoteResponse.swapAmountWithDecimal),
|
|
45
|
+
useGasCoin: !isSponsored && !isBluefinX,
|
|
46
|
+
}));
|
|
47
|
+
const coinData = tx.splitCoins(coinIn, splits);
|
|
48
|
+
sui_1.SuiUtils.transferOrDestroyZeroCoin(tx, quoteResponse.tokenIn, coinIn, accountAddress);
|
|
49
|
+
const pythMap = await (0, exports.updatePythPriceFeedsIfAny)(tx, [quoteResponse]);
|
|
53
50
|
const coinObjects = [];
|
|
54
51
|
const config = await (0, config_2.getConfig)();
|
|
55
52
|
await Promise.all(routes.map(async (route, index) => {
|
|
@@ -67,79 +64,43 @@ const buildTx = async ({ quoteResponse, accountAddress, slippage, commission: __
|
|
|
67
64
|
}
|
|
68
65
|
}));
|
|
69
66
|
if (coinObjects.length > 0) {
|
|
70
|
-
const
|
|
71
|
-
? sui_1.SuiUtils.mergeCoins(coinObjects, tx)
|
|
72
|
-
: coinObjects[0];
|
|
73
|
-
const returnAmountAfterCommission = (BigInt(10000 - _commission.commissionBps) *
|
|
74
|
-
BigInt(quoteResponse.returnAmountWithDecimal)) /
|
|
75
|
-
BigInt(10000);
|
|
76
|
-
const minReceived = (BigInt(1e9 - +slippage * 1e9) * BigInt(returnAmountAfterCommission)) /
|
|
77
|
-
BigInt(1e9);
|
|
78
|
-
tx.moveCall({
|
|
79
|
-
target: `${_7k_1._7K_PACKAGE_ID}::settle::settle`,
|
|
80
|
-
typeArguments: [quoteResponse.tokenIn, quoteResponse.tokenOut],
|
|
81
|
-
arguments: [
|
|
82
|
-
tx.object(_7k_1._7K_CONFIG),
|
|
83
|
-
tx.object(_7k_1._7K_VAULT),
|
|
84
|
-
tx.pure.u64(quoteResponse.swapAmountWithDecimal),
|
|
85
|
-
mergeCoin,
|
|
86
|
-
tx.pure.u64(minReceived), // minimum received
|
|
87
|
-
tx.pure.u64(returnAmountAfterCommission), // expected amount out
|
|
88
|
-
tx.pure.option("address", (0, utils_1.isValidSuiAddress)(_commission.partner) ? _commission.partner : null),
|
|
89
|
-
tx.pure.u64(_commission.commissionBps),
|
|
90
|
-
tx.pure.u64(0),
|
|
91
|
-
],
|
|
92
|
-
});
|
|
67
|
+
const mergedCoin = tx.add((0, exports.settle)(coinObjects, quoteResponse, Math.floor(+slippage * 10000), _commission));
|
|
93
68
|
if (!extendTx) {
|
|
94
|
-
tx.transferObjects([
|
|
69
|
+
tx.transferObjects([mergedCoin], tx.pure.address(accountAddress));
|
|
95
70
|
}
|
|
96
71
|
else {
|
|
97
|
-
coinOut =
|
|
72
|
+
coinOut = mergedCoin;
|
|
98
73
|
}
|
|
99
74
|
}
|
|
100
75
|
if (isBluefinX) {
|
|
101
|
-
const extra = quoteResponse.swaps[0].extra;
|
|
102
|
-
if (extra.quoteExpiresAtUtcMillis < Date.now()) {
|
|
103
|
-
throw new Error("Quote expired");
|
|
104
|
-
}
|
|
105
|
-
tx.setSenderIfNotSet(accountAddress);
|
|
106
|
-
const bytes = await tx.build({
|
|
107
|
-
client: config_1.Config.getSuiClient(),
|
|
108
|
-
onlyTransactionKind: true,
|
|
109
|
-
});
|
|
110
|
-
const res = await (0, client_1.sponsorBluefinX)({
|
|
111
|
-
quoteId: extra.quoteId,
|
|
112
|
-
txBytes: (0, utils_1.toBase64)(bytes),
|
|
113
|
-
sender: accountAddress,
|
|
114
|
-
});
|
|
115
|
-
if (!res.success) {
|
|
116
|
-
throw new Error("Sponsor failed");
|
|
117
|
-
}
|
|
118
76
|
return {
|
|
119
|
-
tx:
|
|
77
|
+
tx: await (0, exports.buildBluefinXTx)(tx, accountAddress, quoteResponse),
|
|
120
78
|
coinOut,
|
|
121
79
|
};
|
|
122
80
|
}
|
|
81
|
+
tx.setSenderIfNotSet(accountAddress);
|
|
123
82
|
return { tx, coinOut };
|
|
124
83
|
};
|
|
125
84
|
exports.buildTx = buildTx;
|
|
126
|
-
const getPythPriceFeeds = (
|
|
85
|
+
const getPythPriceFeeds = (responses) => {
|
|
127
86
|
const ids = new Set();
|
|
128
|
-
for (const
|
|
129
|
-
for (const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
87
|
+
for (const res of responses) {
|
|
88
|
+
for (const s of res.swaps) {
|
|
89
|
+
for (const o of s.extra?.oracles || []) {
|
|
90
|
+
const bytes = o.Pyth?.price_identifier?.bytes || o.Pyth?.bytes;
|
|
91
|
+
if (bytes) {
|
|
92
|
+
ids.add("0x" + (0, utils_1.toHex)(Uint8Array.from(bytes)));
|
|
93
|
+
}
|
|
134
94
|
}
|
|
135
95
|
}
|
|
136
96
|
}
|
|
137
97
|
return Array.from(ids);
|
|
138
98
|
};
|
|
99
|
+
exports.getPythPriceFeeds = getPythPriceFeeds;
|
|
139
100
|
const updatePythPriceFeedsIfAny = async (tx, quoteResponse) => {
|
|
140
101
|
// update oracles price if any
|
|
141
102
|
const pythMap = {};
|
|
142
|
-
const pythIds = getPythPriceFeeds(quoteResponse);
|
|
103
|
+
const pythIds = (0, exports.getPythPriceFeeds)(quoteResponse);
|
|
143
104
|
if (pythIds.length > 0) {
|
|
144
105
|
const prices = await config_1.Config.getPythConnection().getPriceFeedsUpdateData(pythIds);
|
|
145
106
|
const ids = await config_1.Config.getPythClient().updatePriceFeeds(tx, prices, pythIds);
|
|
@@ -149,6 +110,7 @@ const updatePythPriceFeedsIfAny = async (tx, quoteResponse) => {
|
|
|
149
110
|
}
|
|
150
111
|
return pythMap;
|
|
151
112
|
};
|
|
113
|
+
exports.updatePythPriceFeedsIfAny = updatePythPriceFeedsIfAny;
|
|
152
114
|
const validateRoutes = (routes, isSponsored) => {
|
|
153
115
|
if (!isSponsored) {
|
|
154
116
|
return;
|
|
@@ -158,3 +120,76 @@ const validateRoutes = (routes, isSponsored) => {
|
|
|
158
120
|
throw new Error("Oracle based sources are not supported for sponsored tx");
|
|
159
121
|
}
|
|
160
122
|
};
|
|
123
|
+
exports.validateRoutes = validateRoutes;
|
|
124
|
+
const getExpectedReturn = (returnAmount, slippageBps, commissionBps, tipBps = 0) => {
|
|
125
|
+
if (slippageBps > 10000) {
|
|
126
|
+
throw new Error("Slippage must be less than 100%");
|
|
127
|
+
}
|
|
128
|
+
if (commissionBps > 10000) {
|
|
129
|
+
throw new Error("Commission must be less than 100%");
|
|
130
|
+
}
|
|
131
|
+
if (tipBps > 10000) {
|
|
132
|
+
throw new Error("Tip must be less than 100%");
|
|
133
|
+
}
|
|
134
|
+
const returnAmountWithDecimal = BigInt(returnAmount);
|
|
135
|
+
const tipAmountWithDecimal = (returnAmountWithDecimal * BigInt(tipBps || 0)) / 10000n;
|
|
136
|
+
const commissionAmountWithDecimal = ((returnAmountWithDecimal - tipAmountWithDecimal) * BigInt(commissionBps)) /
|
|
137
|
+
10000n;
|
|
138
|
+
const expectedReturnWithDecimal = returnAmountWithDecimal -
|
|
139
|
+
tipAmountWithDecimal -
|
|
140
|
+
commissionAmountWithDecimal;
|
|
141
|
+
const minAmountWithDecimal = (expectedReturnWithDecimal * BigInt(1e4 - slippageBps)) / 10000n;
|
|
142
|
+
return {
|
|
143
|
+
tipAmount: tipAmountWithDecimal,
|
|
144
|
+
minAmount: minAmountWithDecimal,
|
|
145
|
+
commissionAmount: commissionAmountWithDecimal,
|
|
146
|
+
expectedAmount: expectedReturnWithDecimal.toString(10),
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
exports.getExpectedReturn = getExpectedReturn;
|
|
150
|
+
const settle = (coinObjects, quoteResponse, slippageBps, _commission) => {
|
|
151
|
+
return (tx) => {
|
|
152
|
+
const mergeCoin = coinObjects.length > 1
|
|
153
|
+
? (tx.mergeCoins(coinObjects[0], coinObjects.slice(1)), coinObjects[0])
|
|
154
|
+
: coinObjects[0];
|
|
155
|
+
const { minAmount, expectedAmount } = (0, exports.getExpectedReturn)(quoteResponse.returnAmountWithDecimal, slippageBps, _commission.commissionBps);
|
|
156
|
+
tx.moveCall({
|
|
157
|
+
target: `${_7k_1._7K_PACKAGE_ID}::settle::settle`,
|
|
158
|
+
typeArguments: [quoteResponse.tokenIn, quoteResponse.tokenOut],
|
|
159
|
+
arguments: [
|
|
160
|
+
tx.object(_7k_1._7K_CONFIG),
|
|
161
|
+
tx.object(_7k_1._7K_VAULT),
|
|
162
|
+
tx.pure.u64(quoteResponse.swapAmountWithDecimal),
|
|
163
|
+
mergeCoin,
|
|
164
|
+
tx.pure.u64(minAmount), // minimum received
|
|
165
|
+
tx.pure.u64(expectedAmount), // expected amount out
|
|
166
|
+
tx.pure.option("address", (0, utils_1.isValidSuiAddress)(_commission.partner) ? _commission.partner : null),
|
|
167
|
+
tx.pure.u64(_commission.commissionBps),
|
|
168
|
+
tx.pure.u64(0),
|
|
169
|
+
],
|
|
170
|
+
});
|
|
171
|
+
return mergeCoin;
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
exports.settle = settle;
|
|
175
|
+
const buildBluefinXTx = async (tx, accountAddress, quoteResponse) => {
|
|
176
|
+
const extra = quoteResponse.swaps[0].extra;
|
|
177
|
+
if (extra.quoteExpiresAtUtcMillis < Date.now()) {
|
|
178
|
+
throw new Error("Quote expired");
|
|
179
|
+
}
|
|
180
|
+
tx.setSenderIfNotSet(accountAddress);
|
|
181
|
+
const bytes = await tx.build({
|
|
182
|
+
client: config_1.Config.getSuiClient(),
|
|
183
|
+
onlyTransactionKind: true,
|
|
184
|
+
});
|
|
185
|
+
const res = await (0, client_1.sponsorBluefinX)({
|
|
186
|
+
quoteId: extra.quoteId,
|
|
187
|
+
txBytes: (0, utils_1.toBase64)(bytes),
|
|
188
|
+
sender: accountAddress,
|
|
189
|
+
});
|
|
190
|
+
if (!res.success) {
|
|
191
|
+
throw new Error("Sponsor failed");
|
|
192
|
+
}
|
|
193
|
+
return new types_1.BluefinXTx(res.quoteId, res.data.txBytes);
|
|
194
|
+
};
|
|
195
|
+
exports.buildBluefinXTx = buildBluefinXTx;
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.multiSwap = exports.optimize = exports.buildTxV2 = void 0;
|
|
4
|
+
const transactions_1 = require("@mysten/sui/transactions");
|
|
5
|
+
const utils_1 = require("@mysten/sui/utils");
|
|
6
|
+
const groupSwapRoutes_1 = require("../../libs/groupSwapRoutes");
|
|
7
|
+
const swapWithRoute_1 = require("../../libs/swapWithRoute");
|
|
8
|
+
const aggregator_1 = require("../../types/aggregator");
|
|
9
|
+
const sui_1 = require("../../utils/sui");
|
|
10
|
+
const buildTx_1 = require("./buildTx");
|
|
11
|
+
const config_1 = require("./config");
|
|
12
|
+
/**
|
|
13
|
+
* Wave-based transaction builder that optimizes swap execution by:
|
|
14
|
+
* 1. Grouping swaps into execution waves based on readiness
|
|
15
|
+
* 2. Merging redundant swaps to the same pool within each wave
|
|
16
|
+
* 3. Processing waves sequentially, passing intermediate tokens between waves
|
|
17
|
+
*/
|
|
18
|
+
const buildTxV2 = async ({ quoteResponse, accountAddress, slippage, commission: __commission, devInspect, extendTx, isSponsored, }) => {
|
|
19
|
+
const isBluefinX = (0, aggregator_1.isBluefinXRouting)(quoteResponse);
|
|
20
|
+
const _commission = {
|
|
21
|
+
...__commission,
|
|
22
|
+
commissionBps: isBluefinX ? 0 : __commission.commissionBps,
|
|
23
|
+
};
|
|
24
|
+
const { tx: _tx, coinIn: _coinIn } = extendTx || {};
|
|
25
|
+
let coinOut;
|
|
26
|
+
if (isBluefinX && devInspect) {
|
|
27
|
+
throw new Error("BluefinX tx is sponsored, skip devInspect");
|
|
28
|
+
}
|
|
29
|
+
if (!accountAddress) {
|
|
30
|
+
throw new Error("Sender address is required");
|
|
31
|
+
}
|
|
32
|
+
if (!quoteResponse.routes) {
|
|
33
|
+
throw new Error("Invalid quote response: 'routes' are required");
|
|
34
|
+
}
|
|
35
|
+
if (!(0, utils_1.isValidSuiAddress)(_commission.partner)) {
|
|
36
|
+
throw new Error("Invalid commission partner address");
|
|
37
|
+
}
|
|
38
|
+
const tx = _tx || new transactions_1.Transaction();
|
|
39
|
+
const routes = (0, groupSwapRoutes_1.groupSwapRoutes)(quoteResponse);
|
|
40
|
+
(0, buildTx_1.validateRoutes)(routes, isSponsored);
|
|
41
|
+
const splits = routes.map((group) => group[0]?.amount ?? "0");
|
|
42
|
+
const coinIn = _coinIn ||
|
|
43
|
+
tx.add((0, transactions_1.coinWithBalance)({
|
|
44
|
+
type: quoteResponse.tokenIn,
|
|
45
|
+
balance: BigInt(quoteResponse.swapAmountWithDecimal),
|
|
46
|
+
useGasCoin: !isSponsored && !isBluefinX,
|
|
47
|
+
}));
|
|
48
|
+
const coinData = tx.splitCoins(coinIn, splits);
|
|
49
|
+
sui_1.SuiUtils.transferOrDestroyZeroCoin(tx, quoteResponse.tokenIn, coinIn, accountAddress);
|
|
50
|
+
const pythMap = await (0, buildTx_1.updatePythPriceFeedsIfAny)(tx, [quoteResponse]);
|
|
51
|
+
const config = await (0, config_1.getConfig)();
|
|
52
|
+
const finalCoins = await (0, exports.optimize)(pythMap, config, routes, coinData, tx, accountAddress);
|
|
53
|
+
// Merge all final coins
|
|
54
|
+
if (finalCoins.length > 0) {
|
|
55
|
+
const mergeCoin = tx.add((0, buildTx_1.settle)(finalCoins, quoteResponse, Math.floor(+slippage * 10000), _commission));
|
|
56
|
+
if (!extendTx) {
|
|
57
|
+
tx.transferObjects([mergeCoin], tx.pure.address(accountAddress));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
coinOut = mergeCoin;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (isBluefinX) {
|
|
64
|
+
return {
|
|
65
|
+
tx: await (0, buildTx_1.buildBluefinXTx)(tx, accountAddress, quoteResponse),
|
|
66
|
+
coinOut,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
tx.setSenderIfNotSet(accountAddress);
|
|
70
|
+
return { tx, coinOut };
|
|
71
|
+
};
|
|
72
|
+
exports.buildTxV2 = buildTxV2;
|
|
73
|
+
const optimize = async (pythMap, config, routes, coinData, tx, accountAddress) => {
|
|
74
|
+
// Initialize route states with split coins
|
|
75
|
+
const routeStates = routes.map((route, index) => ({
|
|
76
|
+
routeIndex: index,
|
|
77
|
+
currentHopIndex: 0,
|
|
78
|
+
currentCoin: coinData[index],
|
|
79
|
+
swaps: route,
|
|
80
|
+
completed: false,
|
|
81
|
+
}));
|
|
82
|
+
const finalCoins = [];
|
|
83
|
+
const coinTypeOut = routes[0][routes[0].length - 1].assetOut;
|
|
84
|
+
// Execute swaps in waves
|
|
85
|
+
while (true) {
|
|
86
|
+
const readyHops = [];
|
|
87
|
+
routeStates.forEach((state) => {
|
|
88
|
+
if (state.completed)
|
|
89
|
+
return;
|
|
90
|
+
if (state.currentHopIndex >= state.swaps.length) {
|
|
91
|
+
state.completed = true;
|
|
92
|
+
finalCoins.push(state.currentCoin);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const swap = state.swaps[state.currentHopIndex];
|
|
96
|
+
readyHops.push({
|
|
97
|
+
routeIndex: state.routeIndex,
|
|
98
|
+
hopIndex: state.currentHopIndex,
|
|
99
|
+
swap,
|
|
100
|
+
inputCoin: state.currentCoin,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
if (readyHops.length === 0)
|
|
104
|
+
break;
|
|
105
|
+
// Group hops by pool for merging opportunities
|
|
106
|
+
const poolGroups = new Map();
|
|
107
|
+
readyHops.forEach((hop) => {
|
|
108
|
+
const poolKey = `${hop.swap.poolId}|${hop.swap.assetIn}|${hop.swap.assetOut}`;
|
|
109
|
+
if (!poolGroups.has(poolKey)) {
|
|
110
|
+
poolGroups.set(poolKey, {
|
|
111
|
+
swap: hop.swap,
|
|
112
|
+
hops: [],
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
poolGroups.get(poolKey).hops.push(hop);
|
|
116
|
+
});
|
|
117
|
+
// Execute each pool group in this wave
|
|
118
|
+
const wavePromises = [];
|
|
119
|
+
for (const group of poolGroups.values()) {
|
|
120
|
+
const { swap, hops } = group;
|
|
121
|
+
// For merged swaps, we need to combine input coins first
|
|
122
|
+
const wavePromise = (async () => {
|
|
123
|
+
let combinedCoin;
|
|
124
|
+
if (hops.length > 1) {
|
|
125
|
+
// Merge all input coins for this pool
|
|
126
|
+
const inputCoins = hops.map((h) => h.inputCoin);
|
|
127
|
+
tx.mergeCoins(inputCoins[0], inputCoins.slice(1));
|
|
128
|
+
combinedCoin = inputCoins[0];
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
combinedCoin = hops[0].inputCoin;
|
|
132
|
+
}
|
|
133
|
+
// Execute the swap with the combined coin
|
|
134
|
+
const resultCoin = await (0, swapWithRoute_1.swapWithRoute)({
|
|
135
|
+
route: [swap],
|
|
136
|
+
inputCoinObject: combinedCoin,
|
|
137
|
+
currentAccount: accountAddress,
|
|
138
|
+
tx,
|
|
139
|
+
config,
|
|
140
|
+
pythMap,
|
|
141
|
+
});
|
|
142
|
+
if (!resultCoin) {
|
|
143
|
+
throw new Error(`Swap failed for pool ${swap.poolId}`);
|
|
144
|
+
}
|
|
145
|
+
if (hops[0].swap.assetOut === coinTypeOut) {
|
|
146
|
+
finalCoins.push(resultCoin);
|
|
147
|
+
hops.forEach((hop) => {
|
|
148
|
+
const state = routeStates[hop.routeIndex];
|
|
149
|
+
state.completed = true;
|
|
150
|
+
state.currentHopIndex++;
|
|
151
|
+
});
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
// For merged swaps, we need to split the output proportionally
|
|
155
|
+
if (hops.length > 1) {
|
|
156
|
+
// Split output proportionally (except the last one which gets the remainder)
|
|
157
|
+
const splitAmounts = hops
|
|
158
|
+
.slice(1)
|
|
159
|
+
.map((hop) => hop.swap.returnAmount);
|
|
160
|
+
const splitCoins = splitAmounts.length > 0
|
|
161
|
+
? [resultCoin, ...tx.splitCoins(resultCoin, splitAmounts)]
|
|
162
|
+
: [resultCoin];
|
|
163
|
+
// Assign split coins back to routes
|
|
164
|
+
hops.forEach((hop, index) => {
|
|
165
|
+
const state = routeStates[hop.routeIndex];
|
|
166
|
+
state.currentCoin = splitCoins[index];
|
|
167
|
+
state.currentHopIndex++;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
// Single swap - simply update the route state
|
|
172
|
+
const state = routeStates[hops[0].routeIndex];
|
|
173
|
+
state.currentCoin = resultCoin;
|
|
174
|
+
state.currentHopIndex++;
|
|
175
|
+
}
|
|
176
|
+
})();
|
|
177
|
+
wavePromises.push(wavePromise);
|
|
178
|
+
}
|
|
179
|
+
// Wait for all swaps in this wave to complete
|
|
180
|
+
await Promise.all(wavePromises);
|
|
181
|
+
}
|
|
182
|
+
return finalCoins;
|
|
183
|
+
};
|
|
184
|
+
exports.optimize = optimize;
|
|
185
|
+
/**
|
|
186
|
+
* execute multiple swap in single transaction
|
|
187
|
+
*
|
|
188
|
+
* User must handle the coins from return
|
|
189
|
+
* @param param - MultiSwapParams
|
|
190
|
+
* @returns a map of coinType to coinObject
|
|
191
|
+
*/
|
|
192
|
+
const multiSwap = async ({ sender, slippageBps, swaps, tx, commission, }) => {
|
|
193
|
+
if (swaps.some((s) => (0, aggregator_1.isBluefinXRouting)(s.quote))) {
|
|
194
|
+
throw Error("BluefinX routing not supported yet");
|
|
195
|
+
}
|
|
196
|
+
// update oracles price if any
|
|
197
|
+
const pythMap = await (0, buildTx_1.updatePythPriceFeedsIfAny)(tx, swaps.map((s) => s.quote));
|
|
198
|
+
const map = {};
|
|
199
|
+
const config = await (0, config_1.getConfig)();
|
|
200
|
+
for (const { quote: sorResponse, coinIn } of swaps) {
|
|
201
|
+
const routes = (0, groupSwapRoutes_1.groupSwapRoutes)(sorResponse);
|
|
202
|
+
const splits = routes.map((group) => group[0]?.amount ?? "0");
|
|
203
|
+
const coinData = splits.length === 1
|
|
204
|
+
? [coinIn]
|
|
205
|
+
: [coinIn, ...tx.splitCoins(coinIn, splits.slice(1))];
|
|
206
|
+
const coinObjects = await (0, exports.optimize)(pythMap, config, routes, coinData, tx, sender);
|
|
207
|
+
if (coinObjects.length > 0) {
|
|
208
|
+
const mergeCoin = tx.add((0, buildTx_1.settle)(coinObjects, sorResponse, slippageBps, commission));
|
|
209
|
+
if (!map[(0, utils_1.normalizeStructTag)(sorResponse.tokenOut)]) {
|
|
210
|
+
map[(0, utils_1.normalizeStructTag)(sorResponse.tokenOut)] = [];
|
|
211
|
+
}
|
|
212
|
+
map[(0, utils_1.normalizeStructTag)(sorResponse.tokenOut)].push(mergeCoin);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const result = {};
|
|
216
|
+
for (const [tokenOut, coins] of Object.entries(map)) {
|
|
217
|
+
if (coins.length > 1) {
|
|
218
|
+
tx.mergeCoins(coins[0], coins.slice(1));
|
|
219
|
+
}
|
|
220
|
+
result[tokenOut] = coins[0];
|
|
221
|
+
}
|
|
222
|
+
tx.setSenderIfNotSet(sender);
|
|
223
|
+
return result;
|
|
224
|
+
};
|
|
225
|
+
exports.multiSwap = multiSwap;
|
|
@@ -26,7 +26,7 @@ exports.DEFAULT_CONFIG = {
|
|
|
26
26
|
},
|
|
27
27
|
cetus: {
|
|
28
28
|
name: "Cetus",
|
|
29
|
-
package: "
|
|
29
|
+
package: "0xfbb32ac0fa89a3cb0c56c745b688c6d2a53ac8e43447119ad822763997ffb9c3",
|
|
30
30
|
globalConfig: "0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f",
|
|
31
31
|
},
|
|
32
32
|
deepbook_v3: {
|
|
@@ -79,8 +79,8 @@ exports.DEFAULT_CONFIG = {
|
|
|
79
79
|
},
|
|
80
80
|
steamm: {
|
|
81
81
|
name: "Steamm",
|
|
82
|
-
package: "
|
|
83
|
-
script: "
|
|
82
|
+
package: "0x5ef2a1bca239764c8381ba26b758833060eadb8903682e4fb15e58c6406e2488",
|
|
83
|
+
script: "0x0755429cba577decc090009348987a89f4fb8397da27a3eaafc366794078af7d",
|
|
84
84
|
oracle: "0xe84b649199654d18c38e727212f5d8dacfc3cf78d60d0a7fc85fd589f280eb2b",
|
|
85
85
|
},
|
|
86
86
|
magma: {
|
|
@@ -90,16 +90,16 @@ exports.DEFAULT_CONFIG = {
|
|
|
90
90
|
},
|
|
91
91
|
haedal_pmm: {
|
|
92
92
|
name: "Haedal PMM",
|
|
93
|
-
package: "
|
|
93
|
+
package: "0x486622af8a7250a192e6ee97eed4f54e30343b764d9148bf1535b55f85155204",
|
|
94
94
|
},
|
|
95
95
|
momentum: {
|
|
96
96
|
name: "Momentum",
|
|
97
|
-
package: "
|
|
97
|
+
package: "0xcf60a40f45d46fc1e828871a647c1e25a0915dec860d2662eb10fdb382c3c1d1",
|
|
98
98
|
version: "0x2375a0b1ec12010aaea3b2545acfa2ad34cfbba03ce4b59f4c39e1e25eed1b2a",
|
|
99
99
|
},
|
|
100
100
|
bluefinx: {
|
|
101
101
|
name: "BluefinX",
|
|
102
|
-
package: "
|
|
102
|
+
package: "0x9633d611ea4b3a30751135cede2c7871980955473c1c7c883d43567e7e9b164e",
|
|
103
103
|
globalConfig: "0xc6b29a60c3924776bedc78df72c127ea52b86aeb655432979a38f13d742dedaa",
|
|
104
104
|
},
|
|
105
105
|
sevenk_v1: {
|
|
@@ -109,12 +109,18 @@ exports.DEFAULT_CONFIG = {
|
|
|
109
109
|
},
|
|
110
110
|
fullsail: {
|
|
111
111
|
name: "Fullsail",
|
|
112
|
-
package: "
|
|
112
|
+
package: "0xb3b98d4fda36acc2c2e66dba61f9149b341c38e97a532af802ebbb0c037b9d1f",
|
|
113
113
|
globalConfig: "0xe93baa80cb570b3a494cbf0621b2ba96bc993926d34dc92508c9446f9a05d615",
|
|
114
114
|
rewarderGlobalVault: "0xfb971d3a2fb98bde74e1c30ba15a3d8bef60a02789e59ae0b91660aeed3e64e1",
|
|
115
115
|
priceProvider: "0x854b2d2c0381bb656ec962f8b443eb082654384cf97885359d1956c7d76e33c9",
|
|
116
116
|
stats: "0x6822a33d1d971e040c32f7cc74507010d1fe786f7d06ab89135083ddb07d2dc2",
|
|
117
117
|
},
|
|
118
|
+
cetus_dlmm: {
|
|
119
|
+
name: "Cetus DLMM",
|
|
120
|
+
package: "0xa4c6f46bd6b456e6477bcddf0652e0d2d8fb4767e306533e6e885302ee28cfab",
|
|
121
|
+
globalConfig: "0xf31b605d117f959b9730e8c07b08b856cb05143c5e81d5751c90d2979e82f599",
|
|
122
|
+
version: "0x05370b2d656612dd5759cbe80463de301e3b94a921dfc72dd9daa2ecdeb2d0a8",
|
|
123
|
+
},
|
|
118
124
|
};
|
|
119
125
|
let config = exports.DEFAULT_CONFIG;
|
|
120
126
|
let configTs = 0;
|
|
@@ -29,6 +29,7 @@ exports.DEFAULT_SOURCES = [
|
|
|
29
29
|
"momentum",
|
|
30
30
|
"sevenk_v1",
|
|
31
31
|
"fullsail",
|
|
32
|
+
"cetus_dlmm",
|
|
32
33
|
];
|
|
33
34
|
exports.ORACLE_BASED_SOURCES = new Set([
|
|
34
35
|
"obric",
|
|
@@ -37,7 +38,7 @@ exports.ORACLE_BASED_SOURCES = new Set([
|
|
|
37
38
|
"steamm_oracle_quoter",
|
|
38
39
|
"steamm_oracle_quoter_v2",
|
|
39
40
|
]);
|
|
40
|
-
async function getQuote({ tokenIn, tokenOut, amountIn, sources: _sources = exports.DEFAULT_SOURCES, commissionBps, targetPools, excludedPools, taker, isSponsored, }) {
|
|
41
|
+
async function getQuote({ tokenIn, tokenOut, amountIn, sources: _sources = exports.DEFAULT_SOURCES, commissionBps, targetPools, excludedPools, taker, isSponsored, api, }) {
|
|
41
42
|
let sources = _sources;
|
|
42
43
|
if (isSponsored) {
|
|
43
44
|
sources = _sources.filter((s) => !exports.ORACLE_BASED_SOURCES.has(s));
|
|
@@ -57,7 +58,7 @@ async function getQuote({ tokenIn, tokenOut, amountIn, sources: _sources = expor
|
|
|
57
58
|
if (taker) {
|
|
58
59
|
params.append("taker", taker);
|
|
59
60
|
}
|
|
60
|
-
const response = await (0, fetchClient_1.fetchClient)(`${apiEndpoints_1.API_ENDPOINTS.MAIN}/quote?${params}`);
|
|
61
|
+
const response = await (0, fetchClient_1.fetchClient)(`${api || apiEndpoints_1.API_ENDPOINTS.MAIN}/quote?${params}`);
|
|
61
62
|
if (!response.ok) {
|
|
62
63
|
let responseText;
|
|
63
64
|
try {
|
|
@@ -15,6 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./buildTx"), exports);
|
|
18
|
+
__exportStar(require("./buildTxV2"), exports);
|
|
18
19
|
__exportStar(require("./estimateGasFee"), exports);
|
|
19
20
|
__exportStar(require("./executeTx"), exports);
|
|
20
21
|
__exportStar(require("./getQuote"), exports);
|
package/lib/cjs/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.
|
|
17
|
+
exports.setSuiClient = exports.placeLimitOrder = exports.placeDcaOrder = exports.multiSwap = exports.getTokenPrices = exports.getTokenPrice = exports.getSwapHistory = exports.getSuiPrice = exports.getSuiClient = exports.getQuote = exports.getOpenLimitOrders = exports.getOpenDcaOrders = exports.getDcaOrderExecutions = exports.getClosedLimitOrders = exports.getClosedDcaOrders = exports.executeTx = exports.executeBluefinTx = exports.estimateGasFee = exports.DEFAULT_SOURCES = exports.Config = exports.claimExpiredLimitOrder = exports.cancelLimitOrder = exports.cancelDcaOrder = exports.buildTxV2 = exports.buildTx = void 0;
|
|
18
18
|
__exportStar(require("./types/aggregator"), exports);
|
|
19
19
|
const config_1 = require("./config");
|
|
20
20
|
Object.defineProperty(exports, "Config", { enumerable: true, get: function () { return config_1.Config; } });
|
|
@@ -26,11 +26,13 @@ const client_1 = require("./libs/protocols/bluefinx/client");
|
|
|
26
26
|
Object.defineProperty(exports, "executeBluefinTx", { enumerable: true, get: function () { return client_1.executeBluefinTx; } });
|
|
27
27
|
const swap_1 = require("./features/swap");
|
|
28
28
|
Object.defineProperty(exports, "buildTx", { enumerable: true, get: function () { return swap_1.buildTx; } });
|
|
29
|
+
Object.defineProperty(exports, "buildTxV2", { enumerable: true, get: function () { return swap_1.buildTxV2; } });
|
|
30
|
+
Object.defineProperty(exports, "DEFAULT_SOURCES", { enumerable: true, get: function () { return swap_1.DEFAULT_SOURCES; } });
|
|
29
31
|
Object.defineProperty(exports, "estimateGasFee", { enumerable: true, get: function () { return swap_1.estimateGasFee; } });
|
|
30
32
|
Object.defineProperty(exports, "executeTx", { enumerable: true, get: function () { return swap_1.executeTx; } });
|
|
31
33
|
Object.defineProperty(exports, "getQuote", { enumerable: true, get: function () { return swap_1.getQuote; } });
|
|
32
34
|
Object.defineProperty(exports, "getSwapHistory", { enumerable: true, get: function () { return swap_1.getSwapHistory; } });
|
|
33
|
-
Object.defineProperty(exports, "
|
|
35
|
+
Object.defineProperty(exports, "multiSwap", { enumerable: true, get: function () { return swap_1.multiSwap; } });
|
|
34
36
|
const limitDca_1 = require("./features/limitDca");
|
|
35
37
|
Object.defineProperty(exports, "cancelDcaOrder", { enumerable: true, get: function () { return limitDca_1.cancelDcaOrder; } });
|
|
36
38
|
Object.defineProperty(exports, "cancelLimitOrder", { enumerable: true, get: function () { return limitDca_1.cancelLimitOrder; } });
|
|
@@ -61,6 +63,8 @@ exports.default = {
|
|
|
61
63
|
getQuote: swap_1.getQuote,
|
|
62
64
|
estimateGasFee: swap_1.estimateGasFee,
|
|
63
65
|
buildTx: swap_1.buildTx,
|
|
66
|
+
buildTxV2: swap_1.buildTxV2,
|
|
67
|
+
multiSwap: swap_1.multiSwap,
|
|
64
68
|
getSwapHistory: swap_1.getSwapHistory,
|
|
65
69
|
executeTx: swap_1.executeTx,
|
|
66
70
|
executeBluefinTx: client_1.executeBluefinTx,
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CetusDLMMContract = void 0;
|
|
4
|
+
const utils_1 = require("@mysten/sui/utils");
|
|
5
|
+
const sui_1 = require("../../utils/sui");
|
|
6
|
+
const base_1 = require("./base");
|
|
7
|
+
class CetusDLMMContract extends base_1.BaseContract {
|
|
8
|
+
async swap(tx) {
|
|
9
|
+
const config = this.config.cetus_dlmm;
|
|
10
|
+
const [x, y, receipt] = tx.moveCall({
|
|
11
|
+
target: `${config.package}::pool::flash_swap`,
|
|
12
|
+
typeArguments: [this.swapInfo.coinX.type, this.swapInfo.coinY.type],
|
|
13
|
+
arguments: [
|
|
14
|
+
tx.object(this.swapInfo.poolId),
|
|
15
|
+
tx.pure.bool(this.swapInfo.swapXtoY),
|
|
16
|
+
tx.pure.bool(true), // exact in
|
|
17
|
+
this.getInputCoinValue(tx),
|
|
18
|
+
tx.object(config.globalConfig),
|
|
19
|
+
tx.object(config.version),
|
|
20
|
+
tx.object(utils_1.SUI_CLOCK_OBJECT_ID),
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
const debtX = this.swapInfo.swapXtoY
|
|
24
|
+
? sui_1.SuiUtils.coinIntoBalance(tx, this.swapInfo.coinX.type, this.inputCoinObject)
|
|
25
|
+
: sui_1.SuiUtils.zeroBalance(tx, this.swapInfo.coinX.type);
|
|
26
|
+
const debtY = this.swapInfo.swapXtoY
|
|
27
|
+
? sui_1.SuiUtils.zeroBalance(tx, this.swapInfo.coinY.type)
|
|
28
|
+
: sui_1.SuiUtils.coinIntoBalance(tx, this.swapInfo.coinY.type, this.inputCoinObject);
|
|
29
|
+
tx.moveCall({
|
|
30
|
+
target: `${config.package}::pool::repay_flash_swap`,
|
|
31
|
+
typeArguments: [this.swapInfo.coinX.type, this.swapInfo.coinY.type],
|
|
32
|
+
arguments: [
|
|
33
|
+
tx.object(this.swapInfo.poolId),
|
|
34
|
+
debtX,
|
|
35
|
+
debtY,
|
|
36
|
+
receipt,
|
|
37
|
+
tx.object(config.version),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
const [destroyType, destroyCoin, outType, outBalance] = this.swapInfo
|
|
41
|
+
.swapXtoY
|
|
42
|
+
? [this.swapInfo.coinX.type, x, this.swapInfo.coinY.type, y]
|
|
43
|
+
: [this.swapInfo.coinY.type, y, this.swapInfo.coinX.type, x];
|
|
44
|
+
sui_1.SuiUtils.balanceDestroyZero(tx, destroyType, destroyCoin);
|
|
45
|
+
return sui_1.SuiUtils.coinFromBalance(tx, outType, outBalance);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.CetusDLMMContract = CetusDLMMContract;
|