@cetusprotocol/aggregator-sdk 1.1.2 → 1.1.4

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.
Files changed (28) hide show
  1. package/.claude/settings.local.json +41 -0
  2. package/dist/index.d.mts +6 -3
  3. package/dist/index.d.ts +6 -3
  4. package/dist/index.js +86 -52
  5. package/dist/index.mjs +86 -52
  6. package/package.json +2 -2
  7. package/.github/workflows/test.yml +0 -152
  8. package/.vscode/settings.json +0 -8
  9. package/CLAUDE.md +0 -101
  10. package/benchmark-results/benchmark-results-2025-07-17T12-03-15-563Z.csv +0 -3
  11. package/benchmark-results/benchmark-results-2025-07-17T12-03-15-563Z.json +0 -56
  12. package/benchmark-results/benchmark-results-2025-07-17T12-03-34-148Z.csv +0 -3
  13. package/benchmark-results/benchmark-results-2025-07-17T12-03-34-148Z.json +0 -56
  14. package/benchmark-results/benchmark-results-2025-07-21T03-31-59-263Z.csv +0 -21
  15. package/benchmark-results/benchmark-results-2025-07-21T03-31-59-263Z.json +0 -444
  16. package/benchmark-results/benchmark-results-2025-07-21T07-54-54-916Z.csv +0 -21
  17. package/benchmark-results/benchmark-results-2025-07-21T07-54-54-916Z.json +0 -503
  18. package/benchmark-results/error-report-2025-07-17T12-03-34-148Z.md +0 -18
  19. package/benchmark-results/error-report-2025-07-21T03-31-59-263Z.md +0 -18
  20. package/benchmark-results/error-report-2025-07-21T07-54-54-916Z.md +0 -18
  21. package/benchmark-results/gas-analysis-report-2025-07-17T12-03-15-563Z.md +0 -80
  22. package/benchmark-results/gas-analysis-report-2025-07-17T12-03-34-148Z.md +0 -80
  23. package/benchmark-results/gas-analysis-report-2025-07-21T03-31-59-263Z.md +0 -296
  24. package/benchmark-results/gas-analysis-report-2025-07-21T07-54-54-916Z.md +0 -323
  25. package/docs/Cetus_Aggregator_V3_/346/216/245/345/217/243/346/226/207/346/241/243.md +0 -706
  26. package/docs/REFACTOR.md +0 -24
  27. package/docs//350/267/257/345/276/204/346/213/223/346/211/221/346/216/222/345/272/217.md +0 -208
  28. package/script/copy-to-sui-aggregator.sh +0 -85
package/dist/index.mjs CHANGED
@@ -2993,7 +2993,7 @@ var GAS_TYPE_ARG = "0x2::sui::SUI";
2993
2993
  var GAS_TYPE_ARG_LONG = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI";
2994
2994
  var GAS_SYMBOL = "SUI";
2995
2995
  var DEFAULT_NFT_TRANSFER_GAS_FEE = 450;
2996
- var SUI_SYSTEM_STATE_OBJECT_ID = "0x0000000000000000000000000000000000000005";
2996
+ var SUI_SYSTEM_STATE_OBJECT_ID = "0x0000000000000000000000000000000000000000000000000000000000000005";
2997
2997
  var CoinUtils = class _CoinUtils {
2998
2998
  /**
2999
2999
  * Get the coin type argument from a SuiMoveObject.
@@ -3101,10 +3101,18 @@ var CoinUtils = class _CoinUtils {
3101
3101
  * @returns The CoinAsset objects that have a balance greater than or equal to the given amount.
3102
3102
  */
3103
3103
  static selectCoinObjectIdGreaterThanOrEqual(coins, amount, exclude = []) {
3104
- const selectedResult = _CoinUtils.selectCoinAssetGreaterThanOrEqual(coins, amount, exclude);
3105
- const objectArray = selectedResult.selectedCoins.map((item) => item.coinObjectId);
3104
+ const selectedResult = _CoinUtils.selectCoinAssetGreaterThanOrEqual(
3105
+ coins,
3106
+ amount,
3107
+ exclude
3108
+ );
3109
+ const objectArray = selectedResult.selectedCoins.map(
3110
+ (item) => item.coinObjectId
3111
+ );
3106
3112
  const remainCoins = selectedResult.remainingCoins;
3107
- const amountArray = selectedResult.selectedCoins.map((item) => item.balance.toString());
3113
+ const amountArray = selectedResult.selectedCoins.map(
3114
+ (item) => item.balance.toString()
3115
+ );
3108
3116
  return { objectArray, remainCoins, amountArray };
3109
3117
  }
3110
3118
  /**
@@ -3116,7 +3124,9 @@ var CoinUtils = class _CoinUtils {
3116
3124
  * @returns The CoinAsset objects that have a balance greater than or equal to the given amount.
3117
3125
  */
3118
3126
  static selectCoinAssetGreaterThanOrEqual(coins, amount, exclude = []) {
3119
- const sortedCoins = _CoinUtils.sortByBalance(coins.filter((c) => !exclude.includes(c.coinObjectId)));
3127
+ const sortedCoins = _CoinUtils.sortByBalance(
3128
+ coins.filter((c) => !exclude.includes(c.coinObjectId))
3129
+ );
3120
3130
  const total = _CoinUtils.calculateTotalBalance(sortedCoins);
3121
3131
  if (total < amount) {
3122
3132
  return { selectedCoins: [], remainingCoins: sortedCoins };
@@ -3129,9 +3139,13 @@ var CoinUtils = class _CoinUtils {
3129
3139
  const remainingCoins = [...sortedCoins];
3130
3140
  while (sum2 < total) {
3131
3141
  const target = amount - sum2;
3132
- const coinWithSmallestSufficientBalanceIndex = remainingCoins.findIndex((c) => c.balance >= target);
3142
+ const coinWithSmallestSufficientBalanceIndex = remainingCoins.findIndex(
3143
+ (c) => c.balance >= target
3144
+ );
3133
3145
  if (coinWithSmallestSufficientBalanceIndex !== -1) {
3134
- selectedCoins.push(remainingCoins[coinWithSmallestSufficientBalanceIndex]);
3146
+ selectedCoins.push(
3147
+ remainingCoins[coinWithSmallestSufficientBalanceIndex]
3148
+ );
3135
3149
  remainingCoins.splice(coinWithSmallestSufficientBalanceIndex, 1);
3136
3150
  break;
3137
3151
  }
@@ -3141,7 +3155,10 @@ var CoinUtils = class _CoinUtils {
3141
3155
  sum2 += coinWithLargestBalance.balance;
3142
3156
  }
3143
3157
  }
3144
- return { selectedCoins: _CoinUtils.sortByBalance(selectedCoins), remainingCoins: _CoinUtils.sortByBalance(remainingCoins) };
3158
+ return {
3159
+ selectedCoins: _CoinUtils.sortByBalance(selectedCoins),
3160
+ remainingCoins: _CoinUtils.sortByBalance(remainingCoins)
3161
+ };
3145
3162
  }
3146
3163
  /**
3147
3164
  * Sort the CoinAsset objects by their balance.
@@ -3150,10 +3167,14 @@ var CoinUtils = class _CoinUtils {
3150
3167
  * @returns The sorted CoinAsset objects.
3151
3168
  */
3152
3169
  static sortByBalance(coins) {
3153
- return coins.sort((a, b) => a.balance < b.balance ? -1 : a.balance > b.balance ? 1 : 0);
3170
+ return coins.sort(
3171
+ (a, b) => a.balance < b.balance ? -1 : a.balance > b.balance ? 1 : 0
3172
+ );
3154
3173
  }
3155
3174
  static sortByBalanceDes(coins) {
3156
- return coins.sort((a, b) => a.balance > b.balance ? -1 : a.balance < b.balance ? 0 : 1);
3175
+ return coins.sort(
3176
+ (a, b) => a.balance > b.balance ? -1 : a.balance < b.balance ? 0 : 1
3177
+ );
3157
3178
  }
3158
3179
  /**
3159
3180
  * Calculate the total balance of a list of CoinAsset objects.
@@ -3391,8 +3412,9 @@ var DEEPBOOK_V3_DEEP_FEE_TYPES = {
3391
3412
  var CLIENT_CONFIG = {
3392
3413
  DEFAULT_PYTH_URL: "https://hermes.pyth.network",
3393
3414
  PYTH_TIMEOUT: 3e3,
3394
- MAX_OVERLAY_FEE_RATE: 0.1,
3415
+ MAX_OVERLAY_FEE_RATE_PARAMS: 0.1,
3395
3416
  FEE_RATE_MULTIPLIER: 1e6,
3417
+ MAX_FEE_RATE: 1e5,
3396
3418
  DEFAULT_OVERLAY_FEE_RECEIVER: "0x0",
3397
3419
  // Error Messages
3398
3420
  ERRORS: {
@@ -3405,7 +3427,8 @@ var CLIENT_CONFIG = {
3405
3427
  PYTH_UNAVAILABLE: "All Pyth price nodes are unavailable. Cannot fetch price data. Please switch to or add new available Pyth nodes",
3406
3428
  QUOTE_ID_REQUIRED: "Quote ID is required",
3407
3429
  AGGREGATOR_V3_PACKAGE_REQUIRED: "Aggregator V3 package is required",
3408
- PACKAGES_REQUIRED: "Packages are required"
3430
+ PACKAGES_REQUIRED: "Packages are required",
3431
+ OVERLAY_FEE_RECEIVER_REQUIRED: "Overlay fee rate is set, but overlay fee receiver is not set"
3409
3432
  }
3410
3433
  };
3411
3434
  var AGGREGATOR_V3_CONFIG = {
@@ -3420,7 +3443,7 @@ var AGGREGATOR_V3_CONFIG = {
3420
3443
  };
3421
3444
 
3422
3445
  // src/api.ts
3423
- var SDK_VERSION = 1010102;
3446
+ var SDK_VERSION = 1010104;
3424
3447
  function parseRouterResponse(data, byAmountIn) {
3425
3448
  let packages = /* @__PURE__ */ new Map();
3426
3449
  if (data.packages) {
@@ -3438,6 +3461,7 @@ function parseRouterResponse(data, byAmountIn) {
3438
3461
  amountOut: new import_bn2.default(data.amount_out.toString()),
3439
3462
  byAmountIn,
3440
3463
  insufficientLiquidity: false,
3464
+ deviationRatio: data.deviation_ratio,
3441
3465
  packages,
3442
3466
  paths: data.paths.map((path) => ({
3443
3467
  id: path.id,
@@ -6689,7 +6713,7 @@ var SpringsuiRouter = class {
6689
6713
  const args = [
6690
6714
  swapContext,
6691
6715
  txb.object(swapData.poolId),
6692
- txb.object("0x5"),
6716
+ txb.object(SUI_SYSTEM_STATE_OBJECT_ID),
6693
6717
  txb.pure.u64(swapData.amountIn),
6694
6718
  txb.pure.bool(swapData.direction)
6695
6719
  ];
@@ -7371,8 +7395,7 @@ var VoloRouter = class {
7371
7395
  swapContext,
7372
7396
  txb.object(this.stakePool),
7373
7397
  txb.object(this.metadata),
7374
- txb.object("0x5"),
7375
- // SuiSystemState
7398
+ txb.object(SUI_SYSTEM_STATE_OBJECT_ID),
7376
7399
  txb.pure.bool(swapData.direction),
7377
7400
  txb.pure.u64(swapData.amountIn)
7378
7401
  ];
@@ -7423,8 +7446,7 @@ var AfsuiRouter = class {
7423
7446
  swapContext,
7424
7447
  txb.object(this.stakedSuiVault),
7425
7448
  txb.object(this.safe),
7426
- txb.object("0x5"),
7427
- // SuiSystemState
7449
+ txb.object(SUI_SYSTEM_STATE_OBJECT_ID),
7428
7450
  txb.object(this.referVault),
7429
7451
  txb.object(this.validator),
7430
7452
  txb.pure.bool(swapData.direction),
@@ -7469,8 +7491,7 @@ var HaedalRouter = class {
7469
7491
  const args = [
7470
7492
  swapContext,
7471
7493
  txb.object(swapData.poolId),
7472
- txb.object("0x5"),
7473
- // SuiSystemState
7494
+ txb.object(SUI_SYSTEM_STATE_OBJECT_ID),
7474
7495
  txb.pure.bool(swapData.direction),
7475
7496
  txb.pure.u64(swapData.amountIn)
7476
7497
  ];
@@ -8229,7 +8250,7 @@ var _AggregatorClient = class _AggregatorClient {
8229
8250
  this.apiKey = params.apiKey || "";
8230
8251
  this.partner = params.partner;
8231
8252
  if (params.overlayFeeRate) {
8232
- if (params.overlayFeeRate > 0 && params.overlayFeeRate <= CLIENT_CONFIG.MAX_OVERLAY_FEE_RATE) {
8253
+ if (params.overlayFeeRate > 0 && params.overlayFeeRate <= CLIENT_CONFIG.MAX_OVERLAY_FEE_RATE_PARAMS) {
8233
8254
  this.overlayFeeRate = params.overlayFeeRate * AGGREGATOR_V3_CONFIG.FEE_DENOMINATOR;
8234
8255
  if (this.overlayFeeRate > AGGREGATOR_V3_CONFIG.MAX_FEE_RATE) {
8235
8256
  throw new Error(
@@ -8260,6 +8281,11 @@ var _AggregatorClient = class _AggregatorClient {
8260
8281
  return DEEPBOOK_V3_DEEP_FEE_TYPES.Testnet;
8261
8282
  }
8262
8283
  }
8284
+ getDeepbookV3Config() {
8285
+ return __async(this, null, function* () {
8286
+ return yield getDeepbookV3Config(this.endpoint);
8287
+ });
8288
+ }
8263
8289
  getOneCoinUsedToMerge(coinType) {
8264
8290
  return __async(this, null, function* () {
8265
8291
  try {
@@ -8510,20 +8536,22 @@ var _AggregatorClient = class _AggregatorClient {
8510
8536
  }
8511
8537
  routerSwap(params) {
8512
8538
  return __async(this, null, function* () {
8513
- const { router, inputCoin, slippage, txb, fixable, partner } = params;
8539
+ const { router, inputCoin, slippage, txb, partner } = params;
8514
8540
  if (slippage > 1 || slippage < 0) {
8515
8541
  throw new Error(CLIENT_CONFIG.ERRORS.INVALID_SLIPPAGE);
8516
8542
  }
8543
+ if (!params.router.packages || !params.router.packages.get(PACKAGE_NAMES.AGGREGATOR_V3)) {
8544
+ throw new Error(CLIENT_CONFIG.ERRORS.PACKAGES_REQUIRED);
8545
+ }
8517
8546
  const byAmountIn = params.router.byAmountIn;
8518
8547
  const amountIn = router.amountIn;
8519
8548
  const amountOut = router.amountOut;
8549
+ checkOverlayFeeConfig(this.overlayFeeRate, this.overlayFeeReceiver);
8520
8550
  let overlayFee = new import_bn6.default(0);
8521
- if (this.overlayFeeRate > 0 && this.overlayFeeReceiver !== "0x0") {
8522
- if (byAmountIn) {
8523
- overlayFee = amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
8524
- } else {
8525
- overlayFee = amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
8526
- }
8551
+ if (byAmountIn) {
8552
+ overlayFee = amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
8553
+ } else {
8554
+ overlayFee = amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6));
8527
8555
  }
8528
8556
  const expectedAmountOut = byAmountIn ? amountOut.sub(overlayFee) : amountOut;
8529
8557
  const expectedAmountIn = byAmountIn ? amountIn : amountIn.add(overlayFee);
@@ -8532,9 +8560,6 @@ var _AggregatorClient = class _AggregatorClient {
8532
8560
  byAmountIn,
8533
8561
  slippage
8534
8562
  );
8535
- if (!params.router.packages || !params.router.packages.get(PACKAGE_NAMES.AGGREGATOR_V3)) {
8536
- throw new Error(CLIENT_CONFIG.ERRORS.PACKAGES_REQUIRED);
8537
- }
8538
8563
  const priceIDs = findPythPriceIDs(router.paths);
8539
8564
  const priceInfoObjectIds = priceIDs.length > 0 ? yield this.updatePythPriceIDs(priceIDs, txb) : /* @__PURE__ */ new Map();
8540
8565
  if (byAmountIn) {
@@ -8567,17 +8592,16 @@ var _AggregatorClient = class _AggregatorClient {
8567
8592
  const fromCoinType = router.paths[0].from;
8568
8593
  const targetCoinType = router.paths[router.paths.length - 1].target;
8569
8594
  const byAmountIn = router.byAmountIn;
8595
+ checkOverlayFeeConfig(this.overlayFeeRate, this.overlayFeeReceiver);
8570
8596
  let overlayFee = 0;
8571
- if (this.overlayFeeRate > 0 && this.overlayFeeReceiver !== "0x0") {
8572
- if (byAmountIn) {
8573
- overlayFee = Number(
8574
- router.amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8575
- );
8576
- } else {
8577
- overlayFee = Number(
8578
- router.amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8579
- );
8580
- }
8597
+ if (byAmountIn) {
8598
+ overlayFee = Number(
8599
+ router.amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8600
+ );
8601
+ } else {
8602
+ overlayFee = Number(
8603
+ router.amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8604
+ );
8581
8605
  }
8582
8606
  const expectedAmountOut = byAmountIn ? router.amountOut.sub(new import_bn6.default(overlayFee)) : router.amountOut;
8583
8607
  const expectedAmountIn = byAmountIn ? router.amountIn : router.amountIn.add(new import_bn6.default(overlayFee));
@@ -8629,18 +8653,17 @@ var _AggregatorClient = class _AggregatorClient {
8629
8653
  }
8630
8654
  fixableRouterSwapV3(params) {
8631
8655
  return __async(this, null, function* () {
8632
- const { router, inputCoin, slippage, txb, deepbookv3DeepFee, partner } = params;
8656
+ const { router, inputCoin, slippage, txb, partner } = params;
8657
+ checkOverlayFeeConfig(this.overlayFeeRate, this.overlayFeeReceiver);
8633
8658
  let overlayFee = 0;
8634
- if (this.overlayFeeRate > 0 && this.overlayFeeReceiver !== "0x0") {
8635
- if (router.byAmountIn) {
8636
- overlayFee = Number(
8637
- router.amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8638
- );
8639
- } else {
8640
- overlayFee = Number(
8641
- router.amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8642
- );
8643
- }
8659
+ if (router.byAmountIn) {
8660
+ overlayFee = Number(
8661
+ router.amountOut.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8662
+ );
8663
+ } else {
8664
+ overlayFee = Number(
8665
+ router.amountIn.mul(new import_bn6.default(this.overlayFeeRate)).div(new import_bn6.default(1e6)).toString()
8666
+ );
8644
8667
  }
8645
8668
  const expectedAmountOut = router.byAmountIn ? router.amountOut.sub(new import_bn6.default(overlayFee)) : router.amountOut;
8646
8669
  const expectedAmountIn = router.byAmountIn ? router.amountIn : router.amountIn.add(new import_bn6.default(overlayFee));
@@ -8749,6 +8772,7 @@ var _AggregatorClient = class _AggregatorClient {
8749
8772
  const routeData = {
8750
8773
  amountIn,
8751
8774
  amountOut: new import_bn6.default((_d = event.amount_out) != null ? _d : 0),
8775
+ deviationRatio: 0,
8752
8776
  paths: [
8753
8777
  {
8754
8778
  id: pools[tempIndex],
@@ -8866,6 +8890,16 @@ function recordFirstCoinIndex(paths) {
8866
8890
  }
8867
8891
  return newCoinRecord;
8868
8892
  }
8893
+ function checkOverlayFeeConfig(overlayFeeRate, overlayFeeReceiver) {
8894
+ if (overlayFeeRate > CLIENT_CONFIG.MAX_FEE_RATE) {
8895
+ throw new Error(CLIENT_CONFIG.ERRORS.INVALID_OVERLAY_FEE_RATE);
8896
+ }
8897
+ if (overlayFeeReceiver === "0x0" && overlayFeeRate > 0) {
8898
+ throw new Error(
8899
+ CLIENT_CONFIG.ERRORS.OVERLAY_FEE_RECEIVER_REQUIRED
8900
+ );
8901
+ }
8902
+ }
8869
8903
 
8870
8904
  // src/types/sui.ts
8871
8905
  var getDefaultSuiInputType = (value) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cetusprotocol/aggregator-sdk",
3
- "version": "1.1.2",
3
+ "version": "1.1.4",
4
4
  "sideEffects": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -45,4 +45,4 @@
45
45
  "ts-jest": "^29.1.3",
46
46
  "typescript": "^5.0.0"
47
47
  }
48
- }
48
+ }
@@ -1,152 +0,0 @@
1
- name: Automated Testing with Success Rate
2
-
3
- on:
4
- push:
5
- branches: [ main, develop, refactor-v3 ]
6
- pull_request:
7
- branches: [ main, develop, refactor-v3 ]
8
-
9
- jobs:
10
- test:
11
- runs-on: ubuntu-latest
12
-
13
- steps:
14
- - name: Checkout code
15
- uses: actions/checkout@v4
16
-
17
- - name: Setup Bun
18
- uses: oven-sh/setup-bun@v1
19
- with:
20
- bun-version: latest
21
-
22
- - name: Install dependencies
23
- run: bun install
24
-
25
- - name: Run tests with coverage and statistics
26
- run: |
27
- echo "🧪 Running all tests..."
28
-
29
- # Run tests with JSON output for parsing
30
- bun test --json --outputFile=test-results.json --coverage || true
31
-
32
- # Also run regular test output for display
33
- echo "📊 Test Results:"
34
- bun test --verbose || TEST_EXIT_CODE=$?
35
-
36
- # Parse test results and calculate success rate
37
- echo "📈 Calculating test success rate..."
38
-
39
- # Create a simple Node.js script to parse JSON results
40
- cat > calculate-stats.js << 'EOF'
41
- const fs = require('fs');
42
-
43
- try {
44
- // Try to read the JSON results file
45
- let results;
46
- if (fs.existsSync('test-results.json')) {
47
- const data = fs.readFileSync('test-results.json', 'utf8');
48
- results = JSON.parse(data);
49
- } else {
50
- console.log('⚠️ JSON results file not found, using alternative method');
51
- process.exit(1);
52
- }
53
-
54
- // Calculate statistics
55
- const totalTests = results.numTotalTests || 0;
56
- const passedTests = results.numPassedTests || 0;
57
- const failedTests = results.numFailedTests || 0;
58
- const successRate = totalTests > 0 ? ((passedTests / totalTests) * 100).toFixed(2) : 0;
59
-
60
- console.log('\n📊 =================================');
61
- console.log('📊 TEST EXECUTION SUMMARY');
62
- console.log('📊 =================================');
63
- console.log(`📊 Total Tests: ${totalTests}`);
64
- console.log(`✅ Passed Tests: ${passedTests}`);
65
- console.log(`❌ Failed Tests: ${failedTests}`);
66
- console.log(`📈 Success Rate: ${successRate}%`);
67
- console.log('📊 =================================\n');
68
-
69
- // Set environment variables for GitHub Actions
70
- console.log(`::set-output name=total_tests::${totalTests}`);
71
- console.log(`::set-output name=passed_tests::${passedTests}`);
72
- console.log(`::set-output name=failed_tests::${failedTests}`);
73
- console.log(`::set-output name=success_rate::${successRate}`);
74
-
75
- // Exit with non-zero code if tests failed
76
- if (failedTests > 0) {
77
- process.exit(1);
78
- }
79
-
80
- } catch (error) {
81
- console.error('Error parsing test results:', error);
82
- process.exit(1);
83
- }
84
- EOF
85
-
86
- # Run the statistics calculation
87
- node calculate-stats.js || {
88
- echo "⚠️ Falling back to alternative statistics calculation..."
89
-
90
- # Alternative method using grep on test output
91
- echo "📊 ================================="
92
- echo "📊 TEST EXECUTION SUMMARY"
93
- echo "📊 ================================="
94
-
95
- # Count test files
96
- TEST_FILES=$(find tests -name "*.test.ts" | wc -l)
97
- echo "📊 Total Test Files: $TEST_FILES"
98
-
99
- # Try to get basic stats from bun test output
100
- echo "📊 Running tests again for statistics..."
101
- bun test 2>&1 | tee test-output.log
102
-
103
- # Parse the output for basic statistics
104
- if grep -q "Tests:" test-output.log; then
105
- STATS=$(grep "Tests:" test-output.log | tail -1)
106
- echo "📊 $STATS"
107
- fi
108
-
109
- echo "📊 ================================="
110
-
111
- # Clean up
112
- rm -f test-output.log
113
- }
114
-
115
- # Clean up
116
- rm -f calculate-stats.js test-results.json
117
-
118
- # Exit with the original test exit code
119
- exit ${TEST_EXIT_CODE:-0}
120
-
121
- - name: Upload test results
122
- uses: actions/upload-artifact@v3
123
- if: always()
124
- with:
125
- name: test-results
126
- path: |
127
- coverage/
128
- test-results.json
129
- retention-days: 30
130
-
131
- - name: Comment PR with test results
132
- uses: actions/github-script@v6
133
- if: github.event_name == 'pull_request'
134
- with:
135
- script: |
136
- const output = `## 🧪 Test Results
137
-
138
- **Test Execution Summary:**
139
- - Total Tests: \${{ steps.test.outputs.total_tests || 'N/A' }}
140
- - Passed Tests: \${{ steps.test.outputs.passed_tests || 'N/A' }}
141
- - Failed Tests: \${{ steps.test.outputs.failed_tests || 'N/A' }}
142
- - Success Rate: \${{ steps.test.outputs.success_rate || 'N/A' }}%
143
-
144
- \${{ steps.test.outputs.failed_tests > 0 && '❌ Some tests failed. Please review the test output above.' || '✅ All tests passed!' }}
145
- `;
146
-
147
- github.rest.issues.createComment({
148
- issue_number: context.issue.number,
149
- owner: context.repo.owner,
150
- repo: context.repo.repo,
151
- body: output
152
- });
@@ -1,8 +0,0 @@
1
- {
2
- "licenser.license": "AL2",
3
- "licenser.author": "0xBondSui <sugar@cetus.zone>",
4
- "licenser.projectName": "Cetus Aggregator TS SDK",
5
- "licenser.useSingleLineStyle": true,
6
- "licenser.disableAutoSave": false,
7
- "licenser.disableAutoHeaderInsertion": false
8
- }
package/CLAUDE.md DELETED
@@ -1,101 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- The **Cetus Aggregator SDK** is a TypeScript library for the Sui blockchain ecosystem that provides swap aggregation across 25+ decentralized exchanges (DEXs). The SDK finds optimal trading routes, best prices, and lowest slippage by integrating multiple DEXs including Cetus, DeepBook, Kriya, FlowX, Turbos, Aftermath, and many others.
8
-
9
- ## Development Commands
10
-
11
- ### Build and Development
12
-
13
- - `bun run build` - Compile TypeScript to CommonJS/ESM with type definitions using tsup
14
- - `bun run dev` - Development mode with file watching
15
- - `bun run clean` - Remove build artifacts and dependencies
16
- - `bun run publish:test` - Publish experimental version to bun
17
-
18
- ### Testing
19
-
20
- - `bun test` - Run Jest test suite with ESM support
21
- - Tests are organized by aggregator versions (v2/v3) in `/tests/` directory
22
- - Individual DEX tests located in `/tests/aggregatorv2/router/`
23
- - Mathematical function tests in `/tests/math.test.ts`
24
-
25
- ## Architecture
26
-
27
- ### Core Components
28
-
29
- **Main Entry Points:**
30
-
31
- - `src/index.ts` - Main export barrel
32
- - `src/client.ts` - Aggregator v2 client implementation
33
- - `src/clientv3.ts` - Aggregator v3 client implementation
34
-
35
- **Key Directories:**
36
-
37
- - `src/transaction/` - DEX-specific swap implementations (25+ integrations)
38
- - `src/utils/` - Utility functions for coins, transactions, API calls
39
- - `src/types/` - TypeScript type definitions
40
- - `src/movecall/` - Move contract interaction helpers
41
- - `src/api/` - API interaction layer
42
- - `src/math/` - Mathematical calculations for trading
43
-
44
- ### DEX Integration Pattern
45
-
46
- Each DEX has its own transaction module in `src/transaction/` following a consistent pattern:
47
-
48
- - Import from main client class (AggregatorClient/AggregatorClient)
49
- - Implement DEX-specific swap logic
50
- - Handle transaction building and execution
51
- - Support both amount-in and amount-out calculations
52
-
53
- ### TypeScript Configuration
54
-
55
- - Uses path mapping: `~/*` maps to `src/*`
56
- - Jest configured with same path mapping
57
- - Targets ES6 with CommonJS modules
58
- - Strict TypeScript enabled
59
-
60
- ### Key Dependencies
61
-
62
- - `@mysten/sui@^1.6.0` - Official Sui SDK for blockchain interactions
63
- - `@pythnetwork/pyth-sui-js@^2.1.0` - Pyth oracle integration for price feeds
64
- - `bn.js@^5.2.1` - Big number handling for precise calculations
65
- - `decimal.js@^10.4.3` - Decimal arithmetic for financial calculations
66
-
67
- ### Multi-Version Support
68
-
69
- The SDK supports both Aggregator v2 and v3 APIs:
70
-
71
- - v2: Legacy aggregator with extensive DEX support
72
- - v3: Newer aggregator with enhanced features and performance
73
-
74
- ### Testing Strategy
75
-
76
- - Unit tests for mathematical functions (`tests/math.test.ts`)
77
- - Integration tests for each DEX in `tests/aggregatorv2/router/`
78
- - Router functionality tests (`tests/aggregatorv2/router.test.ts`)
79
- - Wallet interaction tests (`tests/wallet.test.ts`)
80
-
81
- ### Build Process
82
-
83
- Uses `tsup` for bundling with:
84
-
85
- - Multiple output formats (CJS, ESM, TypeScript declarations)
86
- - Tree shaking enabled
87
- - Code splitting support
88
- - Development watch mode
89
-
90
- ### Contract Addresses
91
-
92
- The SDK works with multiple contract versions on Sui mainnet:
93
-
94
- - CetusAggregatorV2: `0x3864c7c59a4889fec05d1aae4bc9dba5a0e0940594b424fbed44cb3f6ac4c032`
95
- - CetusAggregatorV2ExtendV1: `0x39402d188b7231036e52266ebafad14413b4bf3daea4ac17115989444e6cd516`
96
- - CetusAggregatorV2ExtendV2: `0x368d13376443a8051b22b42a9125f6a3bc836422bb2d9c4a53984b8d6624c326`
97
- - CetusAggregatorSimple: `0x594d67abc0778023ac852800578271dd7e18698ad06e6298034858c77612333d`
98
-
99
- ### Environment Setup
100
-
101
- The SDK works with Sui mainnet and testnet environments via the `Env` enum. Configure clients with appropriate RPC endpoints and package configurations for the target network.
@@ -1,3 +0,0 @@
1
- Version,Provider,Success,AmountIn,AmountOut,TotalGasCost,ComputationCost,GasEfficiency,PriceImpact,Timestamp
2
- V2,MAGMA,true,5000000,1243876327,2555288,1420000,486,-24777.52,1752753791128
3
- V3,MAGMA,true,5000000,1244172561,1845288,710000,674,-24783.45,1752753794556
@@ -1,56 +0,0 @@
1
- {
2
- "v2": [
3
- {
4
- "gasMetrics": {
5
- "computationCost": "1420000",
6
- "storageCost": "8352400",
7
- "storageRebate": "7290756",
8
- "nonRefundableStorageFee": "73644",
9
- "totalGasCost": "2555288",
10
- "gasUsed": "1420000",
11
- "gasPrice": "1000",
12
- "success": true
13
- },
14
- "amountIn": "4c4b40",
15
- "amountOut": "4a240be7",
16
- "priceImpact": -24777.52,
17
- "gasEfficiency": 486,
18
- "provider": "MAGMA",
19
- "route": [
20
- "MAGMA"
21
- ],
22
- "timestamp": 1752753791128
23
- }
24
- ],
25
- "v3": [
26
- {
27
- "gasMetrics": {
28
- "computationCost": "710000",
29
- "storageCost": "8352400",
30
- "storageRebate": "7290756",
31
- "nonRefundableStorageFee": "73644",
32
- "totalGasCost": "1845288",
33
- "gasUsed": "710000",
34
- "gasPrice": "1000",
35
- "success": true
36
- },
37
- "amountIn": "4c4b40",
38
- "amountOut": "4a289111",
39
- "priceImpact": -24783.45,
40
- "gasEfficiency": 674,
41
- "provider": "MAGMA",
42
- "route": [
43
- "MAGMA"
44
- ],
45
- "timestamp": 1752753794556
46
- }
47
- ],
48
- "summary": {
49
- "v2AverageGas": "2555288",
50
- "v3AverageGas": "1845288",
51
- "gasSavingsPercent": 27.78,
52
- "v2SuccessRate": 100,
53
- "v3SuccessRate": 100,
54
- "totalTests": 2
55
- }
56
- }
@@ -1,3 +0,0 @@
1
- Version,Provider,Success,AmountIn,AmountOut,TotalGasCost,ComputationCost,GasEfficiency,PriceImpact,Timestamp
2
- V2,MAGMA,true,5000000,1244172561,2555288,1420000,486,-24783.45,1752753809734
3
- V3,MAGMA,true,5000000,1244172561,1845288,710000,674,-24783.45,1752753813146