@imtbl/sdk 0.27.7 → 0.27.9

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.
@@ -566,25 +566,41 @@ interface ModuleConfiguration<T> {
566
566
  }
567
567
 
568
568
  /**
569
- * Interface representing a token
569
+ * Interface representing an ERC20 token
570
570
  * @property {number} chainId - The chain ID
571
571
  * @property {string} address - The token address
572
572
  * @property {number} decimals - The token decimals
573
573
  * @property {string | undefined} symbol - The token symbol or undefined if it is not available
574
574
  * @property {string | undefined} name - The token name or undefined if it is not available
575
575
  */
576
- type TokenInfo$1 = {
576
+ type ERC20 = {
577
+ type: 'erc20';
577
578
  chainId: number;
578
579
  address: string;
579
580
  decimals: number;
580
581
  symbol?: string;
581
582
  name?: string;
582
583
  };
584
+ /**
585
+ * Interface representing a native token
586
+ * @property {number} chainId - The chain ID
587
+ * @property {number} decimals - The token decimals
588
+ * @property {string | undefined} symbol - The token symbol or undefined if it is not available
589
+ * @property {string | undefined} name - The token name or undefined if it is not available
590
+ */
591
+ type Native = {
592
+ type: 'native';
593
+ chainId: number;
594
+ decimals: number;
595
+ symbol?: string;
596
+ name?: string;
597
+ };
583
598
  interface ExchangeOverrides {
584
599
  rpcURL: string;
585
600
  exchangeContracts: ExchangeContracts;
586
- commonRoutingTokens: TokenInfo$1[];
587
- nativeToken: TokenInfo$1;
601
+ commonRoutingTokens: ERC20[];
602
+ nativeToken: Native;
603
+ wrappedNativeToken: ERC20;
588
604
  }
589
605
 
590
606
  /**
@@ -14715,25 +14715,65 @@ function isValidNonZeroAddress(address) {
14715
14715
  return false;
14716
14716
  }
14717
14717
  }
14718
- const tokenInfoToUniswapToken = (tokenInfo) => new Token(tokenInfo.chainId, tokenInfo.address, tokenInfo.decimals, tokenInfo.symbol, tokenInfo.name);
14718
+ const erc20ToUniswapToken = (token) =>
14719
+ // eslint-disable-next-line implicit-arrow-linebreak
14720
+ new Token(token.chainId, token.address, token.decimals, token.symbol, token.name);
14721
+ const uniswapTokenToERC20 = (token) => ({
14722
+ chainId: token.chainId,
14723
+ address: token.address,
14724
+ decimals: token.decimals,
14725
+ symbol: token.symbol,
14726
+ name: token.name,
14727
+ type: 'erc20',
14728
+ });
14719
14729
  const toCurrencyAmount = (amount) => {
14720
- const token = tokenInfoToUniswapToken(amount.token);
14730
+ const token = erc20ToUniswapToken(amount.token);
14721
14731
  return CurrencyAmount.fromRawAmount(token, amount.value.toString());
14722
14732
  };
14723
14733
  const newAmount = (amount, token) => ({
14724
14734
  value: amount,
14725
14735
  token,
14726
14736
  });
14727
- const addAmount = (a, b) => {
14737
+ const isERC20Amount = (amount) => amount.token.type === 'erc20';
14738
+ const isNativeAmount = (amount) => amount.token.type === 'native';
14739
+ const addERC20Amount = (a, b) => {
14740
+ // Make sure the ERC20s have the same address
14728
14741
  if (a.token.address !== b.token.address)
14729
- throw new Error('Token mismatch');
14742
+ throw new Error('Token mismatch: token addresses must be the same');
14730
14743
  return { value: a.value.add(b.value), token: a.token };
14731
14744
  };
14732
- const subtractAmount = (a, b) => {
14745
+ const addNativeAmount = (a, b) => ({
14746
+ value: a.value.add(b.value),
14747
+ token: a.token,
14748
+ });
14749
+ const addAmount = (a, b) => {
14750
+ if (isERC20Amount(a) && isERC20Amount(b)) {
14751
+ return addERC20Amount(a, b);
14752
+ }
14753
+ if (isNativeAmount(a) && isNativeAmount(b)) {
14754
+ return addNativeAmount(a, b);
14755
+ }
14756
+ throw new Error('Token mismatch: token types must be the same');
14757
+ };
14758
+ const subtractERC20Amount = (a, b) => {
14759
+ // Make sure the ERC20s have the same address
14733
14760
  if (a.token.address !== b.token.address)
14734
- throw new Error('Token mismatch');
14761
+ throw new Error('Token mismatch: token addresses must be the same');
14735
14762
  return { value: a.value.sub(b.value), token: a.token };
14736
14763
  };
14764
+ const subtractNativeAmount = (a, b) => ({
14765
+ value: a.value.sub(b.value),
14766
+ token: a.token,
14767
+ });
14768
+ const subtractAmount = (a, b) => {
14769
+ if (isERC20Amount(a) && isERC20Amount(b)) {
14770
+ return subtractERC20Amount(a, b);
14771
+ }
14772
+ if (isNativeAmount(a) && isNativeAmount(b)) {
14773
+ return subtractNativeAmount(a, b);
14774
+ }
14775
+ throw new Error('Token mismatch: token types must be the same');
14776
+ };
14737
14777
 
14738
14778
  const amountIndex = 0;
14739
14779
  const gasEstimateIndex = 3;
@@ -14771,10 +14811,12 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
14771
14811
  const quoteAmount = decodedQuoteResult[amountIndex];
14772
14812
  if (!(quoteAmount instanceof BigNumber$1))
14773
14813
  throw new Error('Expected BigNumber');
14814
+ const input = uniswapTokenToERC20(routes[i].input);
14815
+ const output = uniswapTokenToERC20(routes[i].output);
14774
14816
  decodedQuoteResults.push({
14775
14817
  route: routes[i],
14776
- amountIn: tradeType === TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, routes[i].input),
14777
- amountOut: tradeType === TradeType.EXACT_INPUT ? newAmount(quoteAmount, routes[i].output) : amountSpecified,
14818
+ amountIn: tradeType === TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, input),
14819
+ amountOut: tradeType === TradeType.EXACT_INPUT ? newAmount(quoteAmount, output) : amountSpecified,
14778
14820
  gasEstimate: ethers.BigNumber.from(decodedQuoteResult[gasEstimateIndex]),
14779
14821
  tradeType,
14780
14822
  });
@@ -14905,7 +14947,7 @@ const fetchValidPools = async (multicallContract, erc20Pair, commonRoutingERC20s
14905
14947
  if (zeroPrice || zeroLiquidity) {
14906
14948
  return;
14907
14949
  }
14908
- const validPool = new Pool(tokenInfoToUniswapToken(poolID.erc20Pair[0]), tokenInfoToUniswapToken(poolID.erc20Pair[1]), poolID.fee, poolSlot0.sqrtPriceX96.toString(), poolLiquidity.toString(), poolSlot0.tick);
14950
+ const validPool = new Pool(erc20ToUniswapToken(poolID.erc20Pair[0]), erc20ToUniswapToken(poolID.erc20Pair[1]), poolID.fee, poolSlot0.sqrtPriceX96.toString(), poolLiquidity.toString(), poolSlot0.tick);
14909
14951
  validPools.push(validPool);
14910
14952
  });
14911
14953
  return validPools;
@@ -14991,9 +15033,9 @@ maxHops, // the maximum number of pools that can be traversed
14991
15033
  currentRoute = [], // list of pools already traversed
14992
15034
  routes = [], // list of all routes found so far
14993
15035
  startTokenIn = tokenIn) => {
14994
- const currencyIn = tokenInfoToUniswapToken(tokenIn);
14995
- const currencyOut = tokenInfoToUniswapToken(tokenOut);
14996
- const startCurrencyIn = tokenInfoToUniswapToken(startTokenIn);
15036
+ const currencyIn = erc20ToUniswapToken(tokenIn);
15037
+ const currencyOut = erc20ToUniswapToken(tokenOut);
15038
+ const startCurrencyIn = erc20ToUniswapToken(startTokenIn);
14997
15039
  for (const pool of pools) {
14998
15040
  // if the pool doesn't have the tokenIn or if it has already been traversed,
14999
15041
  // skip to the next pool
@@ -15012,7 +15054,7 @@ startTokenIn = tokenIn) => {
15012
15054
  else if (maxHops > 1) {
15013
15055
  // otherwise, if we haven't exceeded the maximum number of pools that can be traversed,
15014
15056
  // recursively call this function with the output token as the new starting currency
15015
- generateAllAcyclicPaths(outputToken, tokenOut, pools, maxHops - 1, [...currentRoute, pool], routes, startTokenIn);
15057
+ generateAllAcyclicPaths(uniswapTokenToERC20(outputToken), tokenOut, pools, maxHops - 1, [...currentRoute, pool], routes, startTokenIn);
15016
15058
  }
15017
15059
  }
15018
15060
  return routes;
@@ -15105,11 +15147,11 @@ const getUnsignedERC20ApproveTransaction = (ownerAddress, tokenAmount, spenderAd
15105
15147
  from: ownerAddress,
15106
15148
  };
15107
15149
  };
15108
- const prepareApproval = (tradeType, amountSpecified, amountWithSlippage, routingContracts, secondaryFees) => {
15150
+ const prepareApproval = (tradeType, amountSpecified, amountWithSlippage, contracts, secondaryFees) => {
15109
15151
  const amountOfTokenIn = tradeType === TradeType.EXACT_INPUT ? amountSpecified : amountWithSlippage;
15110
15152
  const spender = secondaryFees.length === 0
15111
- ? routingContracts.peripheryRouterAddress
15112
- : routingContracts.secondaryFeeAddress;
15153
+ ? contracts.routerAddress
15154
+ : contracts.secondaryFeeAddress;
15113
15155
  return { spender, amount: amountOfTokenIn };
15114
15156
  };
15115
15157
  /**
@@ -15142,7 +15184,7 @@ async function getApproveGasEstimate(provider, ownerAddress, spenderAddress, tok
15142
15184
  from: ownerAddress,
15143
15185
  });
15144
15186
  }
15145
- const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice) => {
15187
+ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice, nativeTokenService) => {
15146
15188
  const approveTransaction = await getApproveTransaction(provider, ownerAddress, preparedApproval.amount, preparedApproval.spender);
15147
15189
  if (!approveTransaction) {
15148
15190
  return null;
@@ -15151,7 +15193,8 @@ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice) =
15151
15193
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, gasEstimate) : null;
15152
15194
  return {
15153
15195
  transaction: approveTransaction,
15154
- gasFeeEstimate,
15196
+ // TODO: TP-1649: Remove the wrapping here
15197
+ gasFeeEstimate: gasFeeEstimate ? nativeTokenService.maybeWrapAmount(gasFeeEstimate) : null,
15155
15198
  };
15156
15199
  };
15157
15200
 
@@ -15187,7 +15230,7 @@ function applySlippage(tradeType, amount, slippage) {
15187
15230
  const amountWithSlippage = maybeInverted.multiply(amount.toString()).quotient;
15188
15231
  return ethers.BigNumber.from(amountWithSlippage.toString());
15189
15232
  }
15190
- function prepareUserQuote(otherToken, tradeInfo, slippage, fees) {
15233
+ function prepareUserQuote(otherToken, tradeInfo, slippage, fees, nativeTokenService) {
15191
15234
  const quote = getQuoteAmountFromTradeType(tradeInfo);
15192
15235
  const amountWithSlippage = applySlippage(tradeInfo.tradeType, quote.value, slippage);
15193
15236
  return {
@@ -15197,16 +15240,20 @@ function prepareUserQuote(otherToken, tradeInfo, slippage, fees) {
15197
15240
  value: amountWithSlippage,
15198
15241
  },
15199
15242
  slippage,
15200
- fees: fees.withAmounts(),
15243
+ fees: fees.withAmounts().map((fee) => ({
15244
+ ...fee,
15245
+ amount: nativeTokenService.maybeWrapAmount(fee.amount),
15246
+ })),
15201
15247
  };
15202
15248
  }
15203
- function getOurQuoteReqAmount(amount, fees, tradeType) {
15249
+ function getOurQuoteReqAmount(amountSpecified, // the amount specified by the user, either exactIn or exactOut
15250
+ fees, tradeType, nativeTokenService) {
15204
15251
  if (tradeType === TradeType.EXACT_OUTPUT) {
15205
15252
  // For an exact output swap, we do not need to subtract fees from the given amount
15206
- return amount;
15253
+ return nativeTokenService.maybeWrapAmount(amountSpecified);
15207
15254
  }
15208
- fees.addAmount(amount);
15209
- return fees.amountLessFees();
15255
+ fees.addAmount(amountSpecified);
15256
+ return nativeTokenService.maybeWrapAmount(fees.amountLessFees());
15210
15257
  }
15211
15258
 
15212
15259
  // 0.1% default slippage
@@ -15222,7 +15269,7 @@ const MIN_MAX_HOPS = 1;
15222
15269
  // precision used to calculate percentage from basis points
15223
15270
  const BASIS_POINT_PRECISION = 10000;
15224
15271
  // 10% maximum secondary fee
15225
- const MAX_SECONDARY_FEE_BASIS_POINTS = 10000;
15272
+ const MAX_SECONDARY_FEE_BASIS_POINTS = 1000;
15226
15273
 
15227
15274
  class Fees {
15228
15275
  secondaryFees;
@@ -15231,6 +15278,9 @@ class Fees {
15231
15278
  this.secondaryFees = secondaryFees;
15232
15279
  this.amount = newAmount(BigNumber$1.from(0), token);
15233
15280
  }
15281
+ get token() {
15282
+ return this.amount.token;
15283
+ }
15234
15284
  addAmount(amount) {
15235
15285
  this.amount = addAmount(this.amount, amount);
15236
15286
  }
@@ -15263,18 +15313,65 @@ class Fees {
15263
15313
  }
15264
15314
  }
15265
15315
 
15316
+ class NativeTokenService {
15317
+ nativeToken;
15318
+ wrappedToken;
15319
+ constructor(nativeToken, wrappedToken) {
15320
+ this.nativeToken = nativeToken;
15321
+ this.wrappedToken = wrappedToken;
15322
+ }
15323
+ wrapAmount(amount) {
15324
+ return newAmount(amount.value, this.wrappedToken);
15325
+ }
15326
+ unwrapAmount(amount) {
15327
+ if (amount.token !== this.wrappedToken) {
15328
+ throw new Error(`token ${amount.token.address} is not wrapped`);
15329
+ }
15330
+ return newAmount(amount.value, this.nativeToken);
15331
+ }
15332
+ maybeWrapToken(token) {
15333
+ if (this.isNativeToken(token)) {
15334
+ return this.wrappedToken;
15335
+ }
15336
+ return token;
15337
+ }
15338
+ maybeWrapAmount(amount) {
15339
+ return newAmount(amount.value, this.maybeWrapToken(amount.token));
15340
+ }
15341
+ isNativeToken(token) {
15342
+ return token === this.nativeToken;
15343
+ }
15344
+ }
15345
+
15266
15346
  const IMMUTABLE_TESTNET_RPC_URL = 'https://rpc.testnet.immutable.com';
15267
15347
  const IMMUTABLE_TESTNET_CHAIN_ID = 13472;
15268
15348
 
15349
+ const NATIVE_IMX_IMMUTABLE_TESTNET = {
15350
+ chainId: IMMUTABLE_TESTNET_CHAIN_ID,
15351
+ decimals: 18,
15352
+ symbol: 'tIMX',
15353
+ name: 'Immutable Testnet Token',
15354
+ type: 'native',
15355
+ };
15269
15356
  const TIMX_IMMUTABLE_TESTNET = {
15270
15357
  chainId: IMMUTABLE_TESTNET_CHAIN_ID,
15271
15358
  address: '0x0000000000000000000000000000000000001010',
15272
15359
  decimals: 18,
15273
15360
  symbol: 'tIMX',
15274
15361
  name: 'Immutable Testnet Token',
15362
+ type: 'erc20',
15363
+ };
15364
+ const WIMX_IMMUTABLE_TESTNET = {
15365
+ chainId: IMMUTABLE_TESTNET_CHAIN_ID,
15366
+ address: '0xAf7cf5D4Af0BFAa85d384d42b8D410762Ccbce69',
15367
+ decimals: 18,
15368
+ symbol: 'WIMX',
15369
+ name: 'Wrapped Immutable Testnet Token',
15370
+ type: 'erc20',
15275
15371
  };
15276
15372
  const IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS = [
15277
15373
  TIMX_IMMUTABLE_TESTNET,
15374
+ WIMX_IMMUTABLE_TESTNET,
15278
15375
  ];
15279
15376
 
15280
15377
  const zeroNativeCurrencyValue = '0x00';
@@ -15371,7 +15468,7 @@ function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, se
15371
15468
  }
15372
15469
  return createSwapCallParametersWithFees(uncheckedTrade, fromAddress, options, secondaryFees);
15373
15470
  }
15374
- function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees) {
15471
+ function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees, nativeTokenService) {
15375
15472
  const calldata = createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees);
15376
15473
  // TODO: Add additional gas fee estimates for secondary fees
15377
15474
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, adjustedQuote.gasEstimate) : null;
@@ -15382,24 +15479,37 @@ function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouter
15382
15479
  value: zeroNativeCurrencyValue,
15383
15480
  from: fromAddress,
15384
15481
  },
15385
- gasFeeEstimate,
15482
+ // TODO: TP-1649: Remove the wrapping here
15483
+ gasFeeEstimate: gasFeeEstimate ? nativeTokenService.maybeWrapAmount(gasFeeEstimate) : null,
15386
15484
  };
15387
15485
  }
15388
- function prepareSwap(ourQuote, amountSpecified, fees) {
15486
+ const adjustAmountIn = (ourQuote, amountSpecified, fees, nativeTokenService) => {
15389
15487
  if (ourQuote.tradeType === TradeType.EXACT_OUTPUT) {
15390
- fees.addAmount(ourQuote.amountIn);
15391
- return {
15392
- gasEstimate: ourQuote.gasEstimate,
15393
- route: ourQuote.route,
15394
- amountIn: fees.amountWithFeesApplied(),
15395
- amountOut: amountSpecified,
15396
- tradeType: ourQuote.tradeType,
15397
- };
15398
- }
15488
+ // when doing exact output, calculate the fees based on the amountIn
15489
+ const amountToAdd = nativeTokenService.isNativeToken(fees.token)
15490
+ ? nativeTokenService.unwrapAmount(ourQuote.amountIn)
15491
+ : ourQuote.amountIn;
15492
+ fees.addAmount(amountToAdd);
15493
+ return nativeTokenService.maybeWrapAmount(fees.amountWithFeesApplied());
15494
+ }
15495
+ return nativeTokenService.maybeWrapAmount(amountSpecified);
15496
+ };
15497
+ /**
15498
+ * adjustQuoteWithFees adjusts the amountIn of the quote to account for fees
15499
+ * EXACT_OUTPUT swaps will have the fees added to the amountIn if there are fees specified
15500
+ * EXACT_INPUT swaps will have amountIn set to the user-specified amount
15501
+ * @param ourQuote The quote from calling the Quoter contract
15502
+ * @param amountSpecified The user-specified amount for the swap (EXACT...)
15503
+ * @param fees The fees applied to the swap
15504
+ * @param tokenWrapper Helper class for the native token and associated ERC20
15505
+ * @returns {QuoteResult} The adjusted quote
15506
+ */
15507
+ function adjustQuoteWithFees(ourQuote, amountSpecified, fees, nativeTokenService) {
15508
+ const adjustedAmountIn = adjustAmountIn(ourQuote, amountSpecified, fees, nativeTokenService);
15399
15509
  return {
15400
15510
  gasEstimate: ourQuote.gasEstimate,
15401
15511
  route: ourQuote.route,
15402
- amountIn: amountSpecified,
15512
+ amountIn: adjustedAmountIn,
15403
15513
  amountOut: ourQuote.amountOut,
15404
15514
  tradeType: ourQuote.tradeType,
15405
15515
  };
@@ -15420,7 +15530,8 @@ const SUPPORTED_SANDBOX_CHAINS = {
15420
15530
  rpcUrl: IMMUTABLE_TESTNET_RPC_URL,
15421
15531
  contracts: CONTRACTS_FOR_CHAIN_ID[IMMUTABLE_TESTNET_CHAIN_ID],
15422
15532
  commonRoutingTokens: IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS,
15423
- nativeToken: TIMX_IMMUTABLE_TESTNET,
15533
+ nativeToken: NATIVE_IMX_IMMUTABLE_TESTNET,
15534
+ wrappedNativeToken: TIMX_IMMUTABLE_TESTNET, // TODO: TP-1649: Change to WIMX when ready.
15424
15535
  },
15425
15536
  };
15426
15537
  const SUPPORTED_PRODUCTION_CHAINS = {};
@@ -15478,6 +15589,7 @@ class ExchangeConfiguration {
15478
15589
  contracts: overrides.exchangeContracts,
15479
15590
  commonRoutingTokens: overrides.commonRoutingTokens,
15480
15591
  nativeToken: overrides.nativeToken,
15592
+ wrappedNativeToken: overrides.wrappedNativeToken,
15481
15593
  };
15482
15594
  this.secondaryFees = secondaryFees || [];
15483
15595
  return;
@@ -15495,19 +15607,25 @@ class Exchange {
15495
15607
  router;
15496
15608
  chainId;
15497
15609
  nativeToken;
15610
+ wrappedNativeToken;
15498
15611
  secondaryFees;
15612
+ nativeTokenService;
15613
+ secondaryFeeContractAddress;
15614
+ routerContractAddress;
15499
15615
  constructor(configuration) {
15500
15616
  const config = new ExchangeConfiguration(configuration);
15501
15617
  this.chainId = config.chain.chainId;
15502
15618
  this.nativeToken = config.chain.nativeToken;
15619
+ this.wrappedNativeToken = config.chain.wrappedNativeToken;
15620
+ this.nativeTokenService = new NativeTokenService(this.nativeToken, this.wrappedNativeToken);
15503
15621
  this.secondaryFees = config.secondaryFees;
15622
+ this.routerContractAddress = config.chain.contracts.peripheryRouter;
15623
+ this.secondaryFeeContractAddress = config.chain.contracts.secondaryFee;
15504
15624
  this.provider = new ethers.providers.JsonRpcProvider(config.chain.rpcUrl);
15505
15625
  this.router = new Router(this.provider, config.chain.commonRoutingTokens, {
15506
15626
  multicallAddress: config.chain.contracts.multicall,
15507
15627
  factoryAddress: config.chain.contracts.coreFactory,
15508
15628
  quoterAddress: config.chain.contracts.quoterV2,
15509
- peripheryRouterAddress: config.chain.contracts.peripheryRouter,
15510
- secondaryFeeAddress: config.chain.contracts.secondaryFee,
15511
15629
  });
15512
15630
  }
15513
15631
  static validate(tokenInAddress, tokenOutAddress, maxHops, slippagePercent, fromAddress) {
@@ -15524,7 +15642,7 @@ class Exchange {
15524
15642
  if (this.secondaryFees.length === 0) {
15525
15643
  return [];
15526
15644
  }
15527
- const secondaryFeeContract = SecondaryFee__factory.connect(this.router.routingContracts.secondaryFeeAddress, this.provider);
15645
+ const secondaryFeeContract = SecondaryFee__factory.connect(this.secondaryFeeContractAddress, this.provider);
15528
15646
  if (await secondaryFeeContract.paused()) {
15529
15647
  // Do not use secondary fees if the contract is paused
15530
15648
  return [];
@@ -15540,32 +15658,36 @@ class Exchange {
15540
15658
  this.getSecondaryFees(),
15541
15659
  ]);
15542
15660
  const tokenIn = {
15661
+ type: 'erc20',
15543
15662
  address: tokenInAddress,
15544
15663
  chainId: this.chainId,
15545
15664
  decimals: tokenInDecimals,
15546
15665
  };
15547
15666
  const tokenOut = {
15667
+ type: 'erc20',
15548
15668
  address: tokenOutAddress,
15549
15669
  chainId: this.chainId,
15550
15670
  decimals: tokenOutDecimals,
15551
15671
  };
15552
15672
  // determine which amount was specified for the swap from the TradeType
15553
- const [tokenSpecified, otherToken] = tradeType === TradeType.EXACT_INPUT
15554
- ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
15673
+ const [tokenSpecified, otherToken] = tradeType === TradeType.EXACT_INPUT ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
15555
15674
  const amountSpecified = newAmount(amount, tokenSpecified);
15556
15675
  const fees = new Fees(secondaryFees, tokenIn);
15557
- const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType);
15676
+ const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType, this.nativeTokenService);
15558
15677
  // get quote and gas details
15559
15678
  const [ourQuote, gasPrice] = await Promise.all([
15560
15679
  this.router.findOptimalRoute(ourQuoteReqAmount, otherToken, tradeType, maxHops),
15561
15680
  fetchGasPrice(this.provider, this.nativeToken),
15562
15681
  ]);
15563
- const adjustedQuote = prepareSwap(ourQuote, amountSpecified, fees);
15564
- const swap = getSwap(adjustedQuote, fromAddress, slippagePercent, deadline, this.router.routingContracts.peripheryRouterAddress, this.router.routingContracts.secondaryFeeAddress, gasPrice, secondaryFees);
15565
- const userQuote = prepareUserQuote(otherToken, adjustedQuote, slippagePercent, fees);
15566
- const preparedApproval = prepareApproval(tradeType, amountSpecified, userQuote.amountWithMaxSlippage, this.router.routingContracts, secondaryFees);
15682
+ const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
15683
+ const swap = getSwap(adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees, this.nativeTokenService);
15684
+ const userQuote = prepareUserQuote(otherToken, adjustedQuote, slippagePercent, fees, this.nativeTokenService);
15685
+ const preparedApproval = prepareApproval(tradeType, amountSpecified, userQuote.amountWithMaxSlippage, {
15686
+ routerAddress: this.routerContractAddress,
15687
+ secondaryFeeAddress: this.secondaryFeeContractAddress,
15688
+ }, secondaryFees);
15567
15689
  // preparedApproval always uses the tokenIn address because we are always selling the tokenIn
15568
- const approval = await getApproval(this.provider, fromAddress, preparedApproval, gasPrice);
15690
+ const approval = await getApproval(this.provider, fromAddress, preparedApproval, gasPrice, this.nativeTokenService);
15569
15691
  return {
15570
15692
  approval,
15571
15693
  swap,
@@ -16604,9 +16726,6 @@ class Seaport {
16604
16726
  };
16605
16727
  }
16606
16728
  async fulfillBulkOrders(fulfillingOrders, account) {
16607
- // TODO: this function right now does not handle errors from the seaport.js
16608
- // we should figure out why orders are rejected and return a submission
16609
- // transaction on best efforts basis
16610
16729
  const fulfillOrderDetails = fulfillingOrders.map((o) => {
16611
16730
  const { orderComponents, tips } = this.mapImmutableOrderToSeaportOrderComponents(o.order);
16612
16731
  return {
@@ -17025,14 +17144,34 @@ class Orderbook {
17025
17144
  recipient: fee.recipient,
17026
17145
  })),
17027
17146
  })));
17028
- return {
17029
- ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
17030
- fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
17031
- unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
17032
- orderId: o.order_id,
17033
- reason: o.reason,
17034
- })),
17035
- };
17147
+ try {
17148
+ return {
17149
+ ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
17150
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
17151
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
17152
+ orderId: o.order_id,
17153
+ reason: o.reason,
17154
+ })),
17155
+ sufficientBalance: true,
17156
+ };
17157
+ }
17158
+ catch (e) {
17159
+ // if insufficient balance error, we return FulfillBulkOrdersInsufficientBalanceResponse
17160
+ if (String(e).includes('The fulfiller does not have the balances needed to fulfill.')) {
17161
+ return {
17162
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
17163
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
17164
+ orderId: o.order_id,
17165
+ reason: o.reason,
17166
+ })),
17167
+ sufficientBalance: false,
17168
+ };
17169
+ }
17170
+ // if some other error is thrown,
17171
+ // there likely is a race condition of the original order validity
17172
+ // we throw the error back out
17173
+ throw e;
17174
+ }
17036
17175
  }
17037
17176
  /**
17038
17177
  * Get an unsigned cancel order transaction. Orders can only be cancelled by
@@ -20409,7 +20548,7 @@ class APIError extends Error {
20409
20548
 
20410
20549
  /* eslint-disable implicit-arrow-linebreak */
20411
20550
  const defaultHeaders = {
20412
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.7',
20551
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.9',
20413
20552
  };
20414
20553
  /**
20415
20554
  * createAPIConfiguration to create a custom Configuration
@@ -22935,8 +23074,6 @@ const $5e9bcae98dc8ff19$export$1165ca270f090a66 = (isDevelopment, isProduction)=
22935
23074
  return ($d85ad1457a3f1a83$export$89133ca13c5ee30)[(Environment$1).SANDBOX];
22936
23075
  };
22937
23076
  const checkDexAvailability = async ()=>{
22938
- // TEMP FIX: Returns true for sandbox environment
22939
- if (!isDevelopment && !isProduction) return true;
22940
23077
  let response;
22941
23078
  try {
22942
23079
  response = await (0, globalAxios).post(`${postEndpoint()}/v1/availability/checkout/swap`);
@@ -23101,7 +23238,7 @@ const $049bba630af05555$export$6946a1f17c2bbf26 = async (config, chainId, wallet
23101
23238
  const swappableToken = fromToken[index];
23102
23239
  dexQuotes.set(swappableToken, {
23103
23240
  quote: response.value.quote,
23104
- approval: response.value.approval?.gasFeeEstimate,
23241
+ approval: response.value.approval?.gasFeeEstimate ?? null,
23105
23242
  swap: response.value.swap.gasFeeEstimate
23106
23243
  });
23107
23244
  });
@@ -25,7 +25,7 @@ var $045213b18e9f1f94$export$75be0f6af9650f2c;
25
25
  })($045213b18e9f1f94$export$75be0f6af9650f2c || ($045213b18e9f1f94$export$75be0f6af9650f2c = {}));
26
26
 
27
27
 
28
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.7";
28
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.9";
29
29
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
30
30
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
31
31
 
@@ -16,7 +16,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
16
16
  chainID,
17
17
  coreContractAddress,
18
18
  registrationContractAddress,
19
- sdkVersion: 'ts-immutable-sdk-0.27.7',
19
+ sdkVersion: 'ts-immutable-sdk-0.27.9',
20
20
  });
21
21
  /**
22
22
  * Sets `sdkVersion` at the time of build