@imtbl/sdk 0.27.15 → 0.28.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.cjs CHANGED
@@ -3632,7 +3632,7 @@ class MultiRollupApiClients {
3632
3632
  }
3633
3633
 
3634
3634
  // eslint-disable-next-line @typescript-eslint/naming-convention
3635
- const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.27.15' };
3635
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.28.0' };
3636
3636
  const createConfig = ({ basePath, headers, }) => {
3637
3637
  if (!basePath.trim()) {
3638
3638
  throw Error('basePath can not be empty');
@@ -3692,7 +3692,7 @@ class APIError extends Error {
3692
3692
 
3693
3693
  /* eslint-disable implicit-arrow-linebreak */
3694
3694
  const defaultHeaders = {
3695
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.15',
3695
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.28.0',
3696
3696
  };
3697
3697
  /**
3698
3698
  * createAPIConfiguration to create a custom Configuration
@@ -4103,7 +4103,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
4103
4103
  chainID,
4104
4104
  coreContractAddress,
4105
4105
  registrationContractAddress,
4106
- sdkVersion: 'ts-immutable-sdk-0.27.15',
4106
+ sdkVersion: 'ts-immutable-sdk-0.28.0',
4107
4107
  });
4108
4108
  /**
4109
4109
  * Sets `sdkVersion` at the time of build
@@ -9053,7 +9053,7 @@ class MagicAdapter {
9053
9053
  magicClient;
9054
9054
  constructor(config) {
9055
9055
  this.config = config;
9056
- if (window) {
9056
+ if (typeof window !== 'undefined') {
9057
9057
  this.magicClient = this.initMagicClient();
9058
9058
  this.magicClient.preload();
9059
9059
  }
@@ -9289,7 +9289,7 @@ class GuardianClient {
9289
9289
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, transactionRejectedCrossSdkBridgeError);
9290
9290
  }
9291
9291
  if (confirmationRequired && !!messageId) {
9292
- const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId);
9292
+ const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId, user.zkEvm.ethAddress);
9293
9293
  if (!confirmationResult.confirmed) {
9294
9294
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, 'Signature rejected by user');
9295
9295
  }
@@ -9964,7 +9964,19 @@ class ConfirmationScreen {
9964
9964
  constructor(config) {
9965
9965
  this.config = config;
9966
9966
  }
9967
- requestConfirmation(transactionId, imxEtherAddress, chainType, chainId) {
9967
+ getHref(relativePath, queryStringParams) {
9968
+ let href = `${this.config.passportDomain}/transaction-confirmation/${relativePath}`;
9969
+ if (queryStringParams) {
9970
+ const queryString = queryStringParams
9971
+ ? Object.keys(queryStringParams)
9972
+ .map((key) => `${key}=${queryStringParams[key]}`)
9973
+ .join('&')
9974
+ : '';
9975
+ href = `${href}?${queryString}`;
9976
+ }
9977
+ return href;
9978
+ }
9979
+ requestConfirmation(transactionId, etherAddress, chainType, chainId) {
9968
9980
  return new Promise((resolve, reject) => {
9969
9981
  const messageHandler = ({ data, origin }) => {
9970
9982
  if (origin !== this.config.passportDomain
@@ -9994,17 +10006,17 @@ class ConfirmationScreen {
9994
10006
  window.addEventListener('message', messageHandler);
9995
10007
  let href = '';
9996
10008
  if (chainType === TransactionApprovalRequestChainTypeEnum.Starkex) {
9997
- // eslint-disable-next-line max-len
9998
- href = `${this.config.passportDomain}/transaction-confirmation/transaction?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=starkex`;
10009
+ href = this.getHref('transaction', { transactionId, etherAddress, chainType });
9999
10010
  }
10000
10011
  else {
10001
- // eslint-disable-next-line max-len
10002
- href = `${this.config.passportDomain}/transaction-confirmation/zkevm?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=evm&chainId=${chainId}`;
10012
+ href = this.getHref('zkevm', {
10013
+ transactionId, etherAddress, chainType, chainId,
10014
+ });
10003
10015
  }
10004
10016
  this.showConfirmationScreen(href, messageHandler, resolve);
10005
10017
  });
10006
10018
  }
10007
- requestMessageConfirmation(messageId) {
10019
+ requestMessageConfirmation(messageID, etherAddress) {
10008
10020
  return new Promise((resolve, reject) => {
10009
10021
  const messageHandler = ({ data, origin }) => {
10010
10022
  if (origin !== this.config.passportDomain
@@ -10032,7 +10044,7 @@ class ConfirmationScreen {
10032
10044
  return;
10033
10045
  }
10034
10046
  window.addEventListener('message', messageHandler);
10035
- const href = `${this.config.passportDomain}/transaction-confirmation/zkevm/message?messageID=${messageId}`;
10047
+ const href = this.getHref('zkevm/message', { messageID, etherAddress });
10036
10048
  this.showConfirmationScreen(href, messageHandler, resolve);
10037
10049
  });
10038
10050
  }
@@ -10042,7 +10054,7 @@ class ConfirmationScreen {
10042
10054
  return;
10043
10055
  }
10044
10056
  this.confirmationWindow = openPopupCenter({
10045
- url: `${this.config.passportDomain}/transaction-confirmation/loading`,
10057
+ url: this.getHref('loading'),
10046
10058
  title: CONFIRMATION_WINDOW_TITLE,
10047
10059
  width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
10048
10060
  height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
@@ -10055,7 +10067,7 @@ class ConfirmationScreen {
10055
10067
  return new Promise((resolve, rejects) => {
10056
10068
  const iframe = document.createElement('iframe');
10057
10069
  iframe.setAttribute('id', CONFIRMATION_IFRAME_ID);
10058
- iframe.setAttribute('src', `${this.config.passportDomain}/transaction-confirmation/logout`);
10070
+ iframe.setAttribute('src', this.getHref('logout'));
10059
10071
  iframe.setAttribute('style', CONFIRMATION_IFRAME_STYLE);
10060
10072
  const logoutHandler = ({ data, origin }) => {
10061
10073
  if (origin !== this.config.passportDomain
@@ -10499,7 +10511,17 @@ class ZkEvmProvider {
10499
10511
  this.magicAdapter = magicAdapter;
10500
10512
  this.config = config;
10501
10513
  this.confirmationScreen = confirmationScreen;
10502
- this.jsonRpcProvider = new providers.JsonRpcProvider(this.config.zkEvmRpcUrl);
10514
+ if (config.crossSdkBridgeEnabled) {
10515
+ // JsonRpcProvider by default sets the referrer as "client".
10516
+ // On Unreal 4 this errors as the browser used is expecting a valid URL.
10517
+ this.jsonRpcProvider = new providers.JsonRpcProvider({
10518
+ url: this.config.zkEvmRpcUrl,
10519
+ fetchOptions: { referrer: 'http://imtblgamesdk.local' },
10520
+ });
10521
+ }
10522
+ else {
10523
+ this.jsonRpcProvider = new providers.JsonRpcProvider(this.config.zkEvmRpcUrl);
10524
+ }
10503
10525
  this.multiRollupApiClients = multiRollupApiClients;
10504
10526
  this.eventEmitter = new TypedEventEmitter();
10505
10527
  passportEventEmitter.on(PassportEvents.LOGGED_OUT, this.handleLogout);
@@ -11422,7 +11444,7 @@ var CancelledOrderStatus;
11422
11444
  var FailedOrderCancellation;
11423
11445
  (function (FailedOrderCancellation) {
11424
11446
  (function (reason_code) {
11425
- reason_code["ALREADY_FILLED"] = "ALREADY_FILLED";
11447
+ reason_code["FILLED"] = "FILLED";
11426
11448
  })(FailedOrderCancellation.reason_code || (FailedOrderCancellation.reason_code = {}));
11427
11449
  })(FailedOrderCancellation || (FailedOrderCancellation = {}));
11428
11450
 
@@ -11476,10 +11498,12 @@ var TransactionPurpose;
11476
11498
  (function (TransactionPurpose) {
11477
11499
  TransactionPurpose["APPROVAL"] = "APPROVAL";
11478
11500
  TransactionPurpose["FULFILL_ORDER"] = "FULFILL_ORDER";
11501
+ TransactionPurpose["CANCEL"] = "CANCEL";
11479
11502
  })(TransactionPurpose || (TransactionPurpose = {}));
11480
11503
  var SignablePurpose;
11481
11504
  (function (SignablePurpose) {
11482
11505
  SignablePurpose["CREATE_LISTING"] = "CREATE_LISTING";
11506
+ SignablePurpose["OFF_CHAIN_CANCELLATION"] = "OFF_CHAIN_CANCELLATION";
11483
11507
  })(SignablePurpose || (SignablePurpose = {}));
11484
11508
  var ActionType;
11485
11509
  (function (ActionType) {
@@ -11876,11 +11900,15 @@ class Seaport {
11876
11900
  .reduce((p, c) => (new Date(p) < new Date(c) ? p : c)),
11877
11901
  };
11878
11902
  }
11879
- async cancelOrder(order, account) {
11880
- const { orderComponents } = this.mapImmutableOrderToSeaportOrderComponents(order);
11881
- const seaportLib = this.getSeaportLib(order);
11882
- const cancellationTransaction = await seaportLib.cancelOrders([orderComponents], account);
11883
- return prepareTransaction(cancellationTransaction)();
11903
+ async cancelOrders(orders, account) {
11904
+ const orderComponents = orders.map((order) => this.mapImmutableOrderToSeaportOrderComponents(order).orderComponents);
11905
+ const seaportLib = this.getSeaportLib(orders[0]);
11906
+ const cancellationTransaction = await seaportLib.cancelOrders(orderComponents, account);
11907
+ return {
11908
+ type: ActionType.TRANSACTION,
11909
+ buildTransaction: prepareTransaction(cancellationTransaction),
11910
+ purpose: TransactionPurpose.CANCEL,
11911
+ };
11884
11912
  }
11885
11913
  mapImmutableOrderToSeaportOrderComponents(order) {
11886
11914
  const orderCounter = order.protocol_data.counter;
@@ -11982,6 +12010,16 @@ class ImmutableApiClient {
11982
12010
  ...listTradesParams,
11983
12011
  });
11984
12012
  }
12013
+ async cancelOrders(orderIds, accountAddress, signature) {
12014
+ return this.orderbookService.cancelOrders({
12015
+ chainName: this.chainName,
12016
+ requestBody: {
12017
+ account_address: accountAddress,
12018
+ orders: orderIds,
12019
+ signature,
12020
+ },
12021
+ });
12022
+ }
11985
12023
  async createListing({ orderHash, orderComponents, orderSignature, makerFees, }) {
11986
12024
  if (orderComponents.offer.length !== 1) {
11987
12025
  throw new Error('Only one item can be listed at a time');
@@ -12283,24 +12321,89 @@ class Orderbook {
12283
12321
  }
12284
12322
  }
12285
12323
  /**
12286
- * Get an unsigned cancel order transaction. Orders can only be cancelled by
12287
- * the account that created them.
12288
- * @param {string} listingId - The listingId to cancel.
12324
+ * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
12325
+ * `cancelOrdersOnChain`. For the orderbook to authenticate the cancellation, the creator
12326
+ * of the orders must sign an EIP712 message containing the orderIds
12327
+ * @param {string} orderIds - The orderIds to attempt to cancel.
12328
+ * @return {PrepareCancelOrdersResponse} The signable action to cancel the orders.
12329
+ */
12330
+ async prepareOrderCancellations(orderIds) {
12331
+ const network = await this.orderbookConfig.provider.getNetwork();
12332
+ const domain = {
12333
+ name: 'imtbl-order-book',
12334
+ chainId: network.chainId,
12335
+ verifyingContract: this.orderbookConfig.seaportContractAddress,
12336
+ };
12337
+ const types = {
12338
+ // eslint-disable-next-line @typescript-eslint/naming-convention
12339
+ CancelPayload: [
12340
+ { name: 'orders', type: 'Order[]' },
12341
+ ],
12342
+ // eslint-disable-next-line @typescript-eslint/naming-convention
12343
+ Order: [
12344
+ { name: 'id', type: 'string' },
12345
+ ],
12346
+ };
12347
+ const cancelMessage = {
12348
+ orders: orderIds.map((id) => ({ id })),
12349
+ };
12350
+ return {
12351
+ signableAction: {
12352
+ purpose: SignablePurpose.OFF_CHAIN_CANCELLATION,
12353
+ type: ActionType.SIGNABLE,
12354
+ message: {
12355
+ domain,
12356
+ types,
12357
+ value: cancelMessage,
12358
+ },
12359
+ },
12360
+ };
12361
+ }
12362
+ /**
12363
+ * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
12364
+ * `cancelOrdersOnChain`. Orders cancelled this way cannot be fulfilled and will be removed
12365
+ * from the orderbook. If there is pending fulfillment data outstanding for the order, its
12366
+ * cancellation will be pending until the fulfillment window has passed.
12367
+ * `prepareOffchainOrderCancellations` can be used to get the signable action that is signed
12368
+ * to get the signature required for this call.
12369
+ * @param {string[]} orderIds - The orderIds to attempt to cancel.
12370
+ * @param {string} accountAddress - The address of the account cancelling the orders.
12371
+ * @param {string} accountAddress - The address of the account cancelling the orders.
12372
+ * @return {CancelOrdersResult} The result of the off-chain cancellation request
12373
+ */
12374
+ async cancelOrders(orderIds, accountAddress, signature) {
12375
+ return this.apiClient.cancelOrders(orderIds, accountAddress, signature);
12376
+ }
12377
+ /**
12378
+ * Get an unsigned order cancellation transaction. Orders can only be cancelled by
12379
+ * the account that created them. All of the orders must be from the same seaport contract.
12380
+ * If trying to cancel orders from multiple seaport contracts, group the orderIds by seaport
12381
+ * contract and call this method for each group.
12382
+ * @param {string[]} orderIds - The orderIds to cancel.
12289
12383
  * @param {string} accountAddress - The address of the account cancelling the order.
12290
- * @return {CancelOrderResponse} The unsigned cancel order transaction
12384
+ * @return {CancelOrdersOnChainResponse} The unsigned cancel order action
12291
12385
  */
12292
- async cancelOrder(listingId, accountAddress) {
12293
- const orderResult = await this.apiClient.getListing(listingId);
12294
- if (orderResult.result.status.name !== OrderStatusName.ACTIVE
12295
- && orderResult.result.status.name !== OrderStatusName.INACTIVE
12296
- && orderResult.result.status.name !== OrderStatusName.PENDING) {
12297
- throw new Error(`Cannot cancel order with status ${orderResult.result.status}`);
12386
+ async cancelOrdersOnChain(orderIds, accountAddress) {
12387
+ const orderResults = await Promise.all(orderIds.map((id) => this.apiClient.getListing(id)));
12388
+ // eslint-disable-next-line no-restricted-syntax
12389
+ for (const orderResult of orderResults) {
12390
+ if (orderResult.result.status.name !== OrderStatusName.ACTIVE
12391
+ && orderResult.result.status.name !== OrderStatusName.INACTIVE
12392
+ && orderResult.result.status.name !== OrderStatusName.PENDING) {
12393
+ throw new Error(`Cannot cancel order with status ${orderResult.result.status}`);
12394
+ }
12395
+ if (orderResult.result.account_address !== accountAddress.toLowerCase()) {
12396
+ throw new Error(`Only account ${orderResult.result.account_address} can cancel order ${orderResult.result.id}`);
12397
+ }
12298
12398
  }
12299
- if (orderResult.result.account_address !== accountAddress.toLowerCase()) {
12300
- throw new Error(`Only account ${orderResult.result.account_address} can cancel order ${listingId}`);
12399
+ const orders = orderResults.map((orderResult) => orderResult.result);
12400
+ const seaportAddresses = orders.map((o) => o.protocol_data.seaport_address);
12401
+ const distinctSeaportAddresses = new Set(...[seaportAddresses]);
12402
+ if (distinctSeaportAddresses.size !== 1) {
12403
+ throw new Error('Cannot cancel multiple orders from different seaport contracts. Please group your orderIds accordingly');
12301
12404
  }
12302
- const cancelOrderTransaction = await this.seaport.cancelOrder(orderResult.result, accountAddress);
12303
- return { unsignedCancelOrderTransaction: cancelOrderTransaction };
12405
+ const cancellationAction = await this.seaport.cancelOrders(orders, accountAddress);
12406
+ return { cancellationAction };
12304
12407
  }
12305
12408
  }
12306
12409
 
@@ -28099,6 +28202,7 @@ const newAmount = (amount, token) => ({
28099
28202
  });
28100
28203
  const isERC20Amount = (amount) => amount.token.type === 'erc20';
28101
28204
  const isNativeAmount = (amount) => amount.token.type === 'native';
28205
+ const isNative = (token) => token.type === 'native';
28102
28206
  const addERC20Amount = (a, b) => {
28103
28207
  // Make sure the ERC20s have the same address
28104
28208
  if (a.token.address !== b.token.address)
@@ -28752,92 +28856,193 @@ const IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS = [
28752
28856
 
28753
28857
  const zeroNativeCurrencyValue = '0x00';
28754
28858
  const multicallWithDeadlineFunctionSignature = 'multicall(uint256,bytes[])';
28755
- function buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28859
+ function buildSinglePoolSwap(tokenIn, tokenOut, recipient, trade, route, amountIn, amountOut, routerContract, paymentsContract) {
28860
+ const calldatas = [];
28861
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_INPUT) {
28862
+ calldatas.push(routerContract.encodeFunctionData('exactInputSingle', [
28863
+ {
28864
+ tokenIn: route.tokenPath[0].address,
28865
+ tokenOut: route.tokenPath[1].address,
28866
+ fee: route.pools[0].fee,
28867
+ recipient,
28868
+ amountIn,
28869
+ amountOutMinimum: amountOut,
28870
+ sqrtPriceLimitX96: 0,
28871
+ },
28872
+ ]));
28873
+ }
28874
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT) {
28875
+ calldatas.push(routerContract.encodeFunctionData('exactOutputSingle', [
28876
+ {
28877
+ tokenIn: route.tokenPath[0].address,
28878
+ tokenOut: route.tokenPath[1].address,
28879
+ fee: route.pools[0].fee,
28880
+ recipient,
28881
+ amountInMaximum: amountIn,
28882
+ amountOut,
28883
+ sqrtPriceLimitX96: 0,
28884
+ },
28885
+ ]));
28886
+ }
28887
+ const shouldRefundNativeTokens = trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT && isNative(tokenIn);
28888
+ if (shouldRefundNativeTokens) {
28889
+ // Refund ETH if the input token is native and the swap is exact output
28890
+ calldatas.push(paymentsContract.encodeFunctionData('refundETH'));
28891
+ }
28892
+ const shouldUnwrapTokens = isNative(tokenOut);
28893
+ if (shouldUnwrapTokens) {
28894
+ // Unwrap the output token if the user specified a native token as the output
28895
+ calldatas.push(paymentsContract.encodeFunctionData('unwrapWETH9(uint256)', [amountOut]));
28896
+ }
28897
+ return calldatas;
28898
+ }
28899
+ function buildSinglePoolSwapWithFees(recipient, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28756
28900
  const secondaryFeeValues = secondaryFees.map((fee) => ({
28757
28901
  feeBasisPoints: fee.basisPoints,
28758
28902
  recipient: fee.recipient,
28759
28903
  }));
28760
- if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28761
- return secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [
28904
+ const calldatas = [];
28905
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_INPUT) {
28906
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [
28762
28907
  secondaryFeeValues,
28763
28908
  {
28764
28909
  tokenIn: route.tokenPath[0].address,
28765
28910
  tokenOut: route.tokenPath[1].address,
28766
28911
  fee: route.pools[0].fee,
28767
- recipient: fromAddress,
28912
+ recipient,
28768
28913
  amountIn,
28769
28914
  amountOutMinimum: amountOut,
28770
28915
  sqrtPriceLimitX96: 0,
28771
28916
  },
28772
- ]);
28917
+ ]));
28773
28918
  }
28774
- return secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [
28775
- secondaryFeeValues,
28776
- {
28777
- tokenIn: route.tokenPath[0].address,
28778
- tokenOut: route.tokenPath[1].address,
28779
- fee: route.pools[0].fee,
28780
- recipient: fromAddress,
28781
- amountInMaximum: amountIn,
28782
- amountOut,
28783
- sqrtPriceLimitX96: 0,
28784
- },
28785
- ]);
28919
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT) {
28920
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [
28921
+ secondaryFeeValues,
28922
+ {
28923
+ tokenIn: route.tokenPath[0].address,
28924
+ tokenOut: route.tokenPath[1].address,
28925
+ fee: route.pools[0].fee,
28926
+ recipient,
28927
+ amountInMaximum: amountIn,
28928
+ amountOut,
28929
+ sqrtPriceLimitX96: 0,
28930
+ },
28931
+ ]));
28932
+ }
28933
+ // TODO: Add refundETH method when support is added in SecondaryFee contract
28934
+ return calldatas;
28786
28935
  }
28787
- function buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28788
- const path = v3Sdk.encodeRouteToPath(route, trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT);
28936
+ function buildMultiPoolSwap(tokenIn, tokenOut, recipient, trade, route, amountIn, amountOut, routerContract, paymentsContract) {
28937
+ const path = v3Sdk.encodeRouteToPath(route, trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT);
28938
+ const calldatas = [];
28939
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_INPUT) {
28940
+ calldatas.push(routerContract.encodeFunctionData('exactInput', [
28941
+ {
28942
+ path,
28943
+ recipient,
28944
+ amountIn,
28945
+ amountOutMinimum: amountOut,
28946
+ },
28947
+ ]));
28948
+ }
28949
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT) {
28950
+ calldatas.push(routerContract.encodeFunctionData('exactOutput', [
28951
+ {
28952
+ path,
28953
+ recipient,
28954
+ amountInMaximum: amountIn,
28955
+ amountOut,
28956
+ },
28957
+ ]));
28958
+ }
28959
+ const shouldRefundNativeTokens = trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT && isNative(tokenIn);
28960
+ if (shouldRefundNativeTokens) {
28961
+ // Refund ETH if the input token is native and the swap is exact output
28962
+ calldatas.push(paymentsContract.encodeFunctionData('refundETH'));
28963
+ }
28964
+ const shouldUnwrapTokens = isNative(tokenOut);
28965
+ if (shouldUnwrapTokens) {
28966
+ // Unwrap the output token if the user specified a native token as the output
28967
+ calldatas.push(paymentsContract.encodeFunctionData('unwrapWETH9(uint256)', [amountOut]));
28968
+ }
28969
+ return calldatas;
28970
+ }
28971
+ function buildMultiPoolSwapWithFees(recipient, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28972
+ const path = v3Sdk.encodeRouteToPath(route, trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT);
28789
28973
  const secondaryFeeValues = secondaryFees.map((fee) => ({
28790
28974
  feeBasisPoints: fee.basisPoints,
28791
28975
  recipient: fee.recipient,
28792
28976
  }));
28793
- if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28794
- return secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [
28977
+ const calldatas = [];
28978
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_INPUT) {
28979
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [
28795
28980
  secondaryFeeValues,
28796
28981
  {
28797
28982
  path,
28798
- recipient: fromAddress,
28983
+ recipient,
28799
28984
  amountIn,
28800
28985
  amountOutMinimum: amountOut,
28801
28986
  },
28802
- ]);
28987
+ ]));
28803
28988
  }
28804
- return secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [
28805
- secondaryFeeValues,
28806
- {
28807
- path,
28808
- recipient: fromAddress,
28809
- amountInMaximum: amountIn,
28810
- amountOut,
28811
- },
28812
- ]);
28989
+ if (trade.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT) {
28990
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [
28991
+ secondaryFeeValues,
28992
+ {
28993
+ path,
28994
+ recipient,
28995
+ amountInMaximum: amountIn,
28996
+ amountOut,
28997
+ },
28998
+ ]));
28999
+ }
29000
+ // TODO: Add refundETH method when support is added in SecondaryFee contract
29001
+ return calldatas;
28813
29002
  }
28814
29003
  /**
28815
- * Builds swap parameters
28816
- * @param fromAddress the msg.sender of the transaction
28817
- * @param secondaryFeeAddress the secondary fee contract address
28818
- * @param trade details of the swap, including the route, input/output tokens and amounts
28819
- * @param options additional swap options
28820
- * @returns calldata for the swap
29004
+ * Builds and array of calldatas for the swap to be executed in the multicall method
29005
+ * @param tokenIn The token to be swapped
29006
+ * @param tokenOut The token to be received
29007
+ * @param fromAddress The address of the user
29008
+ * @param trade The trade to be executed
29009
+ * @param secondaryFees Secondary fees to be applied to the swap
29010
+ * @param secondaryFeeContract The SecondaryFee contract interface
29011
+ * @param routerContract The SwapRouter02 contract interface
29012
+ * @param paymentsContract The PaymentsExtended contract interface
29013
+ * @param maximumAmountIn The maximum amount of tokenIn to be swapped
29014
+ * @param minimumAmountOut The minimum amount of tokenOut to be received
29015
+ * @returns calldatas that make up the swap transaction
28821
29016
  */
28822
- function buildSwapParameters(fromAddress, trade, options, secondaryFees, secondaryFeeContract, maximumAmountIn, minimumAmountOut) {
29017
+ function buildSwapParameters(tokenIn, tokenOut, recipient, trade, secondaryFees, secondaryFeeContract, routerContract, paymentsContract, maximumAmountIn, minimumAmountOut) {
28823
29018
  // @dev we don't support multiple swaps in a single transaction
28824
29019
  // there will always be only one swap in the trade regardless of the trade type
28825
29020
  const { route } = trade.swaps[0];
28826
29021
  const isSinglePoolSwap = route.pools.length === 1;
29022
+ const hasSecondaryFees = secondaryFees.length > 0;
28827
29023
  if (isSinglePoolSwap) {
28828
- return buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29024
+ if (hasSecondaryFees) {
29025
+ return buildSinglePoolSwapWithFees(recipient, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29026
+ }
29027
+ return buildSinglePoolSwap(tokenIn, tokenOut, recipient, trade, route, maximumAmountIn, minimumAmountOut, routerContract, paymentsContract);
29028
+ }
29029
+ if (hasSecondaryFees) {
29030
+ return buildMultiPoolSwapWithFees(recipient, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
28829
29031
  }
28830
- return buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29032
+ return buildMultiPoolSwap(tokenIn, tokenOut, recipient, trade, route, maximumAmountIn, minimumAmountOut, routerContract, paymentsContract);
28831
29033
  }
28832
- function createSwapCallParametersWithFees(trade, fromAddress, swapOptions, secondaryFees, maximumAmountIn, minimumAmountOut) {
29034
+ function createSwapCallParameters(tokenIn, tokenOut, trade, recipient, swapOptions, secondaryFees, maximumAmountIn, minimumAmountOut) {
28833
29035
  const secondaryFeeContract = SecondaryFee__factory.createInterface();
28834
- const swapWithFeesCalldata = buildSwapParameters(fromAddress, trade, swapOptions, secondaryFees, secondaryFeeContract, maximumAmountIn, minimumAmountOut);
29036
+ const routerContract = routerSdk.SwapRouter.INTERFACE;
29037
+ const paymentsContract = routerSdk.PaymentsExtended.INTERFACE;
29038
+ const calldatas = buildSwapParameters(tokenIn, tokenOut, recipient, trade, secondaryFees, secondaryFeeContract, routerContract, paymentsContract, maximumAmountIn, minimumAmountOut);
29039
+ // Create the multicall transaction using the calldatas generated above
28835
29040
  return secondaryFeeContract.encodeFunctionData(multicallWithDeadlineFunctionSignature, [
28836
29041
  swapOptions.deadlineOrPreviousBlockhash,
28837
- [swapWithFeesCalldata],
29042
+ calldatas,
28838
29043
  ]);
28839
29044
  }
28840
- function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees) {
29045
+ function createSwapParameters(tokenIn, tokenOut, adjustedQuote, fromAddress, slippage, deadline, secondaryFees) {
28841
29046
  // Create an unchecked trade to be used in generating swap parameters.
28842
29047
  const uncheckedTrade = v3Sdk.Trade.createUncheckedTrade({
28843
29048
  route: adjustedQuote.route,
@@ -28852,29 +29057,26 @@ function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, se
28852
29057
  deadlineOrPreviousBlockhash: deadline,
28853
29058
  };
28854
29059
  // If the trade type is EXACT_INPUT, then the maximum amount-in is the user-specified amount (no slippage applied)
29060
+ // For EXACT_OUTPUT, the maximum amount-in is the amount-in with slippage applied
28855
29061
  // https://github.com/Uniswap/v3-sdk/blob/81d66099f07d1ec350767f497ef73222575fe032/src/entities/trade.ts#L456
28856
29062
  const maximumAmountIn = v3Sdk.toHex(uncheckedTrade.maximumAmountIn(options.slippageTolerance).quotient);
28857
29063
  const minimumAmountOut = v3Sdk.toHex(uncheckedTrade.minimumAmountOut(options.slippageTolerance).quotient);
28858
- if (secondaryFees.length === 0) {
28859
- // Generate swap parameters without secondary fee contract details
28860
- return { calldata: routerSdk.SwapRouter.swapCallParameters([uncheckedTrade], options).calldata, maximumAmountIn };
28861
- }
28862
29064
  return {
28863
- calldata: createSwapCallParametersWithFees(uncheckedTrade, fromAddress, options, secondaryFees, maximumAmountIn, minimumAmountOut),
29065
+ calldata: createSwapCallParameters(tokenIn, tokenOut, uncheckedTrade, fromAddress, options, secondaryFees, maximumAmountIn, minimumAmountOut),
28864
29066
  maximumAmountIn,
28865
29067
  };
28866
29068
  }
28867
29069
  const getTransactionValue = (tokenIn, maximumAmountIn) => tokenIn.type === 'native' ? maximumAmountIn : zeroNativeCurrencyValue;
28868
- function getSwap(tokenIn, adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees) {
28869
- // TODO: TP-1651: Include `refundETH` transaction as final step for native Exact Output swaps
28870
- const { calldata, maximumAmountIn } = createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees);
29070
+ function getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippage, deadline, routerContractAddress, secondaryFeesContractAddress, gasPrice, secondaryFees) {
29071
+ const swapRecipient = isNative(tokenOut) ? routerContractAddress : fromAddress;
29072
+ const { calldata, maximumAmountIn } = createSwapParameters(tokenIn, tokenOut, adjustedQuote, swapRecipient, slippage, deadline, secondaryFees);
28871
29073
  // TODO: Add additional gas fee estimates for secondary fees
28872
29074
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, adjustedQuote.gasEstimate) : null;
28873
29075
  const transactionValue = getTransactionValue(tokenIn, maximumAmountIn);
28874
29076
  return {
28875
29077
  transaction: {
28876
29078
  data: calldata,
28877
- to: secondaryFees.length > 0 ? secondaryFeesAddress : peripheryRouterAddress,
29079
+ to: secondaryFees.length > 0 ? secondaryFeesContractAddress : routerContractAddress,
28878
29080
  value: transactionValue,
28879
29081
  from: fromAddress,
28880
29082
  },
@@ -28882,7 +29084,7 @@ function getSwap(tokenIn, adjustedQuote, fromAddress, slippage, deadline, periph
28882
29084
  };
28883
29085
  }
28884
29086
  const adjustAmountIn = (ourQuote, amountSpecified, fees, nativeTokenService) => {
28885
- if (ourQuote.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
29087
+ if (ourQuote.tradeType === Uniswap__namespace.TradeType.EXACT_OUTPUT) {
28886
29088
  // when doing exact output, calculate the fees based on the amountIn
28887
29089
  const amountToAdd = canUnwrapToken(fees.token)
28888
29090
  ? nativeTokenService.unwrapAmount(ourQuote.amountIn)
@@ -29088,7 +29290,7 @@ class Exchange {
29088
29290
  fetchGasPrice(this.provider, this.nativeToken),
29089
29291
  ]);
29090
29292
  const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
29091
- const swap = getSwap(tokenIn, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
29293
+ const swap = getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
29092
29294
  const { quotedAmount, quotedAmountWithMaxSlippage } = prepareUserQuote(this.nativeTokenService, adjustedQuote, slippagePercent, otherToken);
29093
29295
  const preparedApproval = prepareApproval(tradeType, amountSpecified, quotedAmountWithMaxSlippage, {
29094
29296
  routerAddress: this.routerContractAddress,
@@ -32856,8 +33058,10 @@ const $9c3db1bb9c8b69d3$export$70b61ad426ddbe54 = async (config, provider, order
32856
33058
  try {
32857
33059
  const offererAddress = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the address from the provider", provider.getSigner().getAddress());
32858
33060
  const orderbook = $67fc622a2b913d5f$export$c60ce6c6a92bc2ff(config);
32859
- const cancelOrderResponse = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the cancel order from the orderbook", orderbook.cancelOrder(orderId, offererAddress));
32860
- unsignedCancelOrderTransaction = cancelOrderResponse.unsignedCancelOrderTransaction;
33061
+ const cancelOrderResponse = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the cancel order from the orderbook", orderbook.cancelOrdersOnChain([
33062
+ orderId
33063
+ ], offererAddress));
33064
+ unsignedCancelOrderTransaction = await cancelOrderResponse.cancellationAction.buildTransaction();
32861
33065
  } catch (err) {
32862
33066
  throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("An error occurred while cancelling the order listing", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).CANCEL_ORDER_LISTING_ERROR, {
32863
33067
  orderId: orderId,
@@ -33355,7 +33559,7 @@ var $045213b18e9f1f94$export$75be0f6af9650f2c;
33355
33559
  })($045213b18e9f1f94$export$75be0f6af9650f2c || ($045213b18e9f1f94$export$75be0f6af9650f2c = {}));
33356
33560
 
33357
33561
 
33358
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.15";
33562
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.28.0";
33359
33563
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
33360
33564
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
33361
33565