@cetusprotocol/aggregator-sdk 1.4.0 → 1.4.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/README.md +201 -61
- package/dist/index.d.mts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +250 -1
- package/dist/index.mjs +250 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -79,11 +79,11 @@ The new Aggregator Client V3 offers significant improvements over the previous v
|
|
|
79
79
|
|
|
80
80
|
- **Increased Reliability**: More robust transaction execution with better error handling
|
|
81
81
|
|
|
82
|
-
## Migration from
|
|
82
|
+
## Migration from V2 to V3 API
|
|
83
83
|
|
|
84
84
|
### Installation
|
|
85
85
|
|
|
86
|
-
Both
|
|
86
|
+
Both V2 and V3 APIs use the same package:
|
|
87
87
|
|
|
88
88
|
```bash
|
|
89
89
|
npm install @cetusprotocol/aggregator-sdk
|
|
@@ -91,61 +91,67 @@ npm install @cetusprotocol/aggregator-sdk
|
|
|
91
91
|
|
|
92
92
|
### Key Changes
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
**Important:** Both V2 and V3 use the same `AggregatorClient` class. The main differences are:
|
|
95
|
+
- **Return types**: V3 uses `RouterDataV3` (with flattened `paths`) instead of V2's `RouterData` (with nested `routes`)
|
|
96
|
+
- **Swap methods**: V3 introduces `fastRouterSwap()` for automatic coin handling
|
|
97
|
+
- **Transaction structure**: V3 optimizes gas through transaction merging
|
|
98
|
+
|
|
99
|
+
1. **Client Initialization (Same for both)**
|
|
95
100
|
|
|
96
101
|
```typescript
|
|
97
|
-
|
|
98
|
-
const client = new AggregatorClient({})
|
|
102
|
+
import { AggregatorClient } from "@cetusprotocol/aggregator-sdk"
|
|
99
103
|
|
|
100
|
-
|
|
101
|
-
|
|
104
|
+
const client = new AggregatorClient({
|
|
105
|
+
// Optional: Add custom configuration
|
|
106
|
+
})
|
|
102
107
|
```
|
|
103
108
|
|
|
104
|
-
2. **Router Finding**
|
|
109
|
+
2. **Router Finding (API unchanged, but return type differs)**
|
|
105
110
|
|
|
106
111
|
```typescript
|
|
107
|
-
|
|
112
|
+
import BN from "bn.js"
|
|
113
|
+
|
|
114
|
+
// Works with both V2 and V3
|
|
108
115
|
const routers = await client.findRouters({
|
|
109
116
|
from: "0x2::sui::SUI",
|
|
110
|
-
target:
|
|
111
|
-
"0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS",
|
|
117
|
+
target: "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS",
|
|
112
118
|
amount: new BN(1000000),
|
|
113
119
|
byAmountIn: true,
|
|
114
120
|
})
|
|
121
|
+
|
|
122
|
+
// V2 returns: RouterData with routes[]
|
|
123
|
+
// V3 returns: RouterDataV3 with paths[]
|
|
115
124
|
```
|
|
116
125
|
|
|
117
126
|
3. **Transaction Building**
|
|
118
127
|
|
|
119
128
|
```typescript
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
txb,
|
|
124
|
-
inputCoin,
|
|
125
|
-
slippage: 0.01,
|
|
126
|
-
})
|
|
129
|
+
import { Transaction } from "@mysten/sui/transactions"
|
|
130
|
+
|
|
131
|
+
const txb = new Transaction()
|
|
127
132
|
|
|
128
|
-
// V3 Method (Recommended)
|
|
133
|
+
// V3 Method (Recommended) - Automatic coin handling
|
|
129
134
|
await client.fastRouterSwap({
|
|
130
|
-
routers,
|
|
135
|
+
router: routers,
|
|
131
136
|
txb,
|
|
132
137
|
slippage: 0.01,
|
|
133
138
|
})
|
|
134
139
|
|
|
135
|
-
// V3 Alternative
|
|
140
|
+
// V3 Alternative - Manual coin handling for PTB building
|
|
136
141
|
const targetCoin = await client.routerSwap({
|
|
137
|
-
routers,
|
|
142
|
+
router: routers,
|
|
138
143
|
txb,
|
|
139
|
-
inputCoin,
|
|
144
|
+
inputCoin, // TransactionObjectArgument
|
|
140
145
|
slippage: 0.01,
|
|
141
146
|
})
|
|
142
147
|
```
|
|
143
148
|
|
|
144
|
-
4. **Benefits of Migration**
|
|
149
|
+
4. **Benefits of V3 Migration**
|
|
145
150
|
- Reduced gas costs through transaction merging
|
|
146
|
-
- Better transaction traceability
|
|
151
|
+
- Better transaction traceability on-chain
|
|
147
152
|
- Improved error handling and reliability
|
|
148
153
|
- Access to latest DEX integrations
|
|
154
|
+
- Automatic coin management with `fastRouterSwap()`
|
|
149
155
|
|
|
150
156
|
## Install
|
|
151
157
|
|
|
@@ -157,74 +163,208 @@ npm install @cetusprotocol/aggregator-sdk
|
|
|
157
163
|
|
|
158
164
|
## Usage
|
|
159
165
|
|
|
160
|
-
###
|
|
166
|
+
### Complete Example with All Imports
|
|
161
167
|
|
|
162
168
|
```typescript
|
|
163
|
-
|
|
169
|
+
import { AggregatorClient } from "@cetusprotocol/aggregator-sdk"
|
|
170
|
+
import { Transaction } from "@mysten/sui/transactions"
|
|
171
|
+
import BN from "bn.js"
|
|
172
|
+
import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
|
|
173
|
+
|
|
174
|
+
// Initialize your keypair (example using Ed25519)
|
|
175
|
+
const keypair = Ed25519Keypair.deriveKeypair("your-mnemonic-phrase")
|
|
164
176
|
```
|
|
165
177
|
|
|
166
|
-
###
|
|
178
|
+
### 1. Initialize Client
|
|
167
179
|
|
|
168
180
|
```typescript
|
|
169
|
-
|
|
181
|
+
import { Env } from "@cetusprotocol/aggregator-sdk"
|
|
182
|
+
import { getFullnodeUrl, SuiClient } from "@mysten/sui/client"
|
|
183
|
+
|
|
184
|
+
const client = new AggregatorClient({
|
|
185
|
+
// Optional configuration parameters:
|
|
186
|
+
|
|
187
|
+
// Network environment (default: Mainnet)
|
|
188
|
+
env: Env.Mainnet, // or Env.Testnet
|
|
189
|
+
|
|
190
|
+
// Custom API endpoint for aggregator service
|
|
191
|
+
// endpoint: "https://api-sui.cetus.zone",
|
|
192
|
+
|
|
193
|
+
// Custom Sui client (default: mainnet RPC)
|
|
194
|
+
// client: new SuiClient({ url: getFullnodeUrl("mainnet") }),
|
|
195
|
+
|
|
196
|
+
// Partner ID for revenue sharing
|
|
197
|
+
// partner: "your-partner-id",
|
|
198
|
+
|
|
199
|
+
// CETUS DLMM specific partner ID
|
|
200
|
+
// cetusDlmmPartner: "your-dlmm-partner-id",
|
|
201
|
+
|
|
202
|
+
// Overlay fee rate (0 to 0.01 for 0-1%)
|
|
203
|
+
// overlayFeeRate: 0.001, // 0.1%
|
|
204
|
+
|
|
205
|
+
// Overlay fee receiver address
|
|
206
|
+
// overlayFeeReceiver: "0x...",
|
|
207
|
+
|
|
208
|
+
// Custom Pyth oracle URLs
|
|
209
|
+
// pythUrls: ["https://hermes.pyth.network"],
|
|
210
|
+
|
|
211
|
+
// API key for rate limiting
|
|
212
|
+
// apiKey: "your-api-key",
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### 2. Find Best Router
|
|
217
|
+
|
|
218
|
+
Get the optimal swap route from the aggregator service:
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const amount = new BN(1000000) // 1 SUI (with 6 decimals)
|
|
170
222
|
const from = "0x2::sui::SUI"
|
|
171
|
-
const target =
|
|
172
|
-
"0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS"
|
|
223
|
+
const target = "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS"
|
|
173
224
|
|
|
174
225
|
const routers = await client.findRouters({
|
|
175
226
|
from,
|
|
176
227
|
target,
|
|
177
228
|
amount,
|
|
178
|
-
byAmountIn: true, // true
|
|
229
|
+
byAmountIn: true, // true = fixed input amount, false = fixed output amount
|
|
230
|
+
// Optional parameters:
|
|
231
|
+
// depth: 3, // Maximum number of hops
|
|
232
|
+
// providers: ["CETUS", "TURBOS"], // Limit to specific DEXs
|
|
179
233
|
})
|
|
234
|
+
|
|
235
|
+
// Check if a valid route was found
|
|
236
|
+
if (!routers || routers.insufficientLiquidity) {
|
|
237
|
+
console.error("No valid route found or insufficient liquidity")
|
|
238
|
+
process.exit(1)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log(`Expected output: ${routers.amountOut.toString()}`)
|
|
180
242
|
```
|
|
181
243
|
|
|
182
|
-
### 3.
|
|
244
|
+
### 3. Fast Swap (Recommended - Automatic Coin Handling)
|
|
245
|
+
|
|
246
|
+
The easiest way to execute a swap with automatic coin management:
|
|
183
247
|
|
|
184
248
|
```typescript
|
|
185
249
|
const txb = new Transaction()
|
|
186
250
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
251
|
+
await client.fastRouterSwap({
|
|
252
|
+
router: routers,
|
|
253
|
+
txb,
|
|
254
|
+
slippage: 0.01, // 1% slippage tolerance
|
|
255
|
+
// Optional:
|
|
256
|
+
// partner: "your-partner-id",
|
|
257
|
+
// payDeepFeeAmount: 1000000, // For DeepBook V3 pools
|
|
258
|
+
})
|
|
193
259
|
|
|
194
|
-
|
|
260
|
+
// Simulate the transaction first
|
|
261
|
+
const dryRunResult = await client.devInspectTransactionBlock(txb, keypair)
|
|
195
262
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
263
|
+
if (dryRunResult.effects.status.status === "success") {
|
|
264
|
+
console.log("Simulation successful, executing transaction...")
|
|
265
|
+
|
|
266
|
+
// Execute the actual transaction
|
|
267
|
+
const result = await client.signAndExecuteTransaction(txb, keypair)
|
|
268
|
+
console.log("Transaction result:", result)
|
|
269
|
+
} else {
|
|
270
|
+
console.error("Simulation failed:", dryRunResult.effects.status)
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### 4. Manual Swap (Advanced - For Custom PTB Building)
|
|
275
|
+
|
|
276
|
+
Use this when you need to build complex programmable transaction blocks:
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { coinWithBalance } from "@mysten/sui/transactions"
|
|
280
|
+
|
|
281
|
+
const txb = new Transaction()
|
|
282
|
+
|
|
283
|
+
// Create input coin object
|
|
284
|
+
// Option 1: From existing coin object
|
|
285
|
+
const inputCoin = txb.object("0x...") // Your coin object ID
|
|
286
|
+
|
|
287
|
+
// Option 2: Create coin with specific balance
|
|
288
|
+
// const inputCoin = coinWithBalance({
|
|
289
|
+
// type: from,
|
|
290
|
+
// balance: amount.toString()
|
|
291
|
+
// })
|
|
292
|
+
|
|
293
|
+
// Execute swap and get output coin
|
|
294
|
+
const targetCoin = await client.routerSwap({
|
|
295
|
+
router: routers,
|
|
296
|
+
txb,
|
|
297
|
+
inputCoin,
|
|
298
|
+
slippage: 0.01, // 1% slippage tolerance
|
|
299
|
+
// Optional:
|
|
300
|
+
// partner: "your-partner-id",
|
|
301
|
+
// deepbookv3DeepFee: deepCoinObject, // For DeepBook V3
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
// Use the target coin in your custom PTB logic
|
|
305
|
+
// For example, transfer to recipient or use in another DeFi protocol
|
|
306
|
+
txb.transferObjects([targetCoin], keypair.toSuiAddress())
|
|
307
|
+
|
|
308
|
+
// Or destroy if sending to current address
|
|
309
|
+
// client.transferOrDestroyCoin(txb, targetCoin, target)
|
|
310
|
+
|
|
311
|
+
// Simulate and execute
|
|
312
|
+
const dryRunResult = await client.devInspectTransactionBlock(txb, keypair)
|
|
313
|
+
|
|
314
|
+
if (dryRunResult.effects.status.status === "success") {
|
|
315
|
+
console.log("Simulation successful, executing transaction...")
|
|
316
|
+
const result = await client.signAndExecuteTransaction(txb, keypair)
|
|
317
|
+
console.log("Transaction result:", result)
|
|
318
|
+
} else {
|
|
319
|
+
console.error("Simulation failed:", dryRunResult.effects.status)
|
|
201
320
|
}
|
|
202
321
|
```
|
|
203
322
|
|
|
204
|
-
###
|
|
323
|
+
### 5. Advanced: Swap with Maximum Input Amount
|
|
324
|
+
|
|
325
|
+
Protect against excessive input amounts:
|
|
205
326
|
|
|
206
327
|
```typescript
|
|
207
328
|
const txb = new Transaction()
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
329
|
+
const inputCoin = txb.object("0x...") // Your coin object
|
|
330
|
+
|
|
331
|
+
const targetCoin = await client.routerSwapWithMaxAmountIn({
|
|
332
|
+
router: routers,
|
|
333
|
+
txb,
|
|
334
|
+
inputCoin,
|
|
335
|
+
slippage: 0.01,
|
|
336
|
+
maxAmountIn: new BN(2000000), // Maximum 2 SUI allowed
|
|
337
|
+
})
|
|
338
|
+
|
|
339
|
+
// Transaction will abort if input amount exceeds maxAmountIn
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Error Handling
|
|
343
|
+
|
|
344
|
+
```typescript
|
|
345
|
+
try {
|
|
346
|
+
const routers = await client.findRouters({
|
|
347
|
+
from,
|
|
348
|
+
target,
|
|
349
|
+
amount,
|
|
350
|
+
byAmountIn: true,
|
|
216
351
|
})
|
|
217
352
|
|
|
218
|
-
|
|
219
|
-
|
|
353
|
+
if (!routers) {
|
|
354
|
+
throw new Error("No route found")
|
|
355
|
+
}
|
|
220
356
|
|
|
221
|
-
|
|
357
|
+
if (routers.insufficientLiquidity) {
|
|
358
|
+
throw new Error("Insufficient liquidity for this swap")
|
|
359
|
+
}
|
|
222
360
|
|
|
223
|
-
if (
|
|
224
|
-
|
|
225
|
-
const result = await client.signAndExecuteTransaction(txb, keypair)
|
|
361
|
+
if (routers.error) {
|
|
362
|
+
throw new Error(`Router error: ${routers.error.msg}`)
|
|
226
363
|
}
|
|
227
|
-
|
|
364
|
+
|
|
365
|
+
// Proceed with swap...
|
|
366
|
+
} catch (error) {
|
|
367
|
+
console.error("Swap failed:", error)
|
|
228
368
|
}
|
|
229
369
|
```
|
|
230
370
|
|
package/dist/index.d.mts
CHANGED
|
@@ -9,7 +9,7 @@ import { Signer } from '@mysten/sui/cryptography';
|
|
|
9
9
|
interface FindRouterParams {
|
|
10
10
|
from: string;
|
|
11
11
|
target: string;
|
|
12
|
-
amount: BN;
|
|
12
|
+
amount: BN | string | number | bigint;
|
|
13
13
|
byAmountIn: boolean;
|
|
14
14
|
depth?: number;
|
|
15
15
|
splitAlgorithm?: string;
|
|
@@ -20,11 +20,11 @@ interface FindRouterParams {
|
|
|
20
20
|
}
|
|
21
21
|
interface MergeSwapFromCoin {
|
|
22
22
|
coinType: string;
|
|
23
|
-
amount: BN | string | number;
|
|
23
|
+
amount: BN | string | number | bigint;
|
|
24
24
|
}
|
|
25
25
|
interface MergeSwapFromCoin {
|
|
26
26
|
coinType: string;
|
|
27
|
-
amount: BN | string | number;
|
|
27
|
+
amount: BN | string | number | bigint;
|
|
28
28
|
}
|
|
29
29
|
interface MergeSwapParams {
|
|
30
30
|
target: string;
|
|
@@ -394,9 +394,24 @@ declare class AggregatorClient {
|
|
|
394
394
|
executeFlexibleInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, expectedAmountOut: string, amountLimit: string, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<void>;
|
|
395
395
|
newDexRouterV3(provider: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): DexRouter;
|
|
396
396
|
expectInputSwapV3(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, expectAmountOut: string, amountOutLimit: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): TransactionObjectArgument;
|
|
397
|
+
expectInputSwapV3WithMaxAmountIn(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, maxAmountIn: BN, expectAmountOut: string, amountOutLimit: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): TransactionObjectArgument;
|
|
397
398
|
expectOutputSwapV3(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, amountOut: string, _amountLimit: string, // it will set when build inputcoin
|
|
398
399
|
partner?: string): TransactionObjectArgument;
|
|
400
|
+
expectOutputSwapV3WithMaxAmountIn(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, maxAmountIn: BN, amountOut: string, _amountLimit: string, // it will set when build inputcoin
|
|
401
|
+
partner?: string): TransactionObjectArgument;
|
|
399
402
|
routerSwap(params: BuildRouterSwapParamsV3): Promise<TransactionObjectArgument>;
|
|
403
|
+
/**
|
|
404
|
+
* Router swap with max amount in validation.
|
|
405
|
+
* This method validates that the input coin amount does not exceed maxAmountIn.
|
|
406
|
+
* If the validation fails, the transaction will abort with an error.
|
|
407
|
+
*
|
|
408
|
+
* @param params - Router swap parameters with maxAmountIn
|
|
409
|
+
* @returns TransactionObjectArgument - The output coin from the swap
|
|
410
|
+
* @throws Error if input coin amount exceeds maxAmountIn
|
|
411
|
+
*/
|
|
412
|
+
routerSwapWithMaxAmountIn(params: BuildRouterSwapParamsV3 & {
|
|
413
|
+
maxAmountIn: BN;
|
|
414
|
+
}): Promise<TransactionObjectArgument>;
|
|
400
415
|
fastRouterSwap(params: BuildFastRouterSwapParamsV3): Promise<void>;
|
|
401
416
|
mergeSwap(params: BuildMergeSwapParams): Promise<TransactionObjectArgument>;
|
|
402
417
|
fastMergeSwap(params: BuildFastMergeSwapParams): Promise<void>;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,7 +9,7 @@ import { Signer } from '@mysten/sui/cryptography';
|
|
|
9
9
|
interface FindRouterParams {
|
|
10
10
|
from: string;
|
|
11
11
|
target: string;
|
|
12
|
-
amount: BN;
|
|
12
|
+
amount: BN | string | number | bigint;
|
|
13
13
|
byAmountIn: boolean;
|
|
14
14
|
depth?: number;
|
|
15
15
|
splitAlgorithm?: string;
|
|
@@ -20,11 +20,11 @@ interface FindRouterParams {
|
|
|
20
20
|
}
|
|
21
21
|
interface MergeSwapFromCoin {
|
|
22
22
|
coinType: string;
|
|
23
|
-
amount: BN | string | number;
|
|
23
|
+
amount: BN | string | number | bigint;
|
|
24
24
|
}
|
|
25
25
|
interface MergeSwapFromCoin {
|
|
26
26
|
coinType: string;
|
|
27
|
-
amount: BN | string | number;
|
|
27
|
+
amount: BN | string | number | bigint;
|
|
28
28
|
}
|
|
29
29
|
interface MergeSwapParams {
|
|
30
30
|
target: string;
|
|
@@ -394,9 +394,24 @@ declare class AggregatorClient {
|
|
|
394
394
|
executeFlexibleInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, expectedAmountOut: string, amountLimit: string, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<void>;
|
|
395
395
|
newDexRouterV3(provider: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): DexRouter;
|
|
396
396
|
expectInputSwapV3(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, expectAmountOut: string, amountOutLimit: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): TransactionObjectArgument;
|
|
397
|
+
expectInputSwapV3WithMaxAmountIn(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, maxAmountIn: BN, expectAmountOut: string, amountOutLimit: string, pythPriceIDs: Map<string, string>, partner?: string, cetusDlmmPartner?: string): TransactionObjectArgument;
|
|
397
398
|
expectOutputSwapV3(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, amountOut: string, _amountLimit: string, // it will set when build inputcoin
|
|
398
399
|
partner?: string): TransactionObjectArgument;
|
|
400
|
+
expectOutputSwapV3WithMaxAmountIn(txb: Transaction, inputCoin: TransactionObjectArgument, routerData: RouterDataV3, maxAmountIn: BN, amountOut: string, _amountLimit: string, // it will set when build inputcoin
|
|
401
|
+
partner?: string): TransactionObjectArgument;
|
|
399
402
|
routerSwap(params: BuildRouterSwapParamsV3): Promise<TransactionObjectArgument>;
|
|
403
|
+
/**
|
|
404
|
+
* Router swap with max amount in validation.
|
|
405
|
+
* This method validates that the input coin amount does not exceed maxAmountIn.
|
|
406
|
+
* If the validation fails, the transaction will abort with an error.
|
|
407
|
+
*
|
|
408
|
+
* @param params - Router swap parameters with maxAmountIn
|
|
409
|
+
* @returns TransactionObjectArgument - The output coin from the swap
|
|
410
|
+
* @throws Error if input coin amount exceeds maxAmountIn
|
|
411
|
+
*/
|
|
412
|
+
routerSwapWithMaxAmountIn(params: BuildRouterSwapParamsV3 & {
|
|
413
|
+
maxAmountIn: BN;
|
|
414
|
+
}): Promise<TransactionObjectArgument>;
|
|
400
415
|
fastRouterSwap(params: BuildFastRouterSwapParamsV3): Promise<void>;
|
|
401
416
|
mergeSwap(params: BuildMergeSwapParams): Promise<TransactionObjectArgument>;
|
|
402
417
|
fastMergeSwap(params: BuildFastMergeSwapParams): Promise<void>;
|
package/dist/index.js
CHANGED
|
@@ -3453,7 +3453,7 @@ var AGGREGATOR_V3_CONFIG = {
|
|
|
3453
3453
|
};
|
|
3454
3454
|
|
|
3455
3455
|
// src/api.ts
|
|
3456
|
-
var SDK_VERSION =
|
|
3456
|
+
var SDK_VERSION = 1010401;
|
|
3457
3457
|
function parseRouterResponse(data, byAmountIn) {
|
|
3458
3458
|
let packages = /* @__PURE__ */ new Map();
|
|
3459
3459
|
if (data.packages) {
|
|
@@ -7759,6 +7759,37 @@ function newSwapContext(params, txb) {
|
|
|
7759
7759
|
});
|
|
7760
7760
|
return swap_context;
|
|
7761
7761
|
}
|
|
7762
|
+
function newSwapContextV2(params, txb) {
|
|
7763
|
+
const {
|
|
7764
|
+
quoteID,
|
|
7765
|
+
fromCoinType,
|
|
7766
|
+
targetCoinType,
|
|
7767
|
+
maxAmountIn,
|
|
7768
|
+
expectAmountOut,
|
|
7769
|
+
amountOutLimit,
|
|
7770
|
+
inputCoin,
|
|
7771
|
+
feeRate,
|
|
7772
|
+
feeRecipient,
|
|
7773
|
+
aggregatorPublishedAt,
|
|
7774
|
+
packages
|
|
7775
|
+
} = params;
|
|
7776
|
+
const publishedAt = getAggregatorPublishedAt(packages, aggregatorPublishedAt);
|
|
7777
|
+
const args = [
|
|
7778
|
+
txb.pure.string(quoteID),
|
|
7779
|
+
txb.pure.u64(maxAmountIn.toString()),
|
|
7780
|
+
txb.pure.u64(expectAmountOut.toString()),
|
|
7781
|
+
txb.pure.u64(amountOutLimit.toString()),
|
|
7782
|
+
inputCoin,
|
|
7783
|
+
txb.pure.u32(Number(feeRate.toString())),
|
|
7784
|
+
txb.pure.address(feeRecipient)
|
|
7785
|
+
];
|
|
7786
|
+
const swap_context = txb.moveCall({
|
|
7787
|
+
target: `${publishedAt}::router::new_swap_context_v2`,
|
|
7788
|
+
typeArguments: [fromCoinType, targetCoinType],
|
|
7789
|
+
arguments: args
|
|
7790
|
+
});
|
|
7791
|
+
return swap_context;
|
|
7792
|
+
}
|
|
7762
7793
|
function confirmSwap(params, txb) {
|
|
7763
7794
|
const { swapContext, targetCoinType, aggregatorPublishedAt, packages } = params;
|
|
7764
7795
|
const publishedAt = getAggregatorPublishedAt(packages, aggregatorPublishedAt);
|
|
@@ -8760,6 +8791,53 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8760
8791
|
);
|
|
8761
8792
|
return outputCoin;
|
|
8762
8793
|
}
|
|
8794
|
+
expectInputSwapV3WithMaxAmountIn(txb, inputCoin, routerData, maxAmountIn, expectAmountOut, amountOutLimit, pythPriceIDs, partner, cetusDlmmPartner) {
|
|
8795
|
+
if (routerData.quoteID == null) {
|
|
8796
|
+
throw new Error(CLIENT_CONFIG.ERRORS.QUOTE_ID_REQUIRED);
|
|
8797
|
+
}
|
|
8798
|
+
const processedData = processFlattenRoutes(routerData);
|
|
8799
|
+
const swapCtx = newSwapContextV2(
|
|
8800
|
+
{
|
|
8801
|
+
quoteID: processedData.quoteID,
|
|
8802
|
+
fromCoinType: processedData.fromCoinType,
|
|
8803
|
+
targetCoinType: processedData.targetCoinType,
|
|
8804
|
+
maxAmountIn,
|
|
8805
|
+
expectAmountOut,
|
|
8806
|
+
amountOutLimit,
|
|
8807
|
+
inputCoin,
|
|
8808
|
+
feeRate: this.overlayFeeRate,
|
|
8809
|
+
feeRecipient: this.overlayFeeReceiver,
|
|
8810
|
+
packages: processedData.packages
|
|
8811
|
+
},
|
|
8812
|
+
txb
|
|
8813
|
+
);
|
|
8814
|
+
let dexRouters = /* @__PURE__ */ new Map();
|
|
8815
|
+
for (const flattenedPath of processedData.flattenedPaths) {
|
|
8816
|
+
const path = flattenedPath.path;
|
|
8817
|
+
if (!dexRouters.has(path.provider)) {
|
|
8818
|
+
dexRouters.set(
|
|
8819
|
+
path.provider,
|
|
8820
|
+
this.newDexRouterV3(
|
|
8821
|
+
path.provider,
|
|
8822
|
+
pythPriceIDs,
|
|
8823
|
+
partner,
|
|
8824
|
+
cetusDlmmPartner
|
|
8825
|
+
)
|
|
8826
|
+
);
|
|
8827
|
+
}
|
|
8828
|
+
const dex = dexRouters.get(path.provider);
|
|
8829
|
+
dex.swap(txb, flattenedPath, swapCtx, { pythPriceIDs });
|
|
8830
|
+
}
|
|
8831
|
+
const outputCoin = confirmSwap(
|
|
8832
|
+
{
|
|
8833
|
+
swapContext: swapCtx,
|
|
8834
|
+
targetCoinType: processedData.targetCoinType,
|
|
8835
|
+
packages: processedData.packages
|
|
8836
|
+
},
|
|
8837
|
+
txb
|
|
8838
|
+
);
|
|
8839
|
+
return outputCoin;
|
|
8840
|
+
}
|
|
8763
8841
|
expectOutputSwapV3(txb, inputCoin, routerData, amountOut, _amountLimit, partner) {
|
|
8764
8842
|
const receipts = [];
|
|
8765
8843
|
const dex = new CetusRouter(this.env, partner);
|
|
@@ -8869,6 +8947,116 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8869
8947
|
);
|
|
8870
8948
|
return outputCoin;
|
|
8871
8949
|
}
|
|
8950
|
+
expectOutputSwapV3WithMaxAmountIn(txb, inputCoin, routerData, maxAmountIn, amountOut, _amountLimit, partner) {
|
|
8951
|
+
const receipts = [];
|
|
8952
|
+
const dex = new CetusRouter(this.env, partner);
|
|
8953
|
+
const processedData = processFlattenRoutes(routerData);
|
|
8954
|
+
const swapCtx = newSwapContextV2(
|
|
8955
|
+
{
|
|
8956
|
+
quoteID: processedData.quoteID,
|
|
8957
|
+
fromCoinType: processedData.fromCoinType,
|
|
8958
|
+
targetCoinType: processedData.targetCoinType,
|
|
8959
|
+
maxAmountIn,
|
|
8960
|
+
expectAmountOut: amountOut,
|
|
8961
|
+
amountOutLimit: amountOut,
|
|
8962
|
+
// amountOutLimit equals expectAmountOut when fix amout out
|
|
8963
|
+
inputCoin,
|
|
8964
|
+
feeRate: this.overlayFeeRate,
|
|
8965
|
+
feeRecipient: this.overlayFeeReceiver,
|
|
8966
|
+
packages: processedData.packages
|
|
8967
|
+
},
|
|
8968
|
+
txb
|
|
8969
|
+
);
|
|
8970
|
+
const firstCoinRecord = recordFirstCoinIndex(routerData.paths);
|
|
8971
|
+
let needRepayRecord = /* @__PURE__ */ new Map();
|
|
8972
|
+
let payRecord = /* @__PURE__ */ new Map();
|
|
8973
|
+
for (let j = routerData.paths.length - 1; j >= 0; j--) {
|
|
8974
|
+
const path = routerData.paths[j];
|
|
8975
|
+
const firstFromTokenIndex = firstCoinRecord.get(path.from);
|
|
8976
|
+
let amountArg;
|
|
8977
|
+
if (j !== firstFromTokenIndex || path.target === processedData.targetCoinType) {
|
|
8978
|
+
if (path.target !== processedData.targetCoinType) {
|
|
8979
|
+
let payAmount = BigInt(path.amountOut);
|
|
8980
|
+
if (payRecord.has(path.target)) {
|
|
8981
|
+
const oldPayAmount = payRecord.get(path.target);
|
|
8982
|
+
payAmount = oldPayAmount + payAmount;
|
|
8983
|
+
}
|
|
8984
|
+
payRecord.set(path.target, payAmount);
|
|
8985
|
+
}
|
|
8986
|
+
amountArg = txb.pure.u64(
|
|
8987
|
+
path.amountOut.toString()
|
|
8988
|
+
);
|
|
8989
|
+
} else {
|
|
8990
|
+
if (!needRepayRecord.has(path.target)) {
|
|
8991
|
+
throw Error("no need repay record");
|
|
8992
|
+
}
|
|
8993
|
+
if (payRecord.has(path.target)) {
|
|
8994
|
+
const oldPayAmount = payRecord.get(path.target);
|
|
8995
|
+
const oldNeedRepay = needRepayRecord.get(path.target);
|
|
8996
|
+
amountArg = dex.sub(
|
|
8997
|
+
txb,
|
|
8998
|
+
oldNeedRepay,
|
|
8999
|
+
txb.pure.u64(oldPayAmount),
|
|
9000
|
+
path.publishedAt
|
|
9001
|
+
);
|
|
9002
|
+
} else {
|
|
9003
|
+
amountArg = needRepayRecord.get(path.target);
|
|
9004
|
+
}
|
|
9005
|
+
}
|
|
9006
|
+
const flashSwapResult = dex.flashSwapFixedOutput(
|
|
9007
|
+
txb,
|
|
9008
|
+
path,
|
|
9009
|
+
amountArg,
|
|
9010
|
+
swapCtx
|
|
9011
|
+
);
|
|
9012
|
+
receipts.unshift(flashSwapResult.flashReceipt);
|
|
9013
|
+
if (needRepayRecord.has(path.from)) {
|
|
9014
|
+
const oldNeedRepay = needRepayRecord.get(path.from);
|
|
9015
|
+
needRepayRecord.set(
|
|
9016
|
+
path.from,
|
|
9017
|
+
dex.add(
|
|
9018
|
+
txb,
|
|
9019
|
+
oldNeedRepay,
|
|
9020
|
+
flashSwapResult.repayAmount,
|
|
9021
|
+
path.publishedAt
|
|
9022
|
+
)
|
|
9023
|
+
);
|
|
9024
|
+
} else {
|
|
9025
|
+
needRepayRecord.set(path.from, flashSwapResult.repayAmount);
|
|
9026
|
+
}
|
|
9027
|
+
}
|
|
9028
|
+
for (let j = 0; j < routerData.paths.length; j++) {
|
|
9029
|
+
const path = routerData.paths[j];
|
|
9030
|
+
dex.repayFlashSwapFixedOutput(txb, path, swapCtx, receipts[j]);
|
|
9031
|
+
}
|
|
9032
|
+
const remainInputBalance = takeBalance(
|
|
9033
|
+
{
|
|
9034
|
+
coinType: processedData.fromCoinType,
|
|
9035
|
+
amount: U64_MAX,
|
|
9036
|
+
swapCtx,
|
|
9037
|
+
packages: processedData.packages
|
|
9038
|
+
},
|
|
9039
|
+
txb
|
|
9040
|
+
);
|
|
9041
|
+
transferBalance(
|
|
9042
|
+
{
|
|
9043
|
+
balance: remainInputBalance,
|
|
9044
|
+
coinType: processedData.fromCoinType,
|
|
9045
|
+
recipient: this.signer,
|
|
9046
|
+
packages: processedData.packages
|
|
9047
|
+
},
|
|
9048
|
+
txb
|
|
9049
|
+
);
|
|
9050
|
+
const outputCoin = confirmSwap(
|
|
9051
|
+
{
|
|
9052
|
+
swapContext: swapCtx,
|
|
9053
|
+
targetCoinType: processedData.targetCoinType,
|
|
9054
|
+
packages: processedData.packages
|
|
9055
|
+
},
|
|
9056
|
+
txb
|
|
9057
|
+
);
|
|
9058
|
+
return outputCoin;
|
|
9059
|
+
}
|
|
8872
9060
|
routerSwap(params) {
|
|
8873
9061
|
return __async(this, null, function* () {
|
|
8874
9062
|
const { router, inputCoin, slippage, txb, partner } = params;
|
|
@@ -8919,6 +9107,67 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8919
9107
|
}
|
|
8920
9108
|
});
|
|
8921
9109
|
}
|
|
9110
|
+
/**
|
|
9111
|
+
* Router swap with max amount in validation.
|
|
9112
|
+
* This method validates that the input coin amount does not exceed maxAmountIn.
|
|
9113
|
+
* If the validation fails, the transaction will abort with an error.
|
|
9114
|
+
*
|
|
9115
|
+
* @param params - Router swap parameters with maxAmountIn
|
|
9116
|
+
* @returns TransactionObjectArgument - The output coin from the swap
|
|
9117
|
+
* @throws Error if input coin amount exceeds maxAmountIn
|
|
9118
|
+
*/
|
|
9119
|
+
routerSwapWithMaxAmountIn(params) {
|
|
9120
|
+
return __async(this, null, function* () {
|
|
9121
|
+
const { router, inputCoin, slippage, txb, partner, maxAmountIn } = params;
|
|
9122
|
+
if (slippage > 1 || slippage < 0) {
|
|
9123
|
+
throw new Error(CLIENT_CONFIG.ERRORS.INVALID_SLIPPAGE);
|
|
9124
|
+
}
|
|
9125
|
+
if (!params.router.packages || !params.router.packages.get(PACKAGE_NAMES.AGGREGATOR_V3)) {
|
|
9126
|
+
throw new Error(CLIENT_CONFIG.ERRORS.PACKAGES_REQUIRED);
|
|
9127
|
+
}
|
|
9128
|
+
const byAmountIn = params.router.byAmountIn;
|
|
9129
|
+
const amountIn = router.amountIn;
|
|
9130
|
+
const amountOut = router.amountOut;
|
|
9131
|
+
checkOverlayFeeConfig(this.overlayFeeRate, this.overlayFeeReceiver);
|
|
9132
|
+
let overlayFee = new import_bn6.default(0);
|
|
9133
|
+
if (byAmountIn) {
|
|
9134
|
+
overlayFee = amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
|
|
9135
|
+
} else {
|
|
9136
|
+
overlayFee = amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
|
|
9137
|
+
}
|
|
9138
|
+
const expectedAmountOut = byAmountIn ? amountOut.sub(overlayFee) : amountOut;
|
|
9139
|
+
const expectedAmountIn = byAmountIn ? amountIn : amountIn.add(overlayFee);
|
|
9140
|
+
const amountLimit = CalculateAmountLimitBN(
|
|
9141
|
+
byAmountIn ? expectedAmountOut : expectedAmountIn,
|
|
9142
|
+
byAmountIn,
|
|
9143
|
+
slippage
|
|
9144
|
+
);
|
|
9145
|
+
const priceIDs = findPythPriceIDs(router.paths);
|
|
9146
|
+
const priceInfoObjectIds = priceIDs.length > 0 ? yield this.updatePythPriceIDs(priceIDs, txb) : /* @__PURE__ */ new Map();
|
|
9147
|
+
if (byAmountIn) {
|
|
9148
|
+
return this.expectInputSwapV3WithMaxAmountIn(
|
|
9149
|
+
txb,
|
|
9150
|
+
inputCoin,
|
|
9151
|
+
router,
|
|
9152
|
+
maxAmountIn,
|
|
9153
|
+
amountOut.toString(),
|
|
9154
|
+
amountLimit.toString(),
|
|
9155
|
+
priceInfoObjectIds,
|
|
9156
|
+
partner != null ? partner : this.partner
|
|
9157
|
+
);
|
|
9158
|
+
} else {
|
|
9159
|
+
return this.expectOutputSwapV3WithMaxAmountIn(
|
|
9160
|
+
txb,
|
|
9161
|
+
inputCoin,
|
|
9162
|
+
router,
|
|
9163
|
+
maxAmountIn,
|
|
9164
|
+
amountOut.toString(),
|
|
9165
|
+
amountLimit.toString(),
|
|
9166
|
+
partner != null ? partner : this.partner
|
|
9167
|
+
);
|
|
9168
|
+
}
|
|
9169
|
+
});
|
|
9170
|
+
}
|
|
8922
9171
|
// auto build input coin
|
|
8923
9172
|
// auto merge, transfer or destory target coin.
|
|
8924
9173
|
fastRouterSwap(params) {
|
package/dist/index.mjs
CHANGED
|
@@ -3447,7 +3447,7 @@ var AGGREGATOR_V3_CONFIG = {
|
|
|
3447
3447
|
};
|
|
3448
3448
|
|
|
3449
3449
|
// src/api.ts
|
|
3450
|
-
var SDK_VERSION =
|
|
3450
|
+
var SDK_VERSION = 1010401;
|
|
3451
3451
|
function parseRouterResponse(data, byAmountIn) {
|
|
3452
3452
|
let packages = /* @__PURE__ */ new Map();
|
|
3453
3453
|
if (data.packages) {
|
|
@@ -7753,6 +7753,37 @@ function newSwapContext(params, txb) {
|
|
|
7753
7753
|
});
|
|
7754
7754
|
return swap_context;
|
|
7755
7755
|
}
|
|
7756
|
+
function newSwapContextV2(params, txb) {
|
|
7757
|
+
const {
|
|
7758
|
+
quoteID,
|
|
7759
|
+
fromCoinType,
|
|
7760
|
+
targetCoinType,
|
|
7761
|
+
maxAmountIn,
|
|
7762
|
+
expectAmountOut,
|
|
7763
|
+
amountOutLimit,
|
|
7764
|
+
inputCoin,
|
|
7765
|
+
feeRate,
|
|
7766
|
+
feeRecipient,
|
|
7767
|
+
aggregatorPublishedAt,
|
|
7768
|
+
packages
|
|
7769
|
+
} = params;
|
|
7770
|
+
const publishedAt = getAggregatorPublishedAt(packages, aggregatorPublishedAt);
|
|
7771
|
+
const args = [
|
|
7772
|
+
txb.pure.string(quoteID),
|
|
7773
|
+
txb.pure.u64(maxAmountIn.toString()),
|
|
7774
|
+
txb.pure.u64(expectAmountOut.toString()),
|
|
7775
|
+
txb.pure.u64(amountOutLimit.toString()),
|
|
7776
|
+
inputCoin,
|
|
7777
|
+
txb.pure.u32(Number(feeRate.toString())),
|
|
7778
|
+
txb.pure.address(feeRecipient)
|
|
7779
|
+
];
|
|
7780
|
+
const swap_context = txb.moveCall({
|
|
7781
|
+
target: `${publishedAt}::router::new_swap_context_v2`,
|
|
7782
|
+
typeArguments: [fromCoinType, targetCoinType],
|
|
7783
|
+
arguments: args
|
|
7784
|
+
});
|
|
7785
|
+
return swap_context;
|
|
7786
|
+
}
|
|
7756
7787
|
function confirmSwap(params, txb) {
|
|
7757
7788
|
const { swapContext, targetCoinType, aggregatorPublishedAt, packages } = params;
|
|
7758
7789
|
const publishedAt = getAggregatorPublishedAt(packages, aggregatorPublishedAt);
|
|
@@ -8754,6 +8785,53 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8754
8785
|
);
|
|
8755
8786
|
return outputCoin;
|
|
8756
8787
|
}
|
|
8788
|
+
expectInputSwapV3WithMaxAmountIn(txb, inputCoin, routerData, maxAmountIn, expectAmountOut, amountOutLimit, pythPriceIDs, partner, cetusDlmmPartner) {
|
|
8789
|
+
if (routerData.quoteID == null) {
|
|
8790
|
+
throw new Error(CLIENT_CONFIG.ERRORS.QUOTE_ID_REQUIRED);
|
|
8791
|
+
}
|
|
8792
|
+
const processedData = processFlattenRoutes(routerData);
|
|
8793
|
+
const swapCtx = newSwapContextV2(
|
|
8794
|
+
{
|
|
8795
|
+
quoteID: processedData.quoteID,
|
|
8796
|
+
fromCoinType: processedData.fromCoinType,
|
|
8797
|
+
targetCoinType: processedData.targetCoinType,
|
|
8798
|
+
maxAmountIn,
|
|
8799
|
+
expectAmountOut,
|
|
8800
|
+
amountOutLimit,
|
|
8801
|
+
inputCoin,
|
|
8802
|
+
feeRate: this.overlayFeeRate,
|
|
8803
|
+
feeRecipient: this.overlayFeeReceiver,
|
|
8804
|
+
packages: processedData.packages
|
|
8805
|
+
},
|
|
8806
|
+
txb
|
|
8807
|
+
);
|
|
8808
|
+
let dexRouters = /* @__PURE__ */ new Map();
|
|
8809
|
+
for (const flattenedPath of processedData.flattenedPaths) {
|
|
8810
|
+
const path = flattenedPath.path;
|
|
8811
|
+
if (!dexRouters.has(path.provider)) {
|
|
8812
|
+
dexRouters.set(
|
|
8813
|
+
path.provider,
|
|
8814
|
+
this.newDexRouterV3(
|
|
8815
|
+
path.provider,
|
|
8816
|
+
pythPriceIDs,
|
|
8817
|
+
partner,
|
|
8818
|
+
cetusDlmmPartner
|
|
8819
|
+
)
|
|
8820
|
+
);
|
|
8821
|
+
}
|
|
8822
|
+
const dex = dexRouters.get(path.provider);
|
|
8823
|
+
dex.swap(txb, flattenedPath, swapCtx, { pythPriceIDs });
|
|
8824
|
+
}
|
|
8825
|
+
const outputCoin = confirmSwap(
|
|
8826
|
+
{
|
|
8827
|
+
swapContext: swapCtx,
|
|
8828
|
+
targetCoinType: processedData.targetCoinType,
|
|
8829
|
+
packages: processedData.packages
|
|
8830
|
+
},
|
|
8831
|
+
txb
|
|
8832
|
+
);
|
|
8833
|
+
return outputCoin;
|
|
8834
|
+
}
|
|
8757
8835
|
expectOutputSwapV3(txb, inputCoin, routerData, amountOut, _amountLimit, partner) {
|
|
8758
8836
|
const receipts = [];
|
|
8759
8837
|
const dex = new CetusRouter(this.env, partner);
|
|
@@ -8863,6 +8941,116 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8863
8941
|
);
|
|
8864
8942
|
return outputCoin;
|
|
8865
8943
|
}
|
|
8944
|
+
expectOutputSwapV3WithMaxAmountIn(txb, inputCoin, routerData, maxAmountIn, amountOut, _amountLimit, partner) {
|
|
8945
|
+
const receipts = [];
|
|
8946
|
+
const dex = new CetusRouter(this.env, partner);
|
|
8947
|
+
const processedData = processFlattenRoutes(routerData);
|
|
8948
|
+
const swapCtx = newSwapContextV2(
|
|
8949
|
+
{
|
|
8950
|
+
quoteID: processedData.quoteID,
|
|
8951
|
+
fromCoinType: processedData.fromCoinType,
|
|
8952
|
+
targetCoinType: processedData.targetCoinType,
|
|
8953
|
+
maxAmountIn,
|
|
8954
|
+
expectAmountOut: amountOut,
|
|
8955
|
+
amountOutLimit: amountOut,
|
|
8956
|
+
// amountOutLimit equals expectAmountOut when fix amout out
|
|
8957
|
+
inputCoin,
|
|
8958
|
+
feeRate: this.overlayFeeRate,
|
|
8959
|
+
feeRecipient: this.overlayFeeReceiver,
|
|
8960
|
+
packages: processedData.packages
|
|
8961
|
+
},
|
|
8962
|
+
txb
|
|
8963
|
+
);
|
|
8964
|
+
const firstCoinRecord = recordFirstCoinIndex(routerData.paths);
|
|
8965
|
+
let needRepayRecord = /* @__PURE__ */ new Map();
|
|
8966
|
+
let payRecord = /* @__PURE__ */ new Map();
|
|
8967
|
+
for (let j = routerData.paths.length - 1; j >= 0; j--) {
|
|
8968
|
+
const path = routerData.paths[j];
|
|
8969
|
+
const firstFromTokenIndex = firstCoinRecord.get(path.from);
|
|
8970
|
+
let amountArg;
|
|
8971
|
+
if (j !== firstFromTokenIndex || path.target === processedData.targetCoinType) {
|
|
8972
|
+
if (path.target !== processedData.targetCoinType) {
|
|
8973
|
+
let payAmount = BigInt(path.amountOut);
|
|
8974
|
+
if (payRecord.has(path.target)) {
|
|
8975
|
+
const oldPayAmount = payRecord.get(path.target);
|
|
8976
|
+
payAmount = oldPayAmount + payAmount;
|
|
8977
|
+
}
|
|
8978
|
+
payRecord.set(path.target, payAmount);
|
|
8979
|
+
}
|
|
8980
|
+
amountArg = txb.pure.u64(
|
|
8981
|
+
path.amountOut.toString()
|
|
8982
|
+
);
|
|
8983
|
+
} else {
|
|
8984
|
+
if (!needRepayRecord.has(path.target)) {
|
|
8985
|
+
throw Error("no need repay record");
|
|
8986
|
+
}
|
|
8987
|
+
if (payRecord.has(path.target)) {
|
|
8988
|
+
const oldPayAmount = payRecord.get(path.target);
|
|
8989
|
+
const oldNeedRepay = needRepayRecord.get(path.target);
|
|
8990
|
+
amountArg = dex.sub(
|
|
8991
|
+
txb,
|
|
8992
|
+
oldNeedRepay,
|
|
8993
|
+
txb.pure.u64(oldPayAmount),
|
|
8994
|
+
path.publishedAt
|
|
8995
|
+
);
|
|
8996
|
+
} else {
|
|
8997
|
+
amountArg = needRepayRecord.get(path.target);
|
|
8998
|
+
}
|
|
8999
|
+
}
|
|
9000
|
+
const flashSwapResult = dex.flashSwapFixedOutput(
|
|
9001
|
+
txb,
|
|
9002
|
+
path,
|
|
9003
|
+
amountArg,
|
|
9004
|
+
swapCtx
|
|
9005
|
+
);
|
|
9006
|
+
receipts.unshift(flashSwapResult.flashReceipt);
|
|
9007
|
+
if (needRepayRecord.has(path.from)) {
|
|
9008
|
+
const oldNeedRepay = needRepayRecord.get(path.from);
|
|
9009
|
+
needRepayRecord.set(
|
|
9010
|
+
path.from,
|
|
9011
|
+
dex.add(
|
|
9012
|
+
txb,
|
|
9013
|
+
oldNeedRepay,
|
|
9014
|
+
flashSwapResult.repayAmount,
|
|
9015
|
+
path.publishedAt
|
|
9016
|
+
)
|
|
9017
|
+
);
|
|
9018
|
+
} else {
|
|
9019
|
+
needRepayRecord.set(path.from, flashSwapResult.repayAmount);
|
|
9020
|
+
}
|
|
9021
|
+
}
|
|
9022
|
+
for (let j = 0; j < routerData.paths.length; j++) {
|
|
9023
|
+
const path = routerData.paths[j];
|
|
9024
|
+
dex.repayFlashSwapFixedOutput(txb, path, swapCtx, receipts[j]);
|
|
9025
|
+
}
|
|
9026
|
+
const remainInputBalance = takeBalance(
|
|
9027
|
+
{
|
|
9028
|
+
coinType: processedData.fromCoinType,
|
|
9029
|
+
amount: U64_MAX,
|
|
9030
|
+
swapCtx,
|
|
9031
|
+
packages: processedData.packages
|
|
9032
|
+
},
|
|
9033
|
+
txb
|
|
9034
|
+
);
|
|
9035
|
+
transferBalance(
|
|
9036
|
+
{
|
|
9037
|
+
balance: remainInputBalance,
|
|
9038
|
+
coinType: processedData.fromCoinType,
|
|
9039
|
+
recipient: this.signer,
|
|
9040
|
+
packages: processedData.packages
|
|
9041
|
+
},
|
|
9042
|
+
txb
|
|
9043
|
+
);
|
|
9044
|
+
const outputCoin = confirmSwap(
|
|
9045
|
+
{
|
|
9046
|
+
swapContext: swapCtx,
|
|
9047
|
+
targetCoinType: processedData.targetCoinType,
|
|
9048
|
+
packages: processedData.packages
|
|
9049
|
+
},
|
|
9050
|
+
txb
|
|
9051
|
+
);
|
|
9052
|
+
return outputCoin;
|
|
9053
|
+
}
|
|
8866
9054
|
routerSwap(params) {
|
|
8867
9055
|
return __async(this, null, function* () {
|
|
8868
9056
|
const { router, inputCoin, slippage, txb, partner } = params;
|
|
@@ -8913,6 +9101,67 @@ var _AggregatorClient = class _AggregatorClient {
|
|
|
8913
9101
|
}
|
|
8914
9102
|
});
|
|
8915
9103
|
}
|
|
9104
|
+
/**
|
|
9105
|
+
* Router swap with max amount in validation.
|
|
9106
|
+
* This method validates that the input coin amount does not exceed maxAmountIn.
|
|
9107
|
+
* If the validation fails, the transaction will abort with an error.
|
|
9108
|
+
*
|
|
9109
|
+
* @param params - Router swap parameters with maxAmountIn
|
|
9110
|
+
* @returns TransactionObjectArgument - The output coin from the swap
|
|
9111
|
+
* @throws Error if input coin amount exceeds maxAmountIn
|
|
9112
|
+
*/
|
|
9113
|
+
routerSwapWithMaxAmountIn(params) {
|
|
9114
|
+
return __async(this, null, function* () {
|
|
9115
|
+
const { router, inputCoin, slippage, txb, partner, maxAmountIn } = params;
|
|
9116
|
+
if (slippage > 1 || slippage < 0) {
|
|
9117
|
+
throw new Error(CLIENT_CONFIG.ERRORS.INVALID_SLIPPAGE);
|
|
9118
|
+
}
|
|
9119
|
+
if (!params.router.packages || !params.router.packages.get(PACKAGE_NAMES.AGGREGATOR_V3)) {
|
|
9120
|
+
throw new Error(CLIENT_CONFIG.ERRORS.PACKAGES_REQUIRED);
|
|
9121
|
+
}
|
|
9122
|
+
const byAmountIn = params.router.byAmountIn;
|
|
9123
|
+
const amountIn = router.amountIn;
|
|
9124
|
+
const amountOut = router.amountOut;
|
|
9125
|
+
checkOverlayFeeConfig(this.overlayFeeRate, this.overlayFeeReceiver);
|
|
9126
|
+
let overlayFee = new import_bn6.default(0);
|
|
9127
|
+
if (byAmountIn) {
|
|
9128
|
+
overlayFee = amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
|
|
9129
|
+
} else {
|
|
9130
|
+
overlayFee = amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
|
|
9131
|
+
}
|
|
9132
|
+
const expectedAmountOut = byAmountIn ? amountOut.sub(overlayFee) : amountOut;
|
|
9133
|
+
const expectedAmountIn = byAmountIn ? amountIn : amountIn.add(overlayFee);
|
|
9134
|
+
const amountLimit = CalculateAmountLimitBN(
|
|
9135
|
+
byAmountIn ? expectedAmountOut : expectedAmountIn,
|
|
9136
|
+
byAmountIn,
|
|
9137
|
+
slippage
|
|
9138
|
+
);
|
|
9139
|
+
const priceIDs = findPythPriceIDs(router.paths);
|
|
9140
|
+
const priceInfoObjectIds = priceIDs.length > 0 ? yield this.updatePythPriceIDs(priceIDs, txb) : /* @__PURE__ */ new Map();
|
|
9141
|
+
if (byAmountIn) {
|
|
9142
|
+
return this.expectInputSwapV3WithMaxAmountIn(
|
|
9143
|
+
txb,
|
|
9144
|
+
inputCoin,
|
|
9145
|
+
router,
|
|
9146
|
+
maxAmountIn,
|
|
9147
|
+
amountOut.toString(),
|
|
9148
|
+
amountLimit.toString(),
|
|
9149
|
+
priceInfoObjectIds,
|
|
9150
|
+
partner != null ? partner : this.partner
|
|
9151
|
+
);
|
|
9152
|
+
} else {
|
|
9153
|
+
return this.expectOutputSwapV3WithMaxAmountIn(
|
|
9154
|
+
txb,
|
|
9155
|
+
inputCoin,
|
|
9156
|
+
router,
|
|
9157
|
+
maxAmountIn,
|
|
9158
|
+
amountOut.toString(),
|
|
9159
|
+
amountLimit.toString(),
|
|
9160
|
+
partner != null ? partner : this.partner
|
|
9161
|
+
);
|
|
9162
|
+
}
|
|
9163
|
+
});
|
|
9164
|
+
}
|
|
8916
9165
|
// auto build input coin
|
|
8917
9166
|
// auto merge, transfer or destory target coin.
|
|
8918
9167
|
fastRouterSwap(params) {
|