@cetusprotocol/aggregator-sdk 0.3.32 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -81,6 +81,7 @@ declare const ALPHAFI = "ALPHAFI";
81
81
  declare const SPRINGSUI = "SPRINGSUI";
82
82
  declare const STEAMM = "STEAMM";
83
83
  declare const METASTABLE = "METASTABLE";
84
+ declare const OBRIC = "OBRIC";
84
85
  declare const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2";
85
86
  type BuildRouterSwapParams = {
86
87
  routers: Router[];
@@ -139,10 +140,12 @@ declare class AggregatorClient {
139
140
  constructor(endpoint?: string, signer?: string, client?: SuiClient, env?: Env);
140
141
  getCoins(coinType: string, refresh?: boolean): Promise<CoinAsset[]>;
141
142
  findRouters(params: FindRouterParams): Promise<RouterData | null>;
143
+ executeFlexibleInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
142
144
  expectInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
143
145
  expectOutputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], partner?: string, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
144
146
  swapInPools(params: SwapInPoolsParams): Promise<SwapInPoolsResult | null>;
145
147
  routerSwap(params: BuildRouterSwapParams | BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
148
+ fixableRouterSwap(params: BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
146
149
  fastRouterSwap(params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2): Promise<void>;
147
150
  publishedAtV2(): string;
148
151
  publishedAtV2Extend(): string;
@@ -251,6 +254,10 @@ type ExtendedDetails = {
251
254
  metastableCreateCapModule?: string;
252
255
  metastableCreateCapAllTypeParams?: boolean;
253
256
  metastableRegistryId?: string;
257
+ obricCoinAPriceSeed?: string;
258
+ obricCoinBPriceSeed?: string;
259
+ obricCoinAPriceId?: string;
260
+ obricCoinBPriceId?: string;
254
261
  };
255
262
  type Path = {
256
263
  id: string;
@@ -314,4 +321,4 @@ declare enum Env {
314
321
  Testnet = 1
315
322
  }
316
323
 
317
- export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient, type AggregatorResponse, BLUEFIN, BLUEMOVE, type BuildCoinResult, type BuildFastRouterSwapParams, type BuildFastRouterSwapParamsV2, type BuildRouterSwapParams, type BuildRouterSwapParamsV2, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, type DeepbookV3Config, type DeepbookV3ConfigResponse, type Dex, Env, type ExtendedDetails, FLOWXV2, FLOWXV3, type FindRouterParams, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, ONE, type Path, type PreSwapLpChangeParams, type Router, type RouterData, type RouterError, SCALLOP, SPRINGSUI, STEAMM, SUILEND, type SwapInPoolsParams, type SwapInPoolsResult, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
324
+ export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient, type AggregatorResponse, BLUEFIN, BLUEMOVE, type BuildCoinResult, type BuildFastRouterSwapParams, type BuildFastRouterSwapParamsV2, type BuildRouterSwapParams, type BuildRouterSwapParamsV2, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, type DeepbookV3Config, type DeepbookV3ConfigResponse, type Dex, Env, type ExtendedDetails, FLOWXV2, FLOWXV3, type FindRouterParams, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, OBRIC, ONE, type Path, type PreSwapLpChangeParams, type Router, type RouterData, type RouterError, SCALLOP, SPRINGSUI, STEAMM, SUILEND, type SwapInPoolsParams, type SwapInPoolsResult, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
package/dist/index.d.ts CHANGED
@@ -81,6 +81,7 @@ declare const ALPHAFI = "ALPHAFI";
81
81
  declare const SPRINGSUI = "SPRINGSUI";
82
82
  declare const STEAMM = "STEAMM";
83
83
  declare const METASTABLE = "METASTABLE";
84
+ declare const OBRIC = "OBRIC";
84
85
  declare const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2";
85
86
  type BuildRouterSwapParams = {
86
87
  routers: Router[];
@@ -139,10 +140,12 @@ declare class AggregatorClient {
139
140
  constructor(endpoint?: string, signer?: string, client?: SuiClient, env?: Env);
140
141
  getCoins(coinType: string, refresh?: boolean): Promise<CoinAsset[]>;
141
142
  findRouters(params: FindRouterParams): Promise<RouterData | null>;
143
+ executeFlexibleInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
142
144
  expectInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
143
145
  expectOutputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], partner?: string, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
144
146
  swapInPools(params: SwapInPoolsParams): Promise<SwapInPoolsResult | null>;
145
147
  routerSwap(params: BuildRouterSwapParams | BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
148
+ fixableRouterSwap(params: BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
146
149
  fastRouterSwap(params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2): Promise<void>;
147
150
  publishedAtV2(): string;
148
151
  publishedAtV2Extend(): string;
@@ -251,6 +254,10 @@ type ExtendedDetails = {
251
254
  metastableCreateCapModule?: string;
252
255
  metastableCreateCapAllTypeParams?: boolean;
253
256
  metastableRegistryId?: string;
257
+ obricCoinAPriceSeed?: string;
258
+ obricCoinBPriceSeed?: string;
259
+ obricCoinAPriceId?: string;
260
+ obricCoinBPriceId?: string;
254
261
  };
255
262
  type Path = {
256
263
  id: string;
@@ -314,4 +321,4 @@ declare enum Env {
314
321
  Testnet = 1
315
322
  }
316
323
 
317
- export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient, type AggregatorResponse, BLUEFIN, BLUEMOVE, type BuildCoinResult, type BuildFastRouterSwapParams, type BuildFastRouterSwapParamsV2, type BuildRouterSwapParams, type BuildRouterSwapParamsV2, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, type DeepbookV3Config, type DeepbookV3ConfigResponse, type Dex, Env, type ExtendedDetails, FLOWXV2, FLOWXV3, type FindRouterParams, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, ONE, type Path, type PreSwapLpChangeParams, type Router, type RouterData, type RouterError, SCALLOP, SPRINGSUI, STEAMM, SUILEND, type SwapInPoolsParams, type SwapInPoolsResult, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
324
+ export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient, type AggregatorResponse, BLUEFIN, BLUEMOVE, type BuildCoinResult, type BuildFastRouterSwapParams, type BuildFastRouterSwapParamsV2, type BuildRouterSwapParams, type BuildRouterSwapParamsV2, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, type DeepbookV3Config, type DeepbookV3ConfigResponse, type Dex, Env, type ExtendedDetails, FLOWXV2, FLOWXV3, type FindRouterParams, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, OBRIC, ONE, type Path, type PreSwapLpChangeParams, type Router, type RouterData, type RouterError, SCALLOP, SPRINGSUI, STEAMM, SUILEND, type SwapInPoolsParams, type SwapInPoolsResult, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
package/dist/index.js CHANGED
@@ -6422,6 +6422,67 @@ var Metastable = class {
6422
6422
  }
6423
6423
  };
6424
6424
 
6425
+ // src/transaction/obric.ts
6426
+ var Obric = class {
6427
+ constructor(env, pythPriceIDs) {
6428
+ if (env === 1 /* Testnet */) {
6429
+ throw new Error("Obric is not supported on testnet");
6430
+ }
6431
+ this.pythPriceIDs = pythPriceIDs;
6432
+ this.pythStateObjectId = "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8";
6433
+ }
6434
+ swap(client, txb, path, inputCoin, packages) {
6435
+ return __async(this, null, function* () {
6436
+ const { direction, from, target } = path;
6437
+ const [func, coinAType, coinBType] = direction ? ["swap_a2b", from, target] : ["swap_b2a", target, from];
6438
+ let coinAPriceSeed;
6439
+ let coinBPriceSeed;
6440
+ let coinAPriceInfoObjectId;
6441
+ let coinBPriceInfoObjectId;
6442
+ if (path.extendedDetails == null) {
6443
+ throw new Error("Extended details not supported in obric");
6444
+ } else {
6445
+ if (path.extendedDetails.obricCoinAPriceSeed && path.extendedDetails.obricCoinBPriceSeed) {
6446
+ coinAPriceSeed = path.extendedDetails.obricCoinAPriceSeed;
6447
+ coinAPriceInfoObjectId = this.pythPriceIDs.get(coinAPriceSeed);
6448
+ coinBPriceSeed = path.extendedDetails.obricCoinBPriceSeed;
6449
+ coinBPriceInfoObjectId = this.pythPriceIDs.get(coinBPriceSeed);
6450
+ } else {
6451
+ if (!path.extendedDetails.obricCoinAPriceId || !path.extendedDetails.obricCoinBPriceId) {
6452
+ throw new Error("Base price id or quote price id not supported");
6453
+ } else {
6454
+ coinAPriceInfoObjectId = path.extendedDetails.obricCoinAPriceId;
6455
+ coinBPriceInfoObjectId = path.extendedDetails.obricCoinBPriceId;
6456
+ }
6457
+ }
6458
+ }
6459
+ if (!coinAPriceInfoObjectId || !coinBPriceInfoObjectId) {
6460
+ throw new Error(
6461
+ "Base price info object id or quote price info object id not found"
6462
+ );
6463
+ }
6464
+ const args = [
6465
+ txb.object(path.id),
6466
+ inputCoin,
6467
+ txb.object(this.pythStateObjectId),
6468
+ txb.object(coinAPriceInfoObjectId),
6469
+ txb.object(coinBPriceInfoObjectId),
6470
+ txb.object(CLOCK_ADDRESS)
6471
+ ];
6472
+ const publishedAt = getAggregatorV2ExtendPublishedAt(
6473
+ client.publishedAtV2Extend(),
6474
+ packages
6475
+ );
6476
+ const res = txb.moveCall({
6477
+ target: `${publishedAt}::obric::${func}`,
6478
+ typeArguments: [coinAType, coinBType],
6479
+ arguments: args
6480
+ });
6481
+ return res;
6482
+ });
6483
+ }
6484
+ };
6485
+
6425
6486
  // src/client.ts
6426
6487
  var CETUS = "CETUS";
6427
6488
  var DEEPBOOKV2 = "DEEPBOOK";
@@ -6444,6 +6505,7 @@ var ALPHAFI = "ALPHAFI";
6444
6505
  var SPRINGSUI = "SPRINGSUI";
6445
6506
  var STEAMM = "STEAMM";
6446
6507
  var METASTABLE = "METASTABLE";
6508
+ var OBRIC = "OBRIC";
6447
6509
  var DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2";
6448
6510
  function isBuilderRouterSwapParams(params) {
6449
6511
  return Array.isArray(params.routers);
@@ -6513,6 +6575,62 @@ var _AggregatorClient = class _AggregatorClient {
6513
6575
  return getRouterResult(this.endpoint, params);
6514
6576
  });
6515
6577
  }
6578
+ executeFlexibleInputSwap(txb, inputCoin, routers, amountOutLimit, pythPriceIDs, partner, deepbookv3DeepFee, packages) {
6579
+ return __async(this, null, function* () {
6580
+ if (routers.length === 0) {
6581
+ throw new Error("No router found");
6582
+ }
6583
+ const outputCoinType = routers[0].path[routers[0].path.length - 1].target;
6584
+ const outputCoins = [];
6585
+ for (let i = 0; i < routers.length - 1; i++) {
6586
+ if (routers[i].path.length === 0) {
6587
+ throw new Error("Empty path");
6588
+ }
6589
+ const splitCoin = txb.splitCoins(inputCoin, [routers[i].amountIn.toString()]);
6590
+ let nextCoin = splitCoin[0];
6591
+ for (const path of routers[i].path) {
6592
+ const dex = this.newDex(path.provider, pythPriceIDs, partner);
6593
+ nextCoin = yield dex.swap(
6594
+ this,
6595
+ txb,
6596
+ path,
6597
+ nextCoin,
6598
+ packages,
6599
+ deepbookv3DeepFee
6600
+ );
6601
+ }
6602
+ outputCoins.push(nextCoin);
6603
+ }
6604
+ if (routers[routers.length - 1].path.length === 0) {
6605
+ throw new Error("Empty path");
6606
+ }
6607
+ let lastCoin = inputCoin;
6608
+ for (const path of routers[routers.length - 1].path) {
6609
+ const dex = this.newDex(path.provider, pythPriceIDs, partner);
6610
+ lastCoin = yield dex.swap(
6611
+ this,
6612
+ txb,
6613
+ path,
6614
+ lastCoin,
6615
+ packages,
6616
+ deepbookv3DeepFee
6617
+ );
6618
+ }
6619
+ outputCoins.push(lastCoin);
6620
+ const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
6621
+ this.publishedAtV2(),
6622
+ packages
6623
+ );
6624
+ const mergedTargetCoin = this.checkCoinThresholdAndMergeCoin(
6625
+ txb,
6626
+ outputCoins,
6627
+ outputCoinType,
6628
+ amountOutLimit,
6629
+ aggregatorV2PublishedAt
6630
+ );
6631
+ return mergedTargetCoin;
6632
+ });
6633
+ }
6516
6634
  expectInputSwap(txb, inputCoin, routers, amountOutLimit, pythPriceIDs, partner, deepbookv3DeepFee, packages) {
6517
6635
  return __async(this, null, function* () {
6518
6636
  if (routers.length === 0) {
@@ -6691,6 +6809,53 @@ var _AggregatorClient = class _AggregatorClient {
6691
6809
  return targetCoin;
6692
6810
  });
6693
6811
  }
6812
+ fixableRouterSwap(params) {
6813
+ return __async(this, null, function* () {
6814
+ const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } = params;
6815
+ const routerData = Array.isArray(routers) ? routers : routers.routes;
6816
+ const byAmountIn = params.routers.byAmountIn;
6817
+ const amountIn = routerData.reduce(
6818
+ (acc, router) => acc.add(router.amountIn),
6819
+ new import_bn5.default(0)
6820
+ );
6821
+ const amountOut = routerData.reduce(
6822
+ (acc, router) => acc.add(router.amountOut),
6823
+ new import_bn5.default(0)
6824
+ );
6825
+ const amountLimit = CalculateAmountLimitBN(
6826
+ byAmountIn ? amountOut : amountIn,
6827
+ byAmountIn,
6828
+ slippage
6829
+ );
6830
+ const packages = isBuilderRouterSwapParams(params) ? void 0 : params.routers.packages;
6831
+ getAggregatorV2PublishedAt(
6832
+ this.publishedAtV2(),
6833
+ packages
6834
+ );
6835
+ const priceIDs = findPythPriceIDs(routerData);
6836
+ const priceInfoObjectIds = priceIDs.length > 0 ? yield this.updatePythPriceIDs(priceIDs, txb) : /* @__PURE__ */ new Map();
6837
+ if (byAmountIn) {
6838
+ const targetCoin2 = yield this.executeFlexibleInputSwap(
6839
+ txb,
6840
+ inputCoin,
6841
+ routerData,
6842
+ amountLimit,
6843
+ priceInfoObjectIds,
6844
+ partner,
6845
+ deepbookv3DeepFee,
6846
+ packages
6847
+ );
6848
+ return targetCoin2;
6849
+ }
6850
+ const targetCoin = yield this.expectOutputSwap(
6851
+ txb,
6852
+ inputCoin,
6853
+ routerData,
6854
+ partner
6855
+ );
6856
+ return targetCoin;
6857
+ });
6858
+ }
6694
6859
  // auto build input coin
6695
6860
  // auto merge, transfer or destory target coin.
6696
6861
  fastRouterSwap(params) {
@@ -6794,7 +6959,7 @@ var _AggregatorClient = class _AggregatorClient {
6794
6959
  // Include deepbookv3, scallop, bluefin
6795
6960
  publishedAtV2Extend() {
6796
6961
  if (this.env === 0 /* Mainnet */) {
6797
- return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc";
6962
+ return "0x200e762fa2c49f3dc150813038fbf22fd4f894ac6f23ebe1085c62f2ef97f1ca";
6798
6963
  } else {
6799
6964
  return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78";
6800
6965
  }
@@ -6875,6 +7040,8 @@ var _AggregatorClient = class _AggregatorClient {
6875
7040
  return new Steamm(this.env);
6876
7041
  case METASTABLE:
6877
7042
  return new Metastable(this.env, pythPriceIDs);
7043
+ case OBRIC:
7044
+ return new Obric(this.env, pythPriceIDs);
6878
7045
  default:
6879
7046
  throw new Error(`Unsupported dex ${provider}`);
6880
7047
  }
@@ -6982,7 +7149,7 @@ _AggregatorClient.CONFIG = {
6982
7149
  pythStateId: "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8"
6983
7150
  }
6984
7151
  };
6985
- var AggregatorClient21 = _AggregatorClient;
7152
+ var AggregatorClient22 = _AggregatorClient;
6986
7153
  function findPythPriceIDs(routes) {
6987
7154
  const priceIDs = /* @__PURE__ */ new Set();
6988
7155
  for (const route of routes) {
@@ -7001,6 +7168,14 @@ function findPythPriceIDs(routes) {
7001
7168
  priceIDs.add(path.extendedDetails.metastableETHPriceSeed);
7002
7169
  }
7003
7170
  }
7171
+ if (path.provider === OBRIC) {
7172
+ if (path.extendedDetails && path.extendedDetails.obricCoinAPriceSeed) {
7173
+ priceIDs.add(path.extendedDetails.obricCoinAPriceSeed);
7174
+ }
7175
+ if (path.extendedDetails && path.extendedDetails.obricCoinBPriceSeed) {
7176
+ priceIDs.add(path.extendedDetails.obricCoinBPriceSeed);
7177
+ }
7178
+ }
7004
7179
  }
7005
7180
  }
7006
7181
  return Array.from(priceIDs);
@@ -7029,13 +7204,13 @@ function parseRouterResponse(data, byAmountIn) {
7029
7204
  routes: data.routes.map((route) => {
7030
7205
  return {
7031
7206
  path: route.path.map((path) => {
7032
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
7207
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
7033
7208
  let version;
7034
7209
  if (path.provider === AFTERMATH) {
7035
7210
  version = path.extended_details.aftermath_pool_flatness === 0 ? "v2" : "v3";
7036
7211
  }
7037
7212
  let extendedDetails;
7038
- if (path.provider === TURBOS || path.provider === AFTERMATH || path.provider === CETUS || path.provider === DEEPBOOKV3 || path.provider === SCALLOP || path.provider === HAEDALPMM || path.provider === STEAMM || path.provider === METASTABLE) {
7213
+ if (path.provider === TURBOS || path.provider === AFTERMATH || path.provider === CETUS || path.provider === DEEPBOOKV3 || path.provider === SCALLOP || path.provider === HAEDALPMM || path.provider === STEAMM || path.provider === METASTABLE || path.provider === OBRIC) {
7039
7214
  extendedDetails = {
7040
7215
  aftermathLpSupplyType: (_a = path.extended_details) == null ? void 0 : _a.aftermath_lp_supply_type,
7041
7216
  turbosFeeType: (_b = path.extended_details) == null ? void 0 : _b.turbos_fee_type,
@@ -7057,7 +7232,11 @@ function parseRouterResponse(data, byAmountIn) {
7057
7232
  metastableCreateCapPkgId: (_r = path.extended_details) == null ? void 0 : _r.metastable_create_cap_pkg_id,
7058
7233
  metastableCreateCapModule: (_s = path.extended_details) == null ? void 0 : _s.metastable_create_cap_module,
7059
7234
  metastableCreateCapAllTypeParams: (_t = path.extended_details) == null ? void 0 : _t.metastable_create_cap_all_type_params,
7060
- metastableRegistryId: (_u = path.extended_details) == null ? void 0 : _u.metastable_registry_id
7235
+ metastableRegistryId: (_u = path.extended_details) == null ? void 0 : _u.metastable_registry_id,
7236
+ obricCoinAPriceSeed: (_v = path.extended_details) == null ? void 0 : _v.obric_coin_a_price_seed,
7237
+ obricCoinBPriceSeed: (_w = path.extended_details) == null ? void 0 : _w.obric_coin_b_price_seed,
7238
+ obricCoinAPriceId: (_x = path.extended_details) == null ? void 0 : _x.obric_coin_a_price_id,
7239
+ obricCoinBPriceId: (_y = path.extended_details) == null ? void 0 : _y.obric_coin_b_price_id
7061
7240
  };
7062
7241
  }
7063
7242
  return {
@@ -7145,7 +7324,7 @@ function processEndpoint(endpoint) {
7145
7324
  }
7146
7325
 
7147
7326
  // src/api.ts
7148
- var SDK_VERSION = 1000332;
7327
+ var SDK_VERSION = 1000400;
7149
7328
  function getRouterResult(endpoint, params) {
7150
7329
  return __async(this, null, function* () {
7151
7330
  let response;
@@ -7340,7 +7519,7 @@ exports.AFTERMATH = AFTERMATH;
7340
7519
  exports.AGGREGATOR_V2 = AGGREGATOR_V2;
7341
7520
  exports.AGGREGATOR_V2_EXTEND = AGGREGATOR_V2_EXTEND;
7342
7521
  exports.ALPHAFI = ALPHAFI;
7343
- exports.AggregatorClient = AggregatorClient21;
7522
+ exports.AggregatorClient = AggregatorClient22;
7344
7523
  exports.BLUEFIN = BLUEFIN;
7345
7524
  exports.BLUEMOVE = BLUEMOVE;
7346
7525
  exports.CETUS = CETUS;
@@ -7356,6 +7535,7 @@ exports.HAEDALPMM = HAEDALPMM;
7356
7535
  exports.KRIYA = KRIYA;
7357
7536
  exports.KRIYAV3 = KRIYAV3;
7358
7537
  exports.METASTABLE = METASTABLE;
7538
+ exports.OBRIC = OBRIC;
7359
7539
  exports.ONE = ONE;
7360
7540
  exports.SCALLOP = SCALLOP;
7361
7541
  exports.SPRINGSUI = SPRINGSUI;
package/dist/index.mjs CHANGED
@@ -6420,6 +6420,67 @@ var Metastable = class {
6420
6420
  }
6421
6421
  };
6422
6422
 
6423
+ // src/transaction/obric.ts
6424
+ var Obric = class {
6425
+ constructor(env, pythPriceIDs) {
6426
+ if (env === 1 /* Testnet */) {
6427
+ throw new Error("Obric is not supported on testnet");
6428
+ }
6429
+ this.pythPriceIDs = pythPriceIDs;
6430
+ this.pythStateObjectId = "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8";
6431
+ }
6432
+ swap(client, txb, path, inputCoin, packages) {
6433
+ return __async(this, null, function* () {
6434
+ const { direction, from, target } = path;
6435
+ const [func, coinAType, coinBType] = direction ? ["swap_a2b", from, target] : ["swap_b2a", target, from];
6436
+ let coinAPriceSeed;
6437
+ let coinBPriceSeed;
6438
+ let coinAPriceInfoObjectId;
6439
+ let coinBPriceInfoObjectId;
6440
+ if (path.extendedDetails == null) {
6441
+ throw new Error("Extended details not supported in obric");
6442
+ } else {
6443
+ if (path.extendedDetails.obricCoinAPriceSeed && path.extendedDetails.obricCoinBPriceSeed) {
6444
+ coinAPriceSeed = path.extendedDetails.obricCoinAPriceSeed;
6445
+ coinAPriceInfoObjectId = this.pythPriceIDs.get(coinAPriceSeed);
6446
+ coinBPriceSeed = path.extendedDetails.obricCoinBPriceSeed;
6447
+ coinBPriceInfoObjectId = this.pythPriceIDs.get(coinBPriceSeed);
6448
+ } else {
6449
+ if (!path.extendedDetails.obricCoinAPriceId || !path.extendedDetails.obricCoinBPriceId) {
6450
+ throw new Error("Base price id or quote price id not supported");
6451
+ } else {
6452
+ coinAPriceInfoObjectId = path.extendedDetails.obricCoinAPriceId;
6453
+ coinBPriceInfoObjectId = path.extendedDetails.obricCoinBPriceId;
6454
+ }
6455
+ }
6456
+ }
6457
+ if (!coinAPriceInfoObjectId || !coinBPriceInfoObjectId) {
6458
+ throw new Error(
6459
+ "Base price info object id or quote price info object id not found"
6460
+ );
6461
+ }
6462
+ const args = [
6463
+ txb.object(path.id),
6464
+ inputCoin,
6465
+ txb.object(this.pythStateObjectId),
6466
+ txb.object(coinAPriceInfoObjectId),
6467
+ txb.object(coinBPriceInfoObjectId),
6468
+ txb.object(CLOCK_ADDRESS)
6469
+ ];
6470
+ const publishedAt = getAggregatorV2ExtendPublishedAt(
6471
+ client.publishedAtV2Extend(),
6472
+ packages
6473
+ );
6474
+ const res = txb.moveCall({
6475
+ target: `${publishedAt}::obric::${func}`,
6476
+ typeArguments: [coinAType, coinBType],
6477
+ arguments: args
6478
+ });
6479
+ return res;
6480
+ });
6481
+ }
6482
+ };
6483
+
6423
6484
  // src/client.ts
6424
6485
  var CETUS = "CETUS";
6425
6486
  var DEEPBOOKV2 = "DEEPBOOK";
@@ -6442,6 +6503,7 @@ var ALPHAFI = "ALPHAFI";
6442
6503
  var SPRINGSUI = "SPRINGSUI";
6443
6504
  var STEAMM = "STEAMM";
6444
6505
  var METASTABLE = "METASTABLE";
6506
+ var OBRIC = "OBRIC";
6445
6507
  var DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2";
6446
6508
  function isBuilderRouterSwapParams(params) {
6447
6509
  return Array.isArray(params.routers);
@@ -6511,6 +6573,62 @@ var _AggregatorClient = class _AggregatorClient {
6511
6573
  return getRouterResult(this.endpoint, params);
6512
6574
  });
6513
6575
  }
6576
+ executeFlexibleInputSwap(txb, inputCoin, routers, amountOutLimit, pythPriceIDs, partner, deepbookv3DeepFee, packages) {
6577
+ return __async(this, null, function* () {
6578
+ if (routers.length === 0) {
6579
+ throw new Error("No router found");
6580
+ }
6581
+ const outputCoinType = routers[0].path[routers[0].path.length - 1].target;
6582
+ const outputCoins = [];
6583
+ for (let i = 0; i < routers.length - 1; i++) {
6584
+ if (routers[i].path.length === 0) {
6585
+ throw new Error("Empty path");
6586
+ }
6587
+ const splitCoin = txb.splitCoins(inputCoin, [routers[i].amountIn.toString()]);
6588
+ let nextCoin = splitCoin[0];
6589
+ for (const path of routers[i].path) {
6590
+ const dex = this.newDex(path.provider, pythPriceIDs, partner);
6591
+ nextCoin = yield dex.swap(
6592
+ this,
6593
+ txb,
6594
+ path,
6595
+ nextCoin,
6596
+ packages,
6597
+ deepbookv3DeepFee
6598
+ );
6599
+ }
6600
+ outputCoins.push(nextCoin);
6601
+ }
6602
+ if (routers[routers.length - 1].path.length === 0) {
6603
+ throw new Error("Empty path");
6604
+ }
6605
+ let lastCoin = inputCoin;
6606
+ for (const path of routers[routers.length - 1].path) {
6607
+ const dex = this.newDex(path.provider, pythPriceIDs, partner);
6608
+ lastCoin = yield dex.swap(
6609
+ this,
6610
+ txb,
6611
+ path,
6612
+ lastCoin,
6613
+ packages,
6614
+ deepbookv3DeepFee
6615
+ );
6616
+ }
6617
+ outputCoins.push(lastCoin);
6618
+ const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
6619
+ this.publishedAtV2(),
6620
+ packages
6621
+ );
6622
+ const mergedTargetCoin = this.checkCoinThresholdAndMergeCoin(
6623
+ txb,
6624
+ outputCoins,
6625
+ outputCoinType,
6626
+ amountOutLimit,
6627
+ aggregatorV2PublishedAt
6628
+ );
6629
+ return mergedTargetCoin;
6630
+ });
6631
+ }
6514
6632
  expectInputSwap(txb, inputCoin, routers, amountOutLimit, pythPriceIDs, partner, deepbookv3DeepFee, packages) {
6515
6633
  return __async(this, null, function* () {
6516
6634
  if (routers.length === 0) {
@@ -6689,6 +6807,53 @@ var _AggregatorClient = class _AggregatorClient {
6689
6807
  return targetCoin;
6690
6808
  });
6691
6809
  }
6810
+ fixableRouterSwap(params) {
6811
+ return __async(this, null, function* () {
6812
+ const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } = params;
6813
+ const routerData = Array.isArray(routers) ? routers : routers.routes;
6814
+ const byAmountIn = params.routers.byAmountIn;
6815
+ const amountIn = routerData.reduce(
6816
+ (acc, router) => acc.add(router.amountIn),
6817
+ new import_bn5.default(0)
6818
+ );
6819
+ const amountOut = routerData.reduce(
6820
+ (acc, router) => acc.add(router.amountOut),
6821
+ new import_bn5.default(0)
6822
+ );
6823
+ const amountLimit = CalculateAmountLimitBN(
6824
+ byAmountIn ? amountOut : amountIn,
6825
+ byAmountIn,
6826
+ slippage
6827
+ );
6828
+ const packages = isBuilderRouterSwapParams(params) ? void 0 : params.routers.packages;
6829
+ getAggregatorV2PublishedAt(
6830
+ this.publishedAtV2(),
6831
+ packages
6832
+ );
6833
+ const priceIDs = findPythPriceIDs(routerData);
6834
+ const priceInfoObjectIds = priceIDs.length > 0 ? yield this.updatePythPriceIDs(priceIDs, txb) : /* @__PURE__ */ new Map();
6835
+ if (byAmountIn) {
6836
+ const targetCoin2 = yield this.executeFlexibleInputSwap(
6837
+ txb,
6838
+ inputCoin,
6839
+ routerData,
6840
+ amountLimit,
6841
+ priceInfoObjectIds,
6842
+ partner,
6843
+ deepbookv3DeepFee,
6844
+ packages
6845
+ );
6846
+ return targetCoin2;
6847
+ }
6848
+ const targetCoin = yield this.expectOutputSwap(
6849
+ txb,
6850
+ inputCoin,
6851
+ routerData,
6852
+ partner
6853
+ );
6854
+ return targetCoin;
6855
+ });
6856
+ }
6692
6857
  // auto build input coin
6693
6858
  // auto merge, transfer or destory target coin.
6694
6859
  fastRouterSwap(params) {
@@ -6792,7 +6957,7 @@ var _AggregatorClient = class _AggregatorClient {
6792
6957
  // Include deepbookv3, scallop, bluefin
6793
6958
  publishedAtV2Extend() {
6794
6959
  if (this.env === 0 /* Mainnet */) {
6795
- return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc";
6960
+ return "0x200e762fa2c49f3dc150813038fbf22fd4f894ac6f23ebe1085c62f2ef97f1ca";
6796
6961
  } else {
6797
6962
  return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78";
6798
6963
  }
@@ -6873,6 +7038,8 @@ var _AggregatorClient = class _AggregatorClient {
6873
7038
  return new Steamm(this.env);
6874
7039
  case METASTABLE:
6875
7040
  return new Metastable(this.env, pythPriceIDs);
7041
+ case OBRIC:
7042
+ return new Obric(this.env, pythPriceIDs);
6876
7043
  default:
6877
7044
  throw new Error(`Unsupported dex ${provider}`);
6878
7045
  }
@@ -6980,7 +7147,7 @@ _AggregatorClient.CONFIG = {
6980
7147
  pythStateId: "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8"
6981
7148
  }
6982
7149
  };
6983
- var AggregatorClient21 = _AggregatorClient;
7150
+ var AggregatorClient22 = _AggregatorClient;
6984
7151
  function findPythPriceIDs(routes) {
6985
7152
  const priceIDs = /* @__PURE__ */ new Set();
6986
7153
  for (const route of routes) {
@@ -6999,6 +7166,14 @@ function findPythPriceIDs(routes) {
6999
7166
  priceIDs.add(path.extendedDetails.metastableETHPriceSeed);
7000
7167
  }
7001
7168
  }
7169
+ if (path.provider === OBRIC) {
7170
+ if (path.extendedDetails && path.extendedDetails.obricCoinAPriceSeed) {
7171
+ priceIDs.add(path.extendedDetails.obricCoinAPriceSeed);
7172
+ }
7173
+ if (path.extendedDetails && path.extendedDetails.obricCoinBPriceSeed) {
7174
+ priceIDs.add(path.extendedDetails.obricCoinBPriceSeed);
7175
+ }
7176
+ }
7002
7177
  }
7003
7178
  }
7004
7179
  return Array.from(priceIDs);
@@ -7027,13 +7202,13 @@ function parseRouterResponse(data, byAmountIn) {
7027
7202
  routes: data.routes.map((route) => {
7028
7203
  return {
7029
7204
  path: route.path.map((path) => {
7030
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
7205
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y;
7031
7206
  let version;
7032
7207
  if (path.provider === AFTERMATH) {
7033
7208
  version = path.extended_details.aftermath_pool_flatness === 0 ? "v2" : "v3";
7034
7209
  }
7035
7210
  let extendedDetails;
7036
- if (path.provider === TURBOS || path.provider === AFTERMATH || path.provider === CETUS || path.provider === DEEPBOOKV3 || path.provider === SCALLOP || path.provider === HAEDALPMM || path.provider === STEAMM || path.provider === METASTABLE) {
7211
+ if (path.provider === TURBOS || path.provider === AFTERMATH || path.provider === CETUS || path.provider === DEEPBOOKV3 || path.provider === SCALLOP || path.provider === HAEDALPMM || path.provider === STEAMM || path.provider === METASTABLE || path.provider === OBRIC) {
7037
7212
  extendedDetails = {
7038
7213
  aftermathLpSupplyType: (_a = path.extended_details) == null ? void 0 : _a.aftermath_lp_supply_type,
7039
7214
  turbosFeeType: (_b = path.extended_details) == null ? void 0 : _b.turbos_fee_type,
@@ -7055,7 +7230,11 @@ function parseRouterResponse(data, byAmountIn) {
7055
7230
  metastableCreateCapPkgId: (_r = path.extended_details) == null ? void 0 : _r.metastable_create_cap_pkg_id,
7056
7231
  metastableCreateCapModule: (_s = path.extended_details) == null ? void 0 : _s.metastable_create_cap_module,
7057
7232
  metastableCreateCapAllTypeParams: (_t = path.extended_details) == null ? void 0 : _t.metastable_create_cap_all_type_params,
7058
- metastableRegistryId: (_u = path.extended_details) == null ? void 0 : _u.metastable_registry_id
7233
+ metastableRegistryId: (_u = path.extended_details) == null ? void 0 : _u.metastable_registry_id,
7234
+ obricCoinAPriceSeed: (_v = path.extended_details) == null ? void 0 : _v.obric_coin_a_price_seed,
7235
+ obricCoinBPriceSeed: (_w = path.extended_details) == null ? void 0 : _w.obric_coin_b_price_seed,
7236
+ obricCoinAPriceId: (_x = path.extended_details) == null ? void 0 : _x.obric_coin_a_price_id,
7237
+ obricCoinBPriceId: (_y = path.extended_details) == null ? void 0 : _y.obric_coin_b_price_id
7059
7238
  };
7060
7239
  }
7061
7240
  return {
@@ -7143,7 +7322,7 @@ function processEndpoint(endpoint) {
7143
7322
  }
7144
7323
 
7145
7324
  // src/api.ts
7146
- var SDK_VERSION = 1000332;
7325
+ var SDK_VERSION = 1000400;
7147
7326
  function getRouterResult(endpoint, params) {
7148
7327
  return __async(this, null, function* () {
7149
7328
  let response;
@@ -7333,4 +7512,4 @@ decimal.js/decimal.mjs:
7333
7512
  *)
7334
7513
  */
7335
7514
 
7336
- export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient21 as AggregatorClient, BLUEFIN, BLUEMOVE, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, Env, FLOWXV2, FLOWXV3, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, ONE, SCALLOP, SPRINGSUI, STEAMM, SUILEND, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
7515
+ export { AFSUI, AFTERMATH, AGGREGATOR_V2, AGGREGATOR_V2_EXTEND, ALPHAFI, AggregatorClient22 as AggregatorClient, BLUEFIN, BLUEMOVE, CETUS, CLOCK_ADDRESS, DEEPBOOKV2, DEEPBOOKV3, DEFAULT_ENDPOINT, Env, FLOWXV2, FLOWXV3, HAEDAL, HAEDALPMM, KRIYA, KRIYAV3, METASTABLE, OBRIC, ONE, SCALLOP, SPRINGSUI, STEAMM, SUILEND, TEN_POW_NINE, TURBOS, TWO, U128, U64_MAX, U64_MAX_BN, VOLO, ZERO, buildInputCoin, checkInvalidSuiAddress, compareCoins, completionCoin, composeType, createTarget, dealWithFastRouterSwapParamsForMsafe, extractAddressFromType, extractStructTagFromType, findPythPriceIDs, fixSuiObjectId, getAggregatorV2ExtendPublishedAt, getAggregatorV2PublishedAt, getDeepbookV3Config, getRouterResult, isSortedSymbols, mintZeroCoin, normalizeCoinType, parseRouterResponse, patchFixSuiObjectId, printTransaction, processEndpoint, restituteMsafeFastRouterSwapParams };
package/dist/src/api.d.ts CHANGED
@@ -41,6 +41,10 @@ export type ExtendedDetails = {
41
41
  metastableCreateCapModule?: string;
42
42
  metastableCreateCapAllTypeParams?: boolean;
43
43
  metastableRegistryId?: string;
44
+ obricCoinAPriceSeed?: string;
45
+ obricCoinBPriceSeed?: string;
46
+ obricCoinAPriceId?: string;
47
+ obricCoinBPriceId?: string;
44
48
  };
45
49
  export type Path = {
46
50
  id: string;
@@ -25,6 +25,7 @@ export declare const ALPHAFI = "ALPHAFI";
25
25
  export declare const SPRINGSUI = "SPRINGSUI";
26
26
  export declare const STEAMM = "STEAMM";
27
27
  export declare const METASTABLE = "METASTABLE";
28
+ export declare const OBRIC = "OBRIC";
28
29
  export declare const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2";
29
30
  export type BuildRouterSwapParams = {
30
31
  routers: Router[];
@@ -83,10 +84,12 @@ export declare class AggregatorClient {
83
84
  constructor(endpoint?: string, signer?: string, client?: SuiClient, env?: Env);
84
85
  getCoins(coinType: string, refresh?: boolean): Promise<CoinAsset[]>;
85
86
  findRouters(params: FindRouterParams): Promise<RouterData | null>;
87
+ executeFlexibleInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
86
88
  expectInputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], amountOutLimit: BN, pythPriceIDs: Map<string, string>, partner?: string, deepbookv3DeepFee?: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
87
89
  expectOutputSwap(txb: Transaction, inputCoin: TransactionObjectArgument, routers: Router[], partner?: string, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
88
90
  swapInPools(params: SwapInPoolsParams): Promise<SwapInPoolsResult | null>;
89
91
  routerSwap(params: BuildRouterSwapParams | BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
92
+ fixableRouterSwap(params: BuildRouterSwapParamsV2): Promise<TransactionObjectArgument>;
90
93
  fastRouterSwap(params: BuildFastRouterSwapParams | BuildFastRouterSwapParamsV2): Promise<void>;
91
94
  publishedAtV2(): string;
92
95
  publishedAtV2Extend(): string;
@@ -0,0 +1,8 @@
1
+ import { Transaction, TransactionObjectArgument } from "@mysten/sui/transactions";
2
+ import { AggregatorClient, Dex, Env, Path } from "..";
3
+ export declare class Obric implements Dex {
4
+ private pythPriceIDs;
5
+ private pythStateObjectId;
6
+ constructor(env: Env, pythPriceIDs: Map<string, string>);
7
+ swap(client: AggregatorClient, txb: Transaction, path: Path, inputCoin: TransactionObjectArgument, packages?: Map<string, string>): Promise<TransactionObjectArgument>;
8
+ }
@@ -0,0 +1,2 @@
1
+ import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519";
2
+ export declare function buildTestAccount(): Ed25519Keypair;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cetusprotocol/aggregator-sdk",
3
- "version": "0.3.32",
3
+ "version": "0.4.0",
4
4
  "sideEffects": false,
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/api.ts CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./errors"
9
9
  import { parseRouterResponse } from "./client"
10
10
 
11
- const SDK_VERSION = 1000332
11
+ const SDK_VERSION = 1000400
12
12
 
13
13
  export interface FindRouterParams {
14
14
  from: string
@@ -60,6 +60,10 @@ export type ExtendedDetails = {
60
60
  metastableCreateCapModule?: string
61
61
  metastableCreateCapAllTypeParams?: boolean
62
62
  metastableRegistryId?: string
63
+ obricCoinAPriceSeed?: string
64
+ obricCoinBPriceSeed?: string
65
+ obricCoinAPriceId?: string
66
+ obricCoinBPriceId?: string
63
67
  }
64
68
 
65
69
  export type Path = {
package/src/client.ts CHANGED
@@ -49,6 +49,7 @@ import {
49
49
  } from "@pythnetwork/pyth-sui-js"
50
50
  import { Steamm } from "./transaction/steamm"
51
51
  import { Metastable } from "./transaction/metastable"
52
+ import { Obric } from "./transaction/obric"
52
53
 
53
54
  export const CETUS = "CETUS"
54
55
  export const DEEPBOOKV2 = "DEEPBOOK"
@@ -71,6 +72,7 @@ export const ALPHAFI = "ALPHAFI"
71
72
  export const SPRINGSUI = "SPRINGSUI"
72
73
  export const STEAMM = "STEAMM"
73
74
  export const METASTABLE = "METASTABLE"
75
+ export const OBRIC = "OBRIC"
74
76
  export const DEFAULT_ENDPOINT = "https://api-sui.cetus.zone/router_v2"
75
77
 
76
78
  export type BuildRouterSwapParams = {
@@ -258,6 +260,78 @@ export class AggregatorClient {
258
260
  return getRouterResult(this.endpoint, params)
259
261
  }
260
262
 
263
+ async executeFlexibleInputSwap(
264
+ txb: Transaction,
265
+ inputCoin: TransactionObjectArgument,
266
+ routers: Router[],
267
+ amountOutLimit: BN,
268
+ pythPriceIDs: Map<string, string>,
269
+ partner?: string,
270
+ deepbookv3DeepFee?: TransactionObjectArgument,
271
+ packages?: Map<string, string>
272
+ ) {
273
+ if (routers.length === 0) {
274
+ throw new Error("No router found")
275
+ }
276
+
277
+ const outputCoinType = routers[0].path[routers[0].path.length - 1].target
278
+ const outputCoins = []
279
+
280
+ for (let i = 0; i < routers.length - 1; i++) {
281
+ if (routers[i].path.length === 0) {
282
+ throw new Error("Empty path")
283
+ }
284
+ // 为每条路径分割所需的代币
285
+ const splitCoin = txb.splitCoins(inputCoin, [routers[i].amountIn.toString()])
286
+ let nextCoin = splitCoin[0] as TransactionObjectArgument
287
+
288
+ for (const path of routers[i].path) {
289
+ const dex = this.newDex(path.provider, pythPriceIDs, partner)
290
+ nextCoin = await dex.swap(
291
+ this,
292
+ txb,
293
+ path,
294
+ nextCoin,
295
+ packages,
296
+ deepbookv3DeepFee
297
+ )
298
+ }
299
+ outputCoins.push(nextCoin)
300
+ }
301
+
302
+ // 处理最后一条路径,使用剩余的所有代币
303
+ if (routers[routers.length - 1].path.length === 0) {
304
+ throw new Error("Empty path")
305
+ }
306
+ let lastCoin = inputCoin
307
+ for (const path of routers[routers.length - 1].path) {
308
+ const dex = this.newDex(path.provider, pythPriceIDs, partner)
309
+ lastCoin = await dex.swap(
310
+ this,
311
+ txb,
312
+ path,
313
+ lastCoin,
314
+ packages,
315
+ deepbookv3DeepFee
316
+ )
317
+ }
318
+ outputCoins.push(lastCoin)
319
+
320
+ const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
321
+ this.publishedAtV2(),
322
+ packages
323
+ )
324
+
325
+ const mergedTargetCoin = this.checkCoinThresholdAndMergeCoin(
326
+ txb,
327
+ outputCoins,
328
+ outputCoinType,
329
+ amountOutLimit,
330
+ aggregatorV2PublishedAt
331
+ )
332
+ return mergedTargetCoin
333
+ }
334
+
261
335
  async expectInputSwap(
262
336
  txb: Transaction,
263
337
  inputCoin: TransactionObjectArgument,
@@ -476,6 +550,69 @@ export class AggregatorClient {
476
550
  return targetCoin
477
551
  }
478
552
 
553
+ async fixableRouterSwap(
554
+ params: BuildRouterSwapParamsV2
555
+ ): Promise<TransactionObjectArgument> {
556
+ const { routers, inputCoin, slippage, txb, partner, deepbookv3DeepFee } =
557
+ params
558
+
559
+ const routerData = Array.isArray(routers) ? routers : routers.routes
560
+ const byAmountIn = params.routers.byAmountIn
561
+
562
+ const amountIn = routerData.reduce(
563
+ (acc, router) => acc.add(router.amountIn),
564
+ new BN(0)
565
+ )
566
+ const amountOut = routerData.reduce(
567
+ (acc, router) => acc.add(router.amountOut),
568
+ new BN(0)
569
+ )
570
+
571
+ const amountLimit = CalculateAmountLimitBN(
572
+ byAmountIn ? amountOut : amountIn,
573
+ byAmountIn,
574
+ slippage
575
+ )
576
+
577
+ const packages = isBuilderRouterSwapParams(params)
578
+ ? undefined
579
+ : params.routers.packages
580
+
581
+ const aggregatorV2PublishedAt = getAggregatorV2PublishedAt(
582
+ this.publishedAtV2(),
583
+ packages
584
+ )
585
+
586
+ const priceIDs = findPythPriceIDs(routerData)
587
+
588
+ const priceInfoObjectIds =
589
+ priceIDs.length > 0
590
+ ? await this.updatePythPriceIDs(priceIDs, txb)
591
+ : new Map<string, string>()
592
+
593
+ if (byAmountIn) {
594
+ const targetCoin = await this.executeFlexibleInputSwap(
595
+ txb,
596
+ inputCoin,
597
+ routerData,
598
+ amountLimit,
599
+ priceInfoObjectIds,
600
+ partner,
601
+ deepbookv3DeepFee,
602
+ packages
603
+ )
604
+ return targetCoin
605
+ }
606
+
607
+ const targetCoin = await this.expectOutputSwap(
608
+ txb,
609
+ inputCoin,
610
+ routerData,
611
+ partner
612
+ )
613
+ return targetCoin
614
+ }
615
+
479
616
  // auto build input coin
480
617
  // auto merge, transfer or destory target coin.
481
618
  async fastRouterSwap(
@@ -611,7 +748,8 @@ export class AggregatorClient {
611
748
  // return "0xf2fcea41dc217385019828375764fa06d9bd25e8e4726ba1962680849fb8d613" // version 8
612
749
  // return "0xa2d8a4279d69d8fec04b2fea8852d0d467d3cc0d39c5890180d439ae7a9953ed" // version 9
613
750
  // return "0x34ef25b60b51f9d07cd9b7dc5b08dfdf26c7b0ff00c57bb17454c161fa6b6b83" // version 10
614
- return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc" // version 11
751
+ // return "0xf57be4b9f9036034b1c5484d299d8fb68d5f43862d6afe8886d67db293dfc4bc" // version 11
752
+ return "0x200e762fa2c49f3dc150813038fbf22fd4f894ac6f23ebe1085c62f2ef97f1ca" // version 12
615
753
  } else {
616
754
  return "0xabb6a81c8a216828e317719e06125de5bb2cb0fe8f9916ff8c023ca5be224c78"
617
755
  }
@@ -712,6 +850,8 @@ export class AggregatorClient {
712
850
  return new Steamm(this.env)
713
851
  case METASTABLE:
714
852
  return new Metastable(this.env, pythPriceIDs)
853
+ case OBRIC:
854
+ return new Obric(this.env, pythPriceIDs)
715
855
  default:
716
856
  throw new Error(`Unsupported dex ${provider}`)
717
857
  }
@@ -822,6 +962,14 @@ export function findPythPriceIDs(routes: Router[]): string[] {
822
962
  priceIDs.add(path.extendedDetails.metastableETHPriceSeed)
823
963
  }
824
964
  }
965
+ if (path.provider === OBRIC) {
966
+ if (path.extendedDetails && path.extendedDetails.obricCoinAPriceSeed) {
967
+ priceIDs.add(path.extendedDetails.obricCoinAPriceSeed)
968
+ }
969
+ if (path.extendedDetails && path.extendedDetails.obricCoinBPriceSeed) {
970
+ priceIDs.add(path.extendedDetails.obricCoinBPriceSeed)
971
+ }
972
+ }
825
973
  }
826
974
  }
827
975
  return Array.from(priceIDs)
@@ -871,7 +1019,8 @@ export function parseRouterResponse(
871
1019
  path.provider === SCALLOP ||
872
1020
  path.provider === HAEDALPMM ||
873
1021
  path.provider === STEAMM ||
874
- path.provider === METASTABLE
1022
+ path.provider === METASTABLE ||
1023
+ path.provider === OBRIC
875
1024
  ) {
876
1025
  extendedDetails = {
877
1026
  aftermathLpSupplyType:
@@ -899,6 +1048,10 @@ export function parseRouterResponse(
899
1048
  metastableCreateCapModule: path.extended_details?.metastable_create_cap_module,
900
1049
  metastableCreateCapAllTypeParams: path.extended_details?.metastable_create_cap_all_type_params,
901
1050
  metastableRegistryId: path.extended_details?.metastable_registry_id,
1051
+ obricCoinAPriceSeed: path.extended_details?.obric_coin_a_price_seed,
1052
+ obricCoinBPriceSeed: path.extended_details?.obric_coin_b_price_seed,
1053
+ obricCoinAPriceId: path.extended_details?.obric_coin_a_price_id,
1054
+ obricCoinBPriceId: path.extended_details?.obric_coin_b_price_id,
902
1055
  }
903
1056
  }
904
1057
 
@@ -0,0 +1,90 @@
1
+ import {
2
+ Transaction,
3
+ TransactionArgument,
4
+ TransactionObjectArgument,
5
+ } from "@mysten/sui/transactions"
6
+ import {
7
+ AggregatorClient,
8
+ CLOCK_ADDRESS,
9
+ Dex,
10
+ Env,
11
+ getAggregatorV2ExtendPublishedAt,
12
+ Path,
13
+ } from ".."
14
+
15
+ export class Obric implements Dex {
16
+ private pythPriceIDs: Map<string, string>
17
+ private pythStateObjectId: string
18
+
19
+ constructor(env: Env, pythPriceIDs: Map<string, string>) {
20
+ if (env === Env.Testnet) {
21
+ throw new Error("Obric is not supported on testnet")
22
+ }
23
+ this.pythPriceIDs = pythPriceIDs
24
+ this.pythStateObjectId = "0x1f9310238ee9298fb703c3419030b35b22bb1cc37113e3bb5007c99aec79e5b8"
25
+ }
26
+
27
+ async swap(
28
+ client: AggregatorClient,
29
+ txb: Transaction,
30
+ path: Path,
31
+ inputCoin: TransactionObjectArgument,
32
+ packages?: Map<string, string>
33
+ ): Promise<TransactionObjectArgument> {
34
+ const { direction, from, target } = path
35
+ const [func, coinAType, coinBType] = direction
36
+ ? ["swap_a2b", from, target]
37
+ : ["swap_b2a", target, from]
38
+
39
+ let coinAPriceSeed
40
+ let coinBPriceSeed
41
+
42
+ let coinAPriceInfoObjectId
43
+ let coinBPriceInfoObjectId
44
+
45
+ if (path.extendedDetails == null) {
46
+ throw new Error("Extended details not supported in obric")
47
+ } else {
48
+ if (
49
+ path.extendedDetails.obricCoinAPriceSeed && path.extendedDetails.obricCoinBPriceSeed
50
+ ) {
51
+ coinAPriceSeed = path.extendedDetails.obricCoinAPriceSeed
52
+ coinAPriceInfoObjectId = this.pythPriceIDs.get(coinAPriceSeed!)
53
+ coinBPriceSeed = path.extendedDetails.obricCoinBPriceSeed
54
+ coinBPriceInfoObjectId = this.pythPriceIDs.get(coinBPriceSeed!)
55
+ } else {
56
+ if (!path.extendedDetails.obricCoinAPriceId || !path.extendedDetails.obricCoinBPriceId) {
57
+ throw new Error("Base price id or quote price id not supported")
58
+ } else {
59
+ coinAPriceInfoObjectId = path.extendedDetails.obricCoinAPriceId
60
+ coinBPriceInfoObjectId = path.extendedDetails.obricCoinBPriceId
61
+ }
62
+ }
63
+ }
64
+
65
+ if (!coinAPriceInfoObjectId || !coinBPriceInfoObjectId) {
66
+ throw new Error(
67
+ "Base price info object id or quote price info object id not found"
68
+ )
69
+ }
70
+
71
+ const args = [
72
+ txb.object(path.id),
73
+ inputCoin,
74
+ txb.object(this.pythStateObjectId),
75
+ txb.object(coinAPriceInfoObjectId),
76
+ txb.object(coinBPriceInfoObjectId),
77
+ txb.object(CLOCK_ADDRESS),
78
+ ]
79
+ const publishedAt = getAggregatorV2ExtendPublishedAt(
80
+ client.publishedAtV2Extend(),
81
+ packages
82
+ )
83
+ const res = txb.moveCall({
84
+ target: `${publishedAt}::obric::${func}`,
85
+ typeArguments: [coinAType, coinBType],
86
+ arguments: args,
87
+ }) as TransactionArgument
88
+ return res
89
+ }
90
+ }
@@ -0,0 +1,197 @@
1
+ import { describe, test } from "@jest/globals"
2
+ import dotenv from "dotenv"
3
+ import { AggregatorClient } from "~/client"
4
+ import { Ed25519Keypair } from "@mysten/sui/keypairs/ed25519"
5
+ import { printTransaction } from "~/utils/transaction"
6
+ import BN from "bn.js"
7
+ import { fromB64 } from "@mysten/sui/utils"
8
+ import { SuiClient } from "@mysten/sui/client"
9
+ import { Env } from "~/index"
10
+ import { Transaction } from "@mysten/sui/transactions"
11
+
12
+ dotenv.config()
13
+
14
+ export function buildTestAccount(): Ed25519Keypair {
15
+ const mnemonics = process.env.SUI_WALLET_MNEMONICS || ""
16
+ const testAccountObject = Ed25519Keypair.deriveKeypair(mnemonics)
17
+ return testAccountObject
18
+ }
19
+
20
+ describe("Test obric provider", () => {
21
+ let client: AggregatorClient
22
+ let keypair: Ed25519Keypair
23
+
24
+ const T_SUI = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
25
+ const WH_USDC = "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN"
26
+ const T_USDC = "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC"
27
+
28
+ beforeAll(() => {
29
+ const fullNodeURL = process.env.SUI_RPC!
30
+ const aggregatorURL = process.env.CETUS_AGGREGATOR!
31
+ const secret = process.env.SUI_WALLET_SECRET!
32
+
33
+ if (secret) {
34
+ keypair = Ed25519Keypair.fromSecretKey(fromB64(secret).slice(1, 33))
35
+ } else {
36
+ keypair = buildTestAccount()
37
+ }
38
+
39
+ // const wallet = keypair.getPublicKey().toSuiAddress()
40
+
41
+ const wallet = "0x935029ca5219502a47ac9b69f556ccf6e2198b5e7815cf50f68846f723739cbd" // has 80 eth
42
+ console.log("wallet: ", wallet)
43
+
44
+ const endpoint = aggregatorURL
45
+
46
+ const suiClient = new SuiClient({
47
+ url: fullNodeURL,
48
+ })
49
+ client = new AggregatorClient(endpoint, wallet, suiClient, Env.Mainnet)
50
+ })
51
+
52
+ test("Find Routers --> SUI -> USDC, locked", async () => {
53
+ // const amounts = ["1000", "1000000", "100000000", "5000000000", "10000000000000"]
54
+ const amounts = ["9990", "5000000000"]
55
+
56
+ for (const amount of amounts) {
57
+ const res = await client.findRouters({
58
+ from: T_SUI,
59
+ target: WH_USDC,
60
+ amount: new BN(amount),
61
+ byAmountIn: true,
62
+ depth: 3,
63
+ splitCount: 1,
64
+ providers: ["OBRIC"],
65
+ })
66
+
67
+ if (res != null) {
68
+ console.log(JSON.stringify(res, null, 2))
69
+ }
70
+ console.log("amount in", res?.amountIn.toString())
71
+ console.log("amount out", res?.amountOut.toString())
72
+
73
+ const txb = new Transaction()
74
+
75
+ if (res != null) {
76
+ console.log(JSON.stringify(res, null, 2))
77
+ await client.fastRouterSwap({
78
+ routers: res,
79
+ txb,
80
+ slippage: 0.01,
81
+ refreshAllCoins: true,
82
+ payDeepFeeAmount: 0,
83
+ })
84
+
85
+ txb.setSender(client.signer)
86
+ const buildTxb = await txb.build({ client: client.client })
87
+ // const buildTxb = await txb.getData()
88
+
89
+ console.log("buildTxb", buildTxb)
90
+ printTransaction(txb)
91
+
92
+ let result = await client.devInspectTransactionBlock(txb)
93
+ console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
94
+ for (const event of result.events) {
95
+ console.log("event", JSON.stringify(event, null, 2))
96
+ }
97
+ }
98
+ }
99
+ }, 50000)
100
+
101
+ test("Find Routers --> WUSDC --> SUI, no pyth mode", async () => {
102
+ // const amounts = ["1000", "1000000", "100000000", "5000000000", "10000000000000"]
103
+ // const amounts = ["1000", "1000000", "900000000"]
104
+ const amounts = ["90000000"]
105
+
106
+ for (const amount of amounts) {
107
+ const res = await client.findRouters({
108
+ from: T_USDC,
109
+ target: T_SUI,
110
+ amount: new BN(amount),
111
+ byAmountIn: true,
112
+ depth: 3,
113
+ splitCount: 1,
114
+ providers: ["OBRIC"],
115
+ })
116
+
117
+ if (res != null) {
118
+ console.log(JSON.stringify(res, null, 2))
119
+ }
120
+ console.log("amount in", res?.amountIn.toString())
121
+ console.log("amount out", res?.amountOut.toString())
122
+
123
+ const txb = new Transaction()
124
+
125
+ if (res != null) {
126
+ await client.fastRouterSwap({
127
+ routers: res,
128
+ txb,
129
+ slippage: 0.001,
130
+ refreshAllCoins: true,
131
+ payDeepFeeAmount: 0,
132
+ })
133
+
134
+ txb.setSender(client.signer)
135
+ const buildTxb = await txb.build({ client: client.client })
136
+ // const buildTxb = await txb.getData()
137
+
138
+ // printTransaction(txb)
139
+
140
+ let result = await client.devInspectTransactionBlock(txb)
141
+ console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
142
+ for (const event of result.events) {
143
+ console.log("event", JSON.stringify(event, null, 2))
144
+ }
145
+ }
146
+ }
147
+ })
148
+
149
+ test("Build Router TX", async () => {
150
+ const amount = "1000000"
151
+
152
+ const res = await client.findRouters({
153
+ from: T_USDC,
154
+ target: T_SUI,
155
+ amount: new BN(amount),
156
+ byAmountIn: true,
157
+ depth: 3,
158
+ providers: ["OBRIC"],
159
+ })
160
+
161
+ console.log("amount in", res?.amountIn.toString())
162
+ console.log("amount out", res?.amountOut.toString())
163
+
164
+ const txb = new Transaction()
165
+
166
+ if (res != null) {
167
+ console.log(JSON.stringify(res, null, 2))
168
+ await client.fastRouterSwap({
169
+ routers: res,
170
+ txb,
171
+ slippage: 0.01,
172
+ refreshAllCoins: true,
173
+ payDeepFeeAmount: 0,
174
+ })
175
+
176
+ txb.setSender(client.signer)
177
+ const buildTxb = await txb.build({ client: client.client })
178
+ // const buildTxb = await txb.getData()
179
+
180
+ console.log("buildTxb", buildTxb)
181
+ // printTransaction(txb)
182
+
183
+ let result = await client.devInspectTransactionBlock(txb)
184
+ console.log("🚀 ~ file: router.test.ts:180 ~ test ~ result:", result)
185
+ for (const event of result.events) {
186
+ console.log("event", JSON.stringify(event, null, 2))
187
+ }
188
+
189
+ // if (result.effects.status.status === "success") {
190
+ // const result = await client.signAndExecuteTransaction(txb, keypair)
191
+ // console.log("result", result)
192
+ // } else {
193
+ // console.log("result", result)
194
+ // }
195
+ }
196
+ }, 600000)
197
+ })