@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.js CHANGED
@@ -22,7 +22,7 @@ import { TradeType, Percent } from '@uniswap/sdk-core';
22
22
  import assert from 'assert';
23
23
  import { FeeAmount, Route, SwapQuoter, Pool, Trade, toHex as toHex$1, encodeRouteToPath } from '@uniswap/v3-sdk';
24
24
  import { keccak256 as keccak256$1 } from '@ethersproject/solidity';
25
- import { SwapRouter } from '@uniswap/router-sdk';
25
+ import { SwapRouter, PaymentsExtended } from '@uniswap/router-sdk';
26
26
  import { jsx } from 'react/jsx-runtime';
27
27
  import { useEffect } from 'react';
28
28
 
@@ -3610,7 +3610,7 @@ class MultiRollupApiClients {
3610
3610
  }
3611
3611
 
3612
3612
  // eslint-disable-next-line @typescript-eslint/naming-convention
3613
- const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.27.15' };
3613
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.28.0' };
3614
3614
  const createConfig = ({ basePath, headers, }) => {
3615
3615
  if (!basePath.trim()) {
3616
3616
  throw Error('basePath can not be empty');
@@ -3670,7 +3670,7 @@ class APIError extends Error {
3670
3670
 
3671
3671
  /* eslint-disable implicit-arrow-linebreak */
3672
3672
  const defaultHeaders = {
3673
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.15',
3673
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.28.0',
3674
3674
  };
3675
3675
  /**
3676
3676
  * createAPIConfiguration to create a custom Configuration
@@ -4081,7 +4081,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
4081
4081
  chainID,
4082
4082
  coreContractAddress,
4083
4083
  registrationContractAddress,
4084
- sdkVersion: 'ts-immutable-sdk-0.27.15',
4084
+ sdkVersion: 'ts-immutable-sdk-0.28.0',
4085
4085
  });
4086
4086
  /**
4087
4087
  * Sets `sdkVersion` at the time of build
@@ -9031,7 +9031,7 @@ class MagicAdapter {
9031
9031
  magicClient;
9032
9032
  constructor(config) {
9033
9033
  this.config = config;
9034
- if (window) {
9034
+ if (typeof window !== 'undefined') {
9035
9035
  this.magicClient = this.initMagicClient();
9036
9036
  this.magicClient.preload();
9037
9037
  }
@@ -9267,7 +9267,7 @@ class GuardianClient {
9267
9267
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, transactionRejectedCrossSdkBridgeError);
9268
9268
  }
9269
9269
  if (confirmationRequired && !!messageId) {
9270
- const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId);
9270
+ const confirmationResult = await this.confirmationScreen.requestMessageConfirmation(messageId, user.zkEvm.ethAddress);
9271
9271
  if (!confirmationResult.confirmed) {
9272
9272
  throw new JsonRpcError(RpcErrorCode.TRANSACTION_REJECTED, 'Signature rejected by user');
9273
9273
  }
@@ -9942,7 +9942,19 @@ class ConfirmationScreen {
9942
9942
  constructor(config) {
9943
9943
  this.config = config;
9944
9944
  }
9945
- requestConfirmation(transactionId, imxEtherAddress, chainType, chainId) {
9945
+ getHref(relativePath, queryStringParams) {
9946
+ let href = `${this.config.passportDomain}/transaction-confirmation/${relativePath}`;
9947
+ if (queryStringParams) {
9948
+ const queryString = queryStringParams
9949
+ ? Object.keys(queryStringParams)
9950
+ .map((key) => `${key}=${queryStringParams[key]}`)
9951
+ .join('&')
9952
+ : '';
9953
+ href = `${href}?${queryString}`;
9954
+ }
9955
+ return href;
9956
+ }
9957
+ requestConfirmation(transactionId, etherAddress, chainType, chainId) {
9946
9958
  return new Promise((resolve, reject) => {
9947
9959
  const messageHandler = ({ data, origin }) => {
9948
9960
  if (origin !== this.config.passportDomain
@@ -9972,17 +9984,17 @@ class ConfirmationScreen {
9972
9984
  window.addEventListener('message', messageHandler);
9973
9985
  let href = '';
9974
9986
  if (chainType === TransactionApprovalRequestChainTypeEnum.Starkex) {
9975
- // eslint-disable-next-line max-len
9976
- href = `${this.config.passportDomain}/transaction-confirmation/transaction?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=starkex`;
9987
+ href = this.getHref('transaction', { transactionId, etherAddress, chainType });
9977
9988
  }
9978
9989
  else {
9979
- // eslint-disable-next-line max-len
9980
- href = `${this.config.passportDomain}/transaction-confirmation/zkevm?transactionId=${transactionId}&imxEtherAddress=${imxEtherAddress}&chainType=evm&chainId=${chainId}`;
9990
+ href = this.getHref('zkevm', {
9991
+ transactionId, etherAddress, chainType, chainId,
9992
+ });
9981
9993
  }
9982
9994
  this.showConfirmationScreen(href, messageHandler, resolve);
9983
9995
  });
9984
9996
  }
9985
- requestMessageConfirmation(messageId) {
9997
+ requestMessageConfirmation(messageID, etherAddress) {
9986
9998
  return new Promise((resolve, reject) => {
9987
9999
  const messageHandler = ({ data, origin }) => {
9988
10000
  if (origin !== this.config.passportDomain
@@ -10010,7 +10022,7 @@ class ConfirmationScreen {
10010
10022
  return;
10011
10023
  }
10012
10024
  window.addEventListener('message', messageHandler);
10013
- const href = `${this.config.passportDomain}/transaction-confirmation/zkevm/message?messageID=${messageId}`;
10025
+ const href = this.getHref('zkevm/message', { messageID, etherAddress });
10014
10026
  this.showConfirmationScreen(href, messageHandler, resolve);
10015
10027
  });
10016
10028
  }
@@ -10020,7 +10032,7 @@ class ConfirmationScreen {
10020
10032
  return;
10021
10033
  }
10022
10034
  this.confirmationWindow = openPopupCenter({
10023
- url: `${this.config.passportDomain}/transaction-confirmation/loading`,
10035
+ url: this.getHref('loading'),
10024
10036
  title: CONFIRMATION_WINDOW_TITLE,
10025
10037
  width: popupOptions?.width || CONFIRMATION_WINDOW_WIDTH,
10026
10038
  height: popupOptions?.height || CONFIRMATION_WINDOW_HEIGHT,
@@ -10033,7 +10045,7 @@ class ConfirmationScreen {
10033
10045
  return new Promise((resolve, rejects) => {
10034
10046
  const iframe = document.createElement('iframe');
10035
10047
  iframe.setAttribute('id', CONFIRMATION_IFRAME_ID);
10036
- iframe.setAttribute('src', `${this.config.passportDomain}/transaction-confirmation/logout`);
10048
+ iframe.setAttribute('src', this.getHref('logout'));
10037
10049
  iframe.setAttribute('style', CONFIRMATION_IFRAME_STYLE);
10038
10050
  const logoutHandler = ({ data, origin }) => {
10039
10051
  if (origin !== this.config.passportDomain
@@ -10477,7 +10489,17 @@ class ZkEvmProvider {
10477
10489
  this.magicAdapter = magicAdapter;
10478
10490
  this.config = config;
10479
10491
  this.confirmationScreen = confirmationScreen;
10480
- this.jsonRpcProvider = new JsonRpcProvider(this.config.zkEvmRpcUrl);
10492
+ if (config.crossSdkBridgeEnabled) {
10493
+ // JsonRpcProvider by default sets the referrer as "client".
10494
+ // On Unreal 4 this errors as the browser used is expecting a valid URL.
10495
+ this.jsonRpcProvider = new JsonRpcProvider({
10496
+ url: this.config.zkEvmRpcUrl,
10497
+ fetchOptions: { referrer: 'http://imtblgamesdk.local' },
10498
+ });
10499
+ }
10500
+ else {
10501
+ this.jsonRpcProvider = new JsonRpcProvider(this.config.zkEvmRpcUrl);
10502
+ }
10481
10503
  this.multiRollupApiClients = multiRollupApiClients;
10482
10504
  this.eventEmitter = new TypedEventEmitter();
10483
10505
  passportEventEmitter.on(PassportEvents.LOGGED_OUT, this.handleLogout);
@@ -11400,7 +11422,7 @@ var CancelledOrderStatus;
11400
11422
  var FailedOrderCancellation;
11401
11423
  (function (FailedOrderCancellation) {
11402
11424
  (function (reason_code) {
11403
- reason_code["ALREADY_FILLED"] = "ALREADY_FILLED";
11425
+ reason_code["FILLED"] = "FILLED";
11404
11426
  })(FailedOrderCancellation.reason_code || (FailedOrderCancellation.reason_code = {}));
11405
11427
  })(FailedOrderCancellation || (FailedOrderCancellation = {}));
11406
11428
 
@@ -11454,10 +11476,12 @@ var TransactionPurpose;
11454
11476
  (function (TransactionPurpose) {
11455
11477
  TransactionPurpose["APPROVAL"] = "APPROVAL";
11456
11478
  TransactionPurpose["FULFILL_ORDER"] = "FULFILL_ORDER";
11479
+ TransactionPurpose["CANCEL"] = "CANCEL";
11457
11480
  })(TransactionPurpose || (TransactionPurpose = {}));
11458
11481
  var SignablePurpose;
11459
11482
  (function (SignablePurpose) {
11460
11483
  SignablePurpose["CREATE_LISTING"] = "CREATE_LISTING";
11484
+ SignablePurpose["OFF_CHAIN_CANCELLATION"] = "OFF_CHAIN_CANCELLATION";
11461
11485
  })(SignablePurpose || (SignablePurpose = {}));
11462
11486
  var ActionType;
11463
11487
  (function (ActionType) {
@@ -11854,11 +11878,15 @@ class Seaport {
11854
11878
  .reduce((p, c) => (new Date(p) < new Date(c) ? p : c)),
11855
11879
  };
11856
11880
  }
11857
- async cancelOrder(order, account) {
11858
- const { orderComponents } = this.mapImmutableOrderToSeaportOrderComponents(order);
11859
- const seaportLib = this.getSeaportLib(order);
11860
- const cancellationTransaction = await seaportLib.cancelOrders([orderComponents], account);
11861
- return prepareTransaction(cancellationTransaction)();
11881
+ async cancelOrders(orders, account) {
11882
+ const orderComponents = orders.map((order) => this.mapImmutableOrderToSeaportOrderComponents(order).orderComponents);
11883
+ const seaportLib = this.getSeaportLib(orders[0]);
11884
+ const cancellationTransaction = await seaportLib.cancelOrders(orderComponents, account);
11885
+ return {
11886
+ type: ActionType.TRANSACTION,
11887
+ buildTransaction: prepareTransaction(cancellationTransaction),
11888
+ purpose: TransactionPurpose.CANCEL,
11889
+ };
11862
11890
  }
11863
11891
  mapImmutableOrderToSeaportOrderComponents(order) {
11864
11892
  const orderCounter = order.protocol_data.counter;
@@ -11960,6 +11988,16 @@ class ImmutableApiClient {
11960
11988
  ...listTradesParams,
11961
11989
  });
11962
11990
  }
11991
+ async cancelOrders(orderIds, accountAddress, signature) {
11992
+ return this.orderbookService.cancelOrders({
11993
+ chainName: this.chainName,
11994
+ requestBody: {
11995
+ account_address: accountAddress,
11996
+ orders: orderIds,
11997
+ signature,
11998
+ },
11999
+ });
12000
+ }
11963
12001
  async createListing({ orderHash, orderComponents, orderSignature, makerFees, }) {
11964
12002
  if (orderComponents.offer.length !== 1) {
11965
12003
  throw new Error('Only one item can be listed at a time');
@@ -12261,24 +12299,89 @@ class Orderbook {
12261
12299
  }
12262
12300
  }
12263
12301
  /**
12264
- * Get an unsigned cancel order transaction. Orders can only be cancelled by
12265
- * the account that created them.
12266
- * @param {string} listingId - The listingId to cancel.
12302
+ * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
12303
+ * `cancelOrdersOnChain`. For the orderbook to authenticate the cancellation, the creator
12304
+ * of the orders must sign an EIP712 message containing the orderIds
12305
+ * @param {string} orderIds - The orderIds to attempt to cancel.
12306
+ * @return {PrepareCancelOrdersResponse} The signable action to cancel the orders.
12307
+ */
12308
+ async prepareOrderCancellations(orderIds) {
12309
+ const network = await this.orderbookConfig.provider.getNetwork();
12310
+ const domain = {
12311
+ name: 'imtbl-order-book',
12312
+ chainId: network.chainId,
12313
+ verifyingContract: this.orderbookConfig.seaportContractAddress,
12314
+ };
12315
+ const types = {
12316
+ // eslint-disable-next-line @typescript-eslint/naming-convention
12317
+ CancelPayload: [
12318
+ { name: 'orders', type: 'Order[]' },
12319
+ ],
12320
+ // eslint-disable-next-line @typescript-eslint/naming-convention
12321
+ Order: [
12322
+ { name: 'id', type: 'string' },
12323
+ ],
12324
+ };
12325
+ const cancelMessage = {
12326
+ orders: orderIds.map((id) => ({ id })),
12327
+ };
12328
+ return {
12329
+ signableAction: {
12330
+ purpose: SignablePurpose.OFF_CHAIN_CANCELLATION,
12331
+ type: ActionType.SIGNABLE,
12332
+ message: {
12333
+ domain,
12334
+ types,
12335
+ value: cancelMessage,
12336
+ },
12337
+ },
12338
+ };
12339
+ }
12340
+ /**
12341
+ * Cancelling orders is a gasless alternative to on-chain cancellation exposed with
12342
+ * `cancelOrdersOnChain`. Orders cancelled this way cannot be fulfilled and will be removed
12343
+ * from the orderbook. If there is pending fulfillment data outstanding for the order, its
12344
+ * cancellation will be pending until the fulfillment window has passed.
12345
+ * `prepareOffchainOrderCancellations` can be used to get the signable action that is signed
12346
+ * to get the signature required for this call.
12347
+ * @param {string[]} orderIds - The orderIds to attempt to cancel.
12348
+ * @param {string} accountAddress - The address of the account cancelling the orders.
12349
+ * @param {string} accountAddress - The address of the account cancelling the orders.
12350
+ * @return {CancelOrdersResult} The result of the off-chain cancellation request
12351
+ */
12352
+ async cancelOrders(orderIds, accountAddress, signature) {
12353
+ return this.apiClient.cancelOrders(orderIds, accountAddress, signature);
12354
+ }
12355
+ /**
12356
+ * Get an unsigned order cancellation transaction. Orders can only be cancelled by
12357
+ * the account that created them. All of the orders must be from the same seaport contract.
12358
+ * If trying to cancel orders from multiple seaport contracts, group the orderIds by seaport
12359
+ * contract and call this method for each group.
12360
+ * @param {string[]} orderIds - The orderIds to cancel.
12267
12361
  * @param {string} accountAddress - The address of the account cancelling the order.
12268
- * @return {CancelOrderResponse} The unsigned cancel order transaction
12362
+ * @return {CancelOrdersOnChainResponse} The unsigned cancel order action
12269
12363
  */
12270
- async cancelOrder(listingId, accountAddress) {
12271
- const orderResult = await this.apiClient.getListing(listingId);
12272
- if (orderResult.result.status.name !== OrderStatusName.ACTIVE
12273
- && orderResult.result.status.name !== OrderStatusName.INACTIVE
12274
- && orderResult.result.status.name !== OrderStatusName.PENDING) {
12275
- throw new Error(`Cannot cancel order with status ${orderResult.result.status}`);
12364
+ async cancelOrdersOnChain(orderIds, accountAddress) {
12365
+ const orderResults = await Promise.all(orderIds.map((id) => this.apiClient.getListing(id)));
12366
+ // eslint-disable-next-line no-restricted-syntax
12367
+ for (const orderResult of orderResults) {
12368
+ if (orderResult.result.status.name !== OrderStatusName.ACTIVE
12369
+ && orderResult.result.status.name !== OrderStatusName.INACTIVE
12370
+ && orderResult.result.status.name !== OrderStatusName.PENDING) {
12371
+ throw new Error(`Cannot cancel order with status ${orderResult.result.status}`);
12372
+ }
12373
+ if (orderResult.result.account_address !== accountAddress.toLowerCase()) {
12374
+ throw new Error(`Only account ${orderResult.result.account_address} can cancel order ${orderResult.result.id}`);
12375
+ }
12276
12376
  }
12277
- if (orderResult.result.account_address !== accountAddress.toLowerCase()) {
12278
- throw new Error(`Only account ${orderResult.result.account_address} can cancel order ${listingId}`);
12377
+ const orders = orderResults.map((orderResult) => orderResult.result);
12378
+ const seaportAddresses = orders.map((o) => o.protocol_data.seaport_address);
12379
+ const distinctSeaportAddresses = new Set(...[seaportAddresses]);
12380
+ if (distinctSeaportAddresses.size !== 1) {
12381
+ throw new Error('Cannot cancel multiple orders from different seaport contracts. Please group your orderIds accordingly');
12279
12382
  }
12280
- const cancelOrderTransaction = await this.seaport.cancelOrder(orderResult.result, accountAddress);
12281
- return { unsignedCancelOrderTransaction: cancelOrderTransaction };
12383
+ const cancellationAction = await this.seaport.cancelOrders(orders, accountAddress);
12384
+ return { cancellationAction };
12282
12385
  }
12283
12386
  }
12284
12387
 
@@ -28077,6 +28180,7 @@ const newAmount = (amount, token) => ({
28077
28180
  });
28078
28181
  const isERC20Amount = (amount) => amount.token.type === 'erc20';
28079
28182
  const isNativeAmount = (amount) => amount.token.type === 'native';
28183
+ const isNative = (token) => token.type === 'native';
28080
28184
  const addERC20Amount = (a, b) => {
28081
28185
  // Make sure the ERC20s have the same address
28082
28186
  if (a.token.address !== b.token.address)
@@ -28730,92 +28834,193 @@ const IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS = [
28730
28834
 
28731
28835
  const zeroNativeCurrencyValue = '0x00';
28732
28836
  const multicallWithDeadlineFunctionSignature = 'multicall(uint256,bytes[])';
28733
- function buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28837
+ function buildSinglePoolSwap(tokenIn, tokenOut, recipient, trade, route, amountIn, amountOut, routerContract, paymentsContract) {
28838
+ const calldatas = [];
28839
+ if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28840
+ calldatas.push(routerContract.encodeFunctionData('exactInputSingle', [
28841
+ {
28842
+ tokenIn: route.tokenPath[0].address,
28843
+ tokenOut: route.tokenPath[1].address,
28844
+ fee: route.pools[0].fee,
28845
+ recipient,
28846
+ amountIn,
28847
+ amountOutMinimum: amountOut,
28848
+ sqrtPriceLimitX96: 0,
28849
+ },
28850
+ ]));
28851
+ }
28852
+ if (trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
28853
+ calldatas.push(routerContract.encodeFunctionData('exactOutputSingle', [
28854
+ {
28855
+ tokenIn: route.tokenPath[0].address,
28856
+ tokenOut: route.tokenPath[1].address,
28857
+ fee: route.pools[0].fee,
28858
+ recipient,
28859
+ amountInMaximum: amountIn,
28860
+ amountOut,
28861
+ sqrtPriceLimitX96: 0,
28862
+ },
28863
+ ]));
28864
+ }
28865
+ const shouldRefundNativeTokens = trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT && isNative(tokenIn);
28866
+ if (shouldRefundNativeTokens) {
28867
+ // Refund ETH if the input token is native and the swap is exact output
28868
+ calldatas.push(paymentsContract.encodeFunctionData('refundETH'));
28869
+ }
28870
+ const shouldUnwrapTokens = isNative(tokenOut);
28871
+ if (shouldUnwrapTokens) {
28872
+ // Unwrap the output token if the user specified a native token as the output
28873
+ calldatas.push(paymentsContract.encodeFunctionData('unwrapWETH9(uint256)', [amountOut]));
28874
+ }
28875
+ return calldatas;
28876
+ }
28877
+ function buildSinglePoolSwapWithFees(recipient, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28734
28878
  const secondaryFeeValues = secondaryFees.map((fee) => ({
28735
28879
  feeBasisPoints: fee.basisPoints,
28736
28880
  recipient: fee.recipient,
28737
28881
  }));
28738
- if (trade.tradeType === TradeType.EXACT_INPUT) {
28739
- return secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [
28882
+ const calldatas = [];
28883
+ if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28884
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [
28740
28885
  secondaryFeeValues,
28741
28886
  {
28742
28887
  tokenIn: route.tokenPath[0].address,
28743
28888
  tokenOut: route.tokenPath[1].address,
28744
28889
  fee: route.pools[0].fee,
28745
- recipient: fromAddress,
28890
+ recipient,
28746
28891
  amountIn,
28747
28892
  amountOutMinimum: amountOut,
28748
28893
  sqrtPriceLimitX96: 0,
28749
28894
  },
28750
- ]);
28895
+ ]));
28751
28896
  }
28752
- return secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [
28753
- secondaryFeeValues,
28754
- {
28755
- tokenIn: route.tokenPath[0].address,
28756
- tokenOut: route.tokenPath[1].address,
28757
- fee: route.pools[0].fee,
28758
- recipient: fromAddress,
28759
- amountInMaximum: amountIn,
28760
- amountOut,
28761
- sqrtPriceLimitX96: 0,
28762
- },
28763
- ]);
28897
+ if (trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
28898
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [
28899
+ secondaryFeeValues,
28900
+ {
28901
+ tokenIn: route.tokenPath[0].address,
28902
+ tokenOut: route.tokenPath[1].address,
28903
+ fee: route.pools[0].fee,
28904
+ recipient,
28905
+ amountInMaximum: amountIn,
28906
+ amountOut,
28907
+ sqrtPriceLimitX96: 0,
28908
+ },
28909
+ ]));
28910
+ }
28911
+ // TODO: Add refundETH method when support is added in SecondaryFee contract
28912
+ return calldatas;
28764
28913
  }
28765
- function buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28766
- const path = encodeRouteToPath(route, trade.tradeType === TradeType.EXACT_OUTPUT);
28914
+ function buildMultiPoolSwap(tokenIn, tokenOut, recipient, trade, route, amountIn, amountOut, routerContract, paymentsContract) {
28915
+ const path = encodeRouteToPath(route, trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT);
28916
+ const calldatas = [];
28917
+ if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28918
+ calldatas.push(routerContract.encodeFunctionData('exactInput', [
28919
+ {
28920
+ path,
28921
+ recipient,
28922
+ amountIn,
28923
+ amountOutMinimum: amountOut,
28924
+ },
28925
+ ]));
28926
+ }
28927
+ if (trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
28928
+ calldatas.push(routerContract.encodeFunctionData('exactOutput', [
28929
+ {
28930
+ path,
28931
+ recipient,
28932
+ amountInMaximum: amountIn,
28933
+ amountOut,
28934
+ },
28935
+ ]));
28936
+ }
28937
+ const shouldRefundNativeTokens = trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT && isNative(tokenIn);
28938
+ if (shouldRefundNativeTokens) {
28939
+ // Refund ETH if the input token is native and the swap is exact output
28940
+ calldatas.push(paymentsContract.encodeFunctionData('refundETH'));
28941
+ }
28942
+ const shouldUnwrapTokens = isNative(tokenOut);
28943
+ if (shouldUnwrapTokens) {
28944
+ // Unwrap the output token if the user specified a native token as the output
28945
+ calldatas.push(paymentsContract.encodeFunctionData('unwrapWETH9(uint256)', [amountOut]));
28946
+ }
28947
+ return calldatas;
28948
+ }
28949
+ function buildMultiPoolSwapWithFees(recipient, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
28950
+ const path = encodeRouteToPath(route, trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT);
28767
28951
  const secondaryFeeValues = secondaryFees.map((fee) => ({
28768
28952
  feeBasisPoints: fee.basisPoints,
28769
28953
  recipient: fee.recipient,
28770
28954
  }));
28771
- if (trade.tradeType === TradeType.EXACT_INPUT) {
28772
- return secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [
28955
+ const calldatas = [];
28956
+ if (trade.tradeType === Uniswap.TradeType.EXACT_INPUT) {
28957
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [
28773
28958
  secondaryFeeValues,
28774
28959
  {
28775
28960
  path,
28776
- recipient: fromAddress,
28961
+ recipient,
28777
28962
  amountIn,
28778
28963
  amountOutMinimum: amountOut,
28779
28964
  },
28780
- ]);
28965
+ ]));
28781
28966
  }
28782
- return secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [
28783
- secondaryFeeValues,
28784
- {
28785
- path,
28786
- recipient: fromAddress,
28787
- amountInMaximum: amountIn,
28788
- amountOut,
28789
- },
28790
- ]);
28967
+ if (trade.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
28968
+ calldatas.push(secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [
28969
+ secondaryFeeValues,
28970
+ {
28971
+ path,
28972
+ recipient,
28973
+ amountInMaximum: amountIn,
28974
+ amountOut,
28975
+ },
28976
+ ]));
28977
+ }
28978
+ // TODO: Add refundETH method when support is added in SecondaryFee contract
28979
+ return calldatas;
28791
28980
  }
28792
28981
  /**
28793
- * Builds swap parameters
28794
- * @param fromAddress the msg.sender of the transaction
28795
- * @param secondaryFeeAddress the secondary fee contract address
28796
- * @param trade details of the swap, including the route, input/output tokens and amounts
28797
- * @param options additional swap options
28798
- * @returns calldata for the swap
28982
+ * Builds and array of calldatas for the swap to be executed in the multicall method
28983
+ * @param tokenIn The token to be swapped
28984
+ * @param tokenOut The token to be received
28985
+ * @param fromAddress The address of the user
28986
+ * @param trade The trade to be executed
28987
+ * @param secondaryFees Secondary fees to be applied to the swap
28988
+ * @param secondaryFeeContract The SecondaryFee contract interface
28989
+ * @param routerContract The SwapRouter02 contract interface
28990
+ * @param paymentsContract The PaymentsExtended contract interface
28991
+ * @param maximumAmountIn The maximum amount of tokenIn to be swapped
28992
+ * @param minimumAmountOut The minimum amount of tokenOut to be received
28993
+ * @returns calldatas that make up the swap transaction
28799
28994
  */
28800
- function buildSwapParameters(fromAddress, trade, options, secondaryFees, secondaryFeeContract, maximumAmountIn, minimumAmountOut) {
28995
+ function buildSwapParameters(tokenIn, tokenOut, recipient, trade, secondaryFees, secondaryFeeContract, routerContract, paymentsContract, maximumAmountIn, minimumAmountOut) {
28801
28996
  // @dev we don't support multiple swaps in a single transaction
28802
28997
  // there will always be only one swap in the trade regardless of the trade type
28803
28998
  const { route } = trade.swaps[0];
28804
28999
  const isSinglePoolSwap = route.pools.length === 1;
29000
+ const hasSecondaryFees = secondaryFees.length > 0;
28805
29001
  if (isSinglePoolSwap) {
28806
- return buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29002
+ if (hasSecondaryFees) {
29003
+ return buildSinglePoolSwapWithFees(recipient, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29004
+ }
29005
+ return buildSinglePoolSwap(tokenIn, tokenOut, recipient, trade, route, maximumAmountIn, minimumAmountOut, routerContract, paymentsContract);
29006
+ }
29007
+ if (hasSecondaryFees) {
29008
+ return buildMultiPoolSwapWithFees(recipient, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
28807
29009
  }
28808
- return buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, maximumAmountIn, minimumAmountOut, secondaryFees, secondaryFeeContract);
29010
+ return buildMultiPoolSwap(tokenIn, tokenOut, recipient, trade, route, maximumAmountIn, minimumAmountOut, routerContract, paymentsContract);
28809
29011
  }
28810
- function createSwapCallParametersWithFees(trade, fromAddress, swapOptions, secondaryFees, maximumAmountIn, minimumAmountOut) {
29012
+ function createSwapCallParameters(tokenIn, tokenOut, trade, recipient, swapOptions, secondaryFees, maximumAmountIn, minimumAmountOut) {
28811
29013
  const secondaryFeeContract = SecondaryFee__factory.createInterface();
28812
- const swapWithFeesCalldata = buildSwapParameters(fromAddress, trade, swapOptions, secondaryFees, secondaryFeeContract, maximumAmountIn, minimumAmountOut);
29014
+ const routerContract = SwapRouter.INTERFACE;
29015
+ const paymentsContract = PaymentsExtended.INTERFACE;
29016
+ const calldatas = buildSwapParameters(tokenIn, tokenOut, recipient, trade, secondaryFees, secondaryFeeContract, routerContract, paymentsContract, maximumAmountIn, minimumAmountOut);
29017
+ // Create the multicall transaction using the calldatas generated above
28813
29018
  return secondaryFeeContract.encodeFunctionData(multicallWithDeadlineFunctionSignature, [
28814
29019
  swapOptions.deadlineOrPreviousBlockhash,
28815
- [swapWithFeesCalldata],
29020
+ calldatas,
28816
29021
  ]);
28817
29022
  }
28818
- function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees) {
29023
+ function createSwapParameters(tokenIn, tokenOut, adjustedQuote, fromAddress, slippage, deadline, secondaryFees) {
28819
29024
  // Create an unchecked trade to be used in generating swap parameters.
28820
29025
  const uncheckedTrade = Trade.createUncheckedTrade({
28821
29026
  route: adjustedQuote.route,
@@ -28830,29 +29035,26 @@ function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, se
28830
29035
  deadlineOrPreviousBlockhash: deadline,
28831
29036
  };
28832
29037
  // If the trade type is EXACT_INPUT, then the maximum amount-in is the user-specified amount (no slippage applied)
29038
+ // For EXACT_OUTPUT, the maximum amount-in is the amount-in with slippage applied
28833
29039
  // https://github.com/Uniswap/v3-sdk/blob/81d66099f07d1ec350767f497ef73222575fe032/src/entities/trade.ts#L456
28834
29040
  const maximumAmountIn = toHex$1(uncheckedTrade.maximumAmountIn(options.slippageTolerance).quotient);
28835
29041
  const minimumAmountOut = toHex$1(uncheckedTrade.minimumAmountOut(options.slippageTolerance).quotient);
28836
- if (secondaryFees.length === 0) {
28837
- // Generate swap parameters without secondary fee contract details
28838
- return { calldata: SwapRouter.swapCallParameters([uncheckedTrade], options).calldata, maximumAmountIn };
28839
- }
28840
29042
  return {
28841
- calldata: createSwapCallParametersWithFees(uncheckedTrade, fromAddress, options, secondaryFees, maximumAmountIn, minimumAmountOut),
29043
+ calldata: createSwapCallParameters(tokenIn, tokenOut, uncheckedTrade, fromAddress, options, secondaryFees, maximumAmountIn, minimumAmountOut),
28842
29044
  maximumAmountIn,
28843
29045
  };
28844
29046
  }
28845
29047
  const getTransactionValue = (tokenIn, maximumAmountIn) => tokenIn.type === 'native' ? maximumAmountIn : zeroNativeCurrencyValue;
28846
- function getSwap(tokenIn, adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees) {
28847
- // TODO: TP-1651: Include `refundETH` transaction as final step for native Exact Output swaps
28848
- const { calldata, maximumAmountIn } = createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees);
29048
+ function getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippage, deadline, routerContractAddress, secondaryFeesContractAddress, gasPrice, secondaryFees) {
29049
+ const swapRecipient = isNative(tokenOut) ? routerContractAddress : fromAddress;
29050
+ const { calldata, maximumAmountIn } = createSwapParameters(tokenIn, tokenOut, adjustedQuote, swapRecipient, slippage, deadline, secondaryFees);
28849
29051
  // TODO: Add additional gas fee estimates for secondary fees
28850
29052
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, adjustedQuote.gasEstimate) : null;
28851
29053
  const transactionValue = getTransactionValue(tokenIn, maximumAmountIn);
28852
29054
  return {
28853
29055
  transaction: {
28854
29056
  data: calldata,
28855
- to: secondaryFees.length > 0 ? secondaryFeesAddress : peripheryRouterAddress,
29057
+ to: secondaryFees.length > 0 ? secondaryFeesContractAddress : routerContractAddress,
28856
29058
  value: transactionValue,
28857
29059
  from: fromAddress,
28858
29060
  },
@@ -28860,7 +29062,7 @@ function getSwap(tokenIn, adjustedQuote, fromAddress, slippage, deadline, periph
28860
29062
  };
28861
29063
  }
28862
29064
  const adjustAmountIn = (ourQuote, amountSpecified, fees, nativeTokenService) => {
28863
- if (ourQuote.tradeType === TradeType.EXACT_OUTPUT) {
29065
+ if (ourQuote.tradeType === Uniswap.TradeType.EXACT_OUTPUT) {
28864
29066
  // when doing exact output, calculate the fees based on the amountIn
28865
29067
  const amountToAdd = canUnwrapToken(fees.token)
28866
29068
  ? nativeTokenService.unwrapAmount(ourQuote.amountIn)
@@ -29066,7 +29268,7 @@ class Exchange {
29066
29268
  fetchGasPrice(this.provider, this.nativeToken),
29067
29269
  ]);
29068
29270
  const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
29069
- const swap = getSwap(tokenIn, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
29271
+ const swap = getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
29070
29272
  const { quotedAmount, quotedAmountWithMaxSlippage } = prepareUserQuote(this.nativeTokenService, adjustedQuote, slippagePercent, otherToken);
29071
29273
  const preparedApproval = prepareApproval(tradeType, amountSpecified, quotedAmountWithMaxSlippage, {
29072
29274
  routerAddress: this.routerContractAddress,
@@ -32834,8 +33036,10 @@ const $9c3db1bb9c8b69d3$export$70b61ad426ddbe54 = async (config, provider, order
32834
33036
  try {
32835
33037
  const offererAddress = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the address from the provider", provider.getSigner().getAddress());
32836
33038
  const orderbook = $67fc622a2b913d5f$export$c60ce6c6a92bc2ff(config);
32837
- const cancelOrderResponse = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the cancel order from the orderbook", orderbook.cancelOrder(orderId, offererAddress));
32838
- unsignedCancelOrderTransaction = cancelOrderResponse.unsignedCancelOrderTransaction;
33039
+ const cancelOrderResponse = await (0, $458d407830d66110$export$5280dbcb91c8b391)(config, "Time to get the cancel order from the orderbook", orderbook.cancelOrdersOnChain([
33040
+ orderId
33041
+ ], offererAddress));
33042
+ unsignedCancelOrderTransaction = await cancelOrderResponse.cancellationAction.buildTransaction();
32839
33043
  } catch (err) {
32840
33044
  throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)("An error occurred while cancelling the order listing", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).CANCEL_ORDER_LISTING_ERROR, {
32841
33045
  orderId: orderId,
@@ -33333,7 +33537,7 @@ var $045213b18e9f1f94$export$75be0f6af9650f2c;
33333
33537
  })($045213b18e9f1f94$export$75be0f6af9650f2c || ($045213b18e9f1f94$export$75be0f6af9650f2c = {}));
33334
33538
 
33335
33539
 
33336
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.15";
33540
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.28.0";
33337
33541
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
33338
33542
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
33339
33543