@imtbl/sdk 0.27.9 → 0.27.11

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.
@@ -2,7 +2,8 @@ import { ethers, ContractFactory, utils, Contract as Contract$1, BigNumber as Bi
2
2
  import globalAxios, { HttpStatusCode } from 'axios';
3
3
  import { Web3Provider, JsonRpcProvider } from '@ethersproject/providers';
4
4
  import $7v2Z6$metamaskdetectprovider from '@metamask/detect-provider';
5
- import { TradeType, Token, CurrencyAmount, Percent } from '@uniswap/sdk-core';
5
+ import * as Uniswap from '@uniswap/sdk-core';
6
+ import { TradeType, Percent } from '@uniswap/sdk-core';
6
7
  import assert from 'assert';
7
8
  import { FeeAmount, Route, SwapQuoter, Pool, Trade, toHex as toHex$1, encodeRouteToPath } from '@uniswap/v3-sdk';
8
9
  import { keccak256 as keccak256$1 } from '@ethersproject/solidity';
@@ -14681,13 +14682,14 @@ const quoteReturnMapping = {
14681
14682
  * @param poolB the other pool
14682
14683
  */
14683
14684
  function poolEquals(poolA, poolB) {
14684
- return (poolA === poolB
14685
- || (poolA.token0.equals(poolB.token0)
14686
- && poolA.token1.equals(poolB.token1)
14687
- && poolA.fee === poolB.fee));
14685
+ return (poolA === poolB ||
14686
+ (poolA.token0.equals(poolB.token0) && poolA.token1.equals(poolB.token1) && poolA.fee === poolB.fee));
14688
14687
  }
14689
- async function getERC20Decimals(tokenAddress, provider) {
14690
- const decimalsFunctionSig = ethers.utils.id('decimals()').substring(0, 10);
14688
+ const decimalsFunctionSig = ethers.utils.id('decimals()').substring(0, 10);
14689
+ async function getTokenDecimals(tokenAddress, provider, nativeToken) {
14690
+ if (tokenAddress === 'native') {
14691
+ return nativeToken.decimals;
14692
+ }
14691
14693
  try {
14692
14694
  const decimalsResult = await provider.call({
14693
14695
  to: tokenAddress,
@@ -14715,9 +14717,10 @@ function isValidNonZeroAddress(address) {
14715
14717
  return false;
14716
14718
  }
14717
14719
  }
14720
+ const isValidTokenLiteral = (address) => address === 'native' ? true : isValidNonZeroAddress(address);
14718
14721
  const erc20ToUniswapToken = (token) =>
14719
14722
  // eslint-disable-next-line implicit-arrow-linebreak
14720
- new Token(token.chainId, token.address, token.decimals, token.symbol, token.name);
14723
+ new Uniswap.Token(token.chainId, token.address, token.decimals, token.symbol, token.name);
14721
14724
  const uniswapTokenToERC20 = (token) => ({
14722
14725
  chainId: token.chainId,
14723
14726
  address: token.address,
@@ -14728,7 +14731,7 @@ const uniswapTokenToERC20 = (token) => ({
14728
14731
  });
14729
14732
  const toCurrencyAmount = (amount) => {
14730
14733
  const token = erc20ToUniswapToken(amount.token);
14731
- return CurrencyAmount.fromRawAmount(token, amount.value.toString());
14734
+ return Uniswap.CurrencyAmount.fromRawAmount(token, amount.value.toString());
14732
14735
  };
14733
14736
  const newAmount = (amount, token) => ({
14734
14737
  value: amount,
@@ -14774,6 +14777,28 @@ const subtractAmount = (a, b) => {
14774
14777
  }
14775
14778
  throw new Error('Token mismatch: token types must be the same');
14776
14779
  };
14780
+ /**
14781
+ * Converts our internal token type which could be ERC20 or Native
14782
+ * into a format consumable by Checkout. They require an address to be
14783
+ * present. We populate the address with empty string if it's Native.
14784
+ * If it's ERC20, we don't need to change it.
14785
+ */
14786
+ const toPublicTokenType = (token) => {
14787
+ if (token.type === 'native') {
14788
+ return {
14789
+ address: '',
14790
+ chainId: token.chainId,
14791
+ decimals: token.decimals,
14792
+ symbol: token.symbol,
14793
+ name: token.name,
14794
+ };
14795
+ }
14796
+ return token;
14797
+ };
14798
+ const toPublicAmount = (amount) => ({
14799
+ token: toPublicTokenType(amount.token),
14800
+ value: amount.value,
14801
+ });
14777
14802
 
14778
14803
  const amountIndex = 0;
14779
14804
  const gasEstimateIndex = 3;
@@ -15147,12 +15172,13 @@ const getUnsignedERC20ApproveTransaction = (ownerAddress, tokenAmount, spenderAd
15147
15172
  from: ownerAddress,
15148
15173
  };
15149
15174
  };
15150
- const prepareApproval = (tradeType, amountSpecified, amountWithSlippage, contracts, secondaryFees) => {
15151
- const amountOfTokenIn = tradeType === TradeType.EXACT_INPUT ? amountSpecified : amountWithSlippage;
15152
- const spender = secondaryFees.length === 0
15153
- ? contracts.routerAddress
15154
- : contracts.secondaryFeeAddress;
15155
- return { spender, amount: amountOfTokenIn };
15175
+ const prepareApproval = (tradeType, userSpecifiedAmount, quotedAmountWithSlippage, contracts, secondaryFees) => {
15176
+ const amountInToApprove = tradeType === TradeType.EXACT_INPUT ? userSpecifiedAmount : quotedAmountWithSlippage;
15177
+ if (!isERC20Amount(amountInToApprove)) {
15178
+ return null;
15179
+ }
15180
+ const spender = secondaryFees.length === 0 ? contracts.routerAddress : contracts.secondaryFeeAddress;
15181
+ return { spender, amount: amountInToApprove };
15156
15182
  };
15157
15183
  /**
15158
15184
  * Get an unsigned approval transaction if needed
@@ -15184,7 +15210,7 @@ async function getApproveGasEstimate(provider, ownerAddress, spenderAddress, tok
15184
15210
  from: ownerAddress,
15185
15211
  });
15186
15212
  }
15187
- const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice, nativeTokenService) => {
15213
+ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice) => {
15188
15214
  const approveTransaction = await getApproveTransaction(provider, ownerAddress, preparedApproval.amount, preparedApproval.spender);
15189
15215
  if (!approveTransaction) {
15190
15216
  return null;
@@ -15193,11 +15219,42 @@ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice, n
15193
15219
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, gasEstimate) : null;
15194
15220
  return {
15195
15221
  transaction: approveTransaction,
15196
- // TODO: TP-1649: Remove the wrapping here
15197
- gasFeeEstimate: gasFeeEstimate ? nativeTokenService.maybeWrapAmount(gasFeeEstimate) : null,
15222
+ gasFeeEstimate: gasFeeEstimate ? toPublicAmount(gasFeeEstimate) : null,
15198
15223
  };
15199
15224
  };
15200
15225
 
15226
+ const canUnwrapToken = (token) => token.type === 'native';
15227
+ class NativeTokenService {
15228
+ nativeToken;
15229
+ wrappedToken;
15230
+ constructor(nativeToken, wrappedToken) {
15231
+ this.nativeToken = nativeToken;
15232
+ this.wrappedToken = wrappedToken;
15233
+ }
15234
+ wrapAmount(amount) {
15235
+ if (!canUnwrapToken(amount.token)) {
15236
+ throw new Error(`cannot wrap non-native token: ${amount.token.address}`);
15237
+ }
15238
+ return newAmount(amount.value, this.wrappedToken);
15239
+ }
15240
+ unwrapAmount(amount) {
15241
+ const isWrappedToken = amount.token.address.toLowerCase() !== this.wrappedToken.address.toLowerCase();
15242
+ if (isWrappedToken) {
15243
+ throw new Error(`cannot unwrap non-wrapped token ${amount.token.address}`);
15244
+ }
15245
+ return newAmount(amount.value, this.nativeToken);
15246
+ }
15247
+ maybeWrapToken(token) {
15248
+ if (canUnwrapToken(token)) {
15249
+ return this.wrappedToken;
15250
+ }
15251
+ return token;
15252
+ }
15253
+ maybeWrapAmount(amount) {
15254
+ return newAmount(amount.value, this.maybeWrapToken(amount.token));
15255
+ }
15256
+ }
15257
+
15201
15258
  // slippageToPercent takes the slippage as a percentage (e.g. 0.1) and
15202
15259
  // converts it to the Uniswap equivalent type
15203
15260
  const slippageToFraction = (slippage) => {
@@ -15217,11 +15274,11 @@ const slippageToFraction = (slippage) => {
15217
15274
  return new Percent(numerator, denominator);
15218
15275
  };
15219
15276
 
15220
- function getQuoteAmountFromTradeType(tradeInfo) {
15221
- if (tradeInfo.tradeType === TradeType.EXACT_INPUT) {
15222
- return tradeInfo.amountOut;
15277
+ function getQuoteAmountFromTradeType(routerQuote) {
15278
+ if (routerQuote.tradeType === TradeType.EXACT_INPUT) {
15279
+ return routerQuote.amountOut;
15223
15280
  }
15224
- return tradeInfo.amountIn;
15281
+ return routerQuote.amountIn;
15225
15282
  }
15226
15283
  function applySlippage(tradeType, amount, slippage) {
15227
15284
  const slippageTolerance = slippageToFraction(slippage);
@@ -15230,22 +15287,18 @@ function applySlippage(tradeType, amount, slippage) {
15230
15287
  const amountWithSlippage = maybeInverted.multiply(amount.toString()).quotient;
15231
15288
  return ethers.BigNumber.from(amountWithSlippage.toString());
15232
15289
  }
15233
- function prepareUserQuote(otherToken, tradeInfo, slippage, fees, nativeTokenService) {
15234
- const quote = getQuoteAmountFromTradeType(tradeInfo);
15235
- const amountWithSlippage = applySlippage(tradeInfo.tradeType, quote.value, slippage);
15290
+ const prepareUserQuote = (nativeTokenService, routerQuote, slippage, tokenOfQuotedAmount) => {
15291
+ const erc20QuoteAmount = getQuoteAmountFromTradeType(routerQuote);
15292
+ // If the quote amount is the native token, we need to unwrap it if the user originally specified the native token
15293
+ const quotedAmount = canUnwrapToken(tokenOfQuotedAmount)
15294
+ ? nativeTokenService.unwrapAmount(erc20QuoteAmount)
15295
+ : erc20QuoteAmount;
15296
+ const quotedAmountWithMaxSlippage = newAmount(applySlippage(routerQuote.tradeType, quotedAmount.value, slippage), tokenOfQuotedAmount);
15236
15297
  return {
15237
- amount: quote,
15238
- amountWithMaxSlippage: {
15239
- token: otherToken,
15240
- value: amountWithSlippage,
15241
- },
15242
- slippage,
15243
- fees: fees.withAmounts().map((fee) => ({
15244
- ...fee,
15245
- amount: nativeTokenService.maybeWrapAmount(fee.amount),
15246
- })),
15298
+ quotedAmount,
15299
+ quotedAmountWithMaxSlippage,
15247
15300
  };
15248
- }
15301
+ };
15249
15302
  function getOurQuoteReqAmount(amountSpecified, // the amount specified by the user, either exactIn or exactOut
15250
15303
  fees, tradeType, nativeTokenService) {
15251
15304
  if (tradeType === TradeType.EXACT_OUTPUT) {
@@ -15313,46 +15366,8 @@ class Fees {
15313
15366
  }
15314
15367
  }
15315
15368
 
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
-
15346
15369
  const IMMUTABLE_TESTNET_RPC_URL = 'https://rpc.testnet.immutable.com';
15347
15370
  const IMMUTABLE_TESTNET_CHAIN_ID = 13472;
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
- };
15356
15371
  const TIMX_IMMUTABLE_TESTNET = {
15357
15372
  chainId: IMMUTABLE_TESTNET_CHAIN_ID,
15358
15373
  address: '0x0000000000000000000000000000000000001010',
@@ -15382,7 +15397,9 @@ function buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, amountI
15382
15397
  recipient: fee.recipient,
15383
15398
  }));
15384
15399
  if (trade.tradeType === TradeType.EXACT_INPUT) {
15385
- return secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [secondaryFeeValues, {
15400
+ return secondaryFeeContract.encodeFunctionData('exactInputSingleWithSecondaryFee', [
15401
+ secondaryFeeValues,
15402
+ {
15386
15403
  tokenIn: route.tokenPath[0].address,
15387
15404
  tokenOut: route.tokenPath[1].address,
15388
15405
  fee: route.pools[0].fee,
@@ -15390,9 +15407,12 @@ function buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, amountI
15390
15407
  amountIn,
15391
15408
  amountOutMinimum: amountOut,
15392
15409
  sqrtPriceLimitX96: 0,
15393
- }]);
15410
+ },
15411
+ ]);
15394
15412
  }
15395
- return secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [secondaryFeeValues, {
15413
+ return secondaryFeeContract.encodeFunctionData('exactOutputSingleWithSecondaryFee', [
15414
+ secondaryFeeValues,
15415
+ {
15396
15416
  tokenIn: route.tokenPath[0].address,
15397
15417
  tokenOut: route.tokenPath[1].address,
15398
15418
  fee: route.pools[0].fee,
@@ -15400,7 +15420,8 @@ function buildSwapParametersForSinglePoolSwap(fromAddress, trade, route, amountI
15400
15420
  amountInMaximum: amountIn,
15401
15421
  amountOut,
15402
15422
  sqrtPriceLimitX96: 0,
15403
- }]);
15423
+ },
15424
+ ]);
15404
15425
  }
15405
15426
  function buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, amountIn, amountOut, secondaryFees, secondaryFeeContract) {
15406
15427
  const path = encodeRouteToPath(route, trade.tradeType === TradeType.EXACT_OUTPUT);
@@ -15409,19 +15430,25 @@ function buildSwapParametersForMultiPoolSwap(fromAddress, trade, route, amountIn
15409
15430
  recipient: fee.recipient,
15410
15431
  }));
15411
15432
  if (trade.tradeType === TradeType.EXACT_INPUT) {
15412
- return secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [secondaryFeeValues, {
15433
+ return secondaryFeeContract.encodeFunctionData('exactInputWithSecondaryFee', [
15434
+ secondaryFeeValues,
15435
+ {
15413
15436
  path,
15414
15437
  recipient: fromAddress,
15415
15438
  amountIn,
15416
15439
  amountOutMinimum: amountOut,
15417
- }]);
15440
+ },
15441
+ ]);
15418
15442
  }
15419
- return secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [secondaryFeeValues, {
15443
+ return secondaryFeeContract.encodeFunctionData('exactOutputWithSecondaryFee', [
15444
+ secondaryFeeValues,
15445
+ {
15420
15446
  path,
15421
15447
  recipient: fromAddress,
15422
15448
  amountInMaximum: amountIn,
15423
15449
  amountOut,
15424
- }]);
15450
+ },
15451
+ ]);
15425
15452
  }
15426
15453
  /**
15427
15454
  * Builds swap parameters
@@ -15446,7 +15473,10 @@ function buildSwapParameters(fromAddress, trade, options, secondaryFees, seconda
15446
15473
  function createSwapCallParametersWithFees(trade, fromAddress, swapOptions, secondaryFees) {
15447
15474
  const secondaryFeeContract = SecondaryFee__factory.createInterface();
15448
15475
  const swapWithFeesCalldata = buildSwapParameters(fromAddress, trade, swapOptions, secondaryFees, secondaryFeeContract);
15449
- return secondaryFeeContract.encodeFunctionData(multicallWithDeadlineFunctionSignature, [swapOptions.deadlineOrPreviousBlockhash, [swapWithFeesCalldata]]);
15476
+ return secondaryFeeContract.encodeFunctionData(multicallWithDeadlineFunctionSignature, [
15477
+ swapOptions.deadlineOrPreviousBlockhash,
15478
+ [swapWithFeesCalldata],
15479
+ ]);
15450
15480
  }
15451
15481
  function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees) {
15452
15482
  // Create an unchecked trade to be used in generating swap parameters.
@@ -15486,7 +15516,7 @@ function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouter
15486
15516
  const adjustAmountIn = (ourQuote, amountSpecified, fees, nativeTokenService) => {
15487
15517
  if (ourQuote.tradeType === TradeType.EXACT_OUTPUT) {
15488
15518
  // when doing exact output, calculate the fees based on the amountIn
15489
- const amountToAdd = nativeTokenService.isNativeToken(fees.token)
15519
+ const amountToAdd = canUnwrapToken(fees.token)
15490
15520
  ? nativeTokenService.unwrapAmount(ourQuote.amountIn)
15491
15521
  : ourQuote.amountIn;
15492
15522
  fees.addAmount(amountToAdd);
@@ -15530,7 +15560,7 @@ const SUPPORTED_SANDBOX_CHAINS = {
15530
15560
  rpcUrl: IMMUTABLE_TESTNET_RPC_URL,
15531
15561
  contracts: CONTRACTS_FOR_CHAIN_ID[IMMUTABLE_TESTNET_CHAIN_ID],
15532
15562
  commonRoutingTokens: IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS,
15533
- nativeToken: NATIVE_IMX_IMMUTABLE_TESTNET,
15563
+ nativeToken: TIMX_IMMUTABLE_TESTNET,
15534
15564
  wrappedNativeToken: TIMX_IMMUTABLE_TESTNET, // TODO: TP-1649: Change to WIMX when ready.
15535
15565
  },
15536
15566
  };
@@ -15602,6 +15632,15 @@ class ExchangeConfiguration {
15602
15632
  }
15603
15633
  }
15604
15634
 
15635
+ const toPublicQuote = (amount, amountWithMaxSlippage, slippage, fees) => ({
15636
+ amount: toPublicAmount(amount),
15637
+ amountWithMaxSlippage: toPublicAmount(amountWithMaxSlippage),
15638
+ slippage,
15639
+ fees: fees.withAmounts().map((fee) => ({
15640
+ ...fee,
15641
+ amount: toPublicAmount(fee.amount),
15642
+ })),
15643
+ });
15605
15644
  class Exchange {
15606
15645
  provider;
15607
15646
  router;
@@ -15630,8 +15669,8 @@ class Exchange {
15630
15669
  }
15631
15670
  static validate(tokenInAddress, tokenOutAddress, maxHops, slippagePercent, fromAddress) {
15632
15671
  assert(isValidNonZeroAddress(fromAddress), new InvalidAddressError('invalid from address'));
15633
- assert(isValidNonZeroAddress(tokenInAddress), new InvalidAddressError('invalid token in address'));
15634
- assert(isValidNonZeroAddress(tokenOutAddress), new InvalidAddressError('invalid token out address'));
15672
+ assert(isValidTokenLiteral(tokenInAddress), new InvalidAddressError('invalid token in address'));
15673
+ assert(isValidTokenLiteral(tokenOutAddress), new InvalidAddressError('invalid token out address'));
15635
15674
  assert(tokenInAddress.toLocaleLowerCase() !== tokenOutAddress.toLocaleLowerCase(), new DuplicateAddressesError());
15636
15675
  assert(maxHops <= MAX_MAX_HOPS, new InvalidMaxHopsError('max hops must be less than or equal to 10'));
15637
15676
  assert(maxHops >= MIN_MAX_HOPS, new InvalidMaxHopsError('max hops must be greater than or equal to 1'));
@@ -15649,63 +15688,63 @@ class Exchange {
15649
15688
  }
15650
15689
  return this.secondaryFees;
15651
15690
  }
15652
- async getUnsignedSwapTx(fromAddress, tokenInAddress, tokenOutAddress, amount, slippagePercent, maxHops, deadline, tradeType) {
15653
- Exchange.validate(tokenInAddress, tokenOutAddress, maxHops, slippagePercent, fromAddress);
15691
+ parseTokenLiteral(tokenLiteral, decimals) {
15692
+ if (tokenLiteral === 'native') {
15693
+ return this.nativeToken;
15694
+ }
15695
+ return {
15696
+ type: 'erc20',
15697
+ address: tokenLiteral,
15698
+ chainId: this.chainId,
15699
+ decimals,
15700
+ };
15701
+ }
15702
+ async getUnsignedSwapTx(fromAddress, tokenInLiteral, tokenOutLiteral, amount, slippagePercent, maxHops, deadline, tradeType) {
15703
+ Exchange.validate(tokenInLiteral, tokenOutLiteral, maxHops, slippagePercent, fromAddress);
15654
15704
  // get the decimals of the tokens that will be swapped
15655
15705
  const [tokenInDecimals, tokenOutDecimals, secondaryFees] = await Promise.all([
15656
- getERC20Decimals(tokenInAddress, this.provider),
15657
- getERC20Decimals(tokenOutAddress, this.provider),
15706
+ getTokenDecimals(tokenInLiteral, this.provider, this.nativeToken),
15707
+ getTokenDecimals(tokenOutLiteral, this.provider, this.nativeToken),
15658
15708
  this.getSecondaryFees(),
15659
15709
  ]);
15660
- const tokenIn = {
15661
- type: 'erc20',
15662
- address: tokenInAddress,
15663
- chainId: this.chainId,
15664
- decimals: tokenInDecimals,
15665
- };
15666
- const tokenOut = {
15667
- type: 'erc20',
15668
- address: tokenOutAddress,
15669
- chainId: this.chainId,
15670
- decimals: tokenOutDecimals,
15671
- };
15710
+ const tokenIn = this.parseTokenLiteral(tokenInLiteral, tokenInDecimals);
15711
+ const tokenOut = this.parseTokenLiteral(tokenOutLiteral, tokenOutDecimals);
15672
15712
  // determine which amount was specified for the swap from the TradeType
15673
15713
  const [tokenSpecified, otherToken] = tradeType === TradeType.EXACT_INPUT ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
15674
15714
  const amountSpecified = newAmount(amount, tokenSpecified);
15675
15715
  const fees = new Fees(secondaryFees, tokenIn);
15676
15716
  const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType, this.nativeTokenService);
15677
- // get quote and gas details
15717
+ // Quotes will always use ERC20s. If the user-specified token is Native, we use the Wrapped Native Token pool
15678
15718
  const [ourQuote, gasPrice] = await Promise.all([
15679
- this.router.findOptimalRoute(ourQuoteReqAmount, otherToken, tradeType, maxHops),
15719
+ this.router.findOptimalRoute(ourQuoteReqAmount, this.nativeTokenService.maybeWrapToken(otherToken), tradeType, maxHops),
15680
15720
  fetchGasPrice(this.provider, this.nativeToken),
15681
15721
  ]);
15682
15722
  const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
15683
15723
  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, {
15724
+ const { quotedAmount, quotedAmountWithMaxSlippage } = prepareUserQuote(this.nativeTokenService, adjustedQuote, slippagePercent, otherToken);
15725
+ const preparedApproval = prepareApproval(tradeType, amountSpecified, quotedAmountWithMaxSlippage, {
15686
15726
  routerAddress: this.routerContractAddress,
15687
15727
  secondaryFeeAddress: this.secondaryFeeContractAddress,
15688
15728
  }, secondaryFees);
15689
15729
  // preparedApproval always uses the tokenIn address because we are always selling the tokenIn
15690
- const approval = await getApproval(this.provider, fromAddress, preparedApproval, gasPrice, this.nativeTokenService);
15691
- return {
15692
- approval,
15693
- swap,
15694
- quote: userQuote,
15695
- };
15730
+ const approval = preparedApproval
15731
+ ? await getApproval(this.provider, fromAddress, preparedApproval, gasPrice)
15732
+ : null;
15733
+ const quote = toPublicQuote(quotedAmount, quotedAmountWithMaxSlippage, slippagePercent, fees);
15734
+ return { quote, approval, swap };
15696
15735
  }
15697
15736
  /**
15698
15737
  * Get the unsigned swap transaction given the amount to sell.
15699
15738
  * Includes quote details for the swap.
15700
15739
  *
15701
- * @param {string} fromAddress The public address that will sign and submit the transaction.
15702
- * @param {string} tokenInAddress Token address to sell.
15703
- * @param {string} tokenOutAddress Token address to buy.
15704
- * @param {ethers.BigNumberish} amountIn Amount to sell.
15705
- * @param {number} slippagePercent (optional) The percentage of slippage tolerance. Default = 0.1. Max = 50. Min = 0.
15706
- * @param {number} maxHops (optional) Maximum hops allowed in optimal route. Default is 2.
15707
- * @param {number} deadline (optional) Latest time swap can execute. Default is 15 minutes.
15708
- * @return {TransactionResponse} The result containing the unsigned transaction and details of the swap.
15740
+ * @param {string} fromAddress The public address that will sign and submit the transaction
15741
+ * @param {string} tokenInAddress Token address or 'native' to sell
15742
+ * @param {string} tokenOutAddress Token address or 'native' to buy
15743
+ * @param {ethers.BigNumberish} amountIn Amount to sell in the smallest unit of the token-in
15744
+ * @param {number} slippagePercent (optional) The percentage of slippage tolerance. Default = 0.1. Max = 50. Min = 0
15745
+ * @param {number} maxHops (optional) Maximum hops allowed in optimal route. Default is 2
15746
+ * @param {number} deadline (optional) Latest time swap can execute. Default is 15 minutes
15747
+ * @return {TransactionResponse} The result containing the unsigned transaction and details of the swap
15709
15748
  */
15710
15749
  async getUnsignedSwapTxFromAmountIn(fromAddress, tokenInAddress, tokenOutAddress, amountIn, slippagePercent = DEFAULT_SLIPPAGE, maxHops = DEFAULT_MAX_HOPS, deadline = DEFAULT_DEADLINE) {
15711
15750
  return await this.getUnsignedSwapTx(fromAddress, tokenInAddress, tokenOutAddress, ethers.BigNumber.from(amountIn), slippagePercent, maxHops, deadline, TradeType.EXACT_INPUT);
@@ -15714,14 +15753,14 @@ class Exchange {
15714
15753
  * Get the unsigned swap transaction given the amount to buy.
15715
15754
  * Includes quote details for the swap.
15716
15755
  *
15717
- * @param {string} fromAddress The public address that will sign and submit the transaction.
15718
- * @param {string} tokenInAddress Token address to sell.
15719
- * @param {string} tokenOutAddress Token address to buy.
15720
- * @param {ethers.BigNumberish} amountOut Amount to buy.
15721
- * @param {number} slippagePercent (optional) The percentage of slippage tolerance. Default = 0.1. Max = 50. Min = 0.
15722
- * @param {number} maxHops (optional) Maximum hops allowed in optimal route. Default is 2.
15723
- * @param {number} deadline (optional) Latest time swap can execute. Default is 15 minutes.
15724
- * @return {TransactionResponse} The result containing the unsigned transaction and details of the swap.
15756
+ * @param {string} fromAddress The public address that will sign and submit the transaction
15757
+ * @param {string} tokenInAddress ERC20 contract address or 'native' to sell
15758
+ * @param {string} tokenOutAddress ERC20 contract address or 'native' to buy
15759
+ * @param {ethers.BigNumberish} amountOut Amount to buy in the smallest unit of the token-out
15760
+ * @param {number} slippagePercent (optional) The percentage of slippage tolerance. Default = 0.1. Max = 50. Min = 0
15761
+ * @param {number} maxHops (optional) Maximum hops allowed in optimal route. Default is 2
15762
+ * @param {number} deadline (optional) Latest time swap can execute. Default is 15 minutes
15763
+ * @return {TransactionResponse} The result containing the unsigned transaction and details of the swap
15725
15764
  */
15726
15765
  async getUnsignedSwapTxFromAmountOut(fromAddress, tokenInAddress, tokenOutAddress, amountOut, slippagePercent = DEFAULT_SLIPPAGE, maxHops = DEFAULT_MAX_HOPS, deadline = DEFAULT_DEADLINE) {
15727
15766
  return await this.getUnsignedSwapTx(fromAddress, tokenInAddress, tokenOutAddress, ethers.BigNumber.from(amountOut), slippagePercent, maxHops, deadline, TradeType.EXACT_OUTPUT);
@@ -20548,7 +20587,7 @@ class APIError extends Error {
20548
20587
 
20549
20588
  /* eslint-disable implicit-arrow-linebreak */
20550
20589
  const defaultHeaders = {
20551
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.9',
20590
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.11',
20552
20591
  };
20553
20592
  /**
20554
20593
  * createAPIConfiguration to create a custom Configuration
@@ -21174,6 +21213,14 @@ const $d85ad1457a3f1a83$export$fc55ed5a42b458ba = {
21174
21213
  [($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_MAINNET]: {
21175
21214
  url: "https://explorer.mainnet.immutable.com",
21176
21215
  nativeToken: $d85ad1457a3f1a83$export$6f24f3cef7d501c4.get(($0472f23319457bfb$export$c06e1e7429de6283).IMTBL_ZKEVM_MAINNET).nativeCurrency
21216
+ },
21217
+ [($0472f23319457bfb$export$c06e1e7429de6283).SEPOLIA]: {
21218
+ url: "https://eth-sepolia.blockscout.com",
21219
+ nativeToken: $d85ad1457a3f1a83$export$3e81fc0987227f10.get(($0472f23319457bfb$export$c06e1e7429de6283).SEPOLIA).nativeCurrency
21220
+ },
21221
+ [($0472f23319457bfb$export$c06e1e7429de6283).ETHEREUM]: {
21222
+ url: "https://eth.blockscout.com/",
21223
+ nativeToken: $d85ad1457a3f1a83$export$6f24f3cef7d501c4.get(($0472f23319457bfb$export$c06e1e7429de6283).ETHEREUM).nativeCurrency
21177
21224
  }
21178
21225
  };
21179
21226
  const $d85ad1457a3f1a83$export$db5daa1b5156ccfe = [
@@ -21773,6 +21820,7 @@ const $efe60cea83bfc4e8$export$473cec51305fdae8 = async (config, { type: type =
21773
21820
 
21774
21821
 
21775
21822
 
21823
+
21776
21824
  const $fd8a8472dcc3ec2b$var$CACHE_DATA_TTL = 60; // seconds
21777
21825
  class $fd8a8472dcc3ec2b$export$ef140a6b05dfc786 {
21778
21826
  url;
@@ -21945,18 +21993,23 @@ async function $1564e43dde50bb61$export$60e0fe116a0e6ed0(web3Provider, walletAdd
21945
21993
  type: ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).GET_ERC20_BALANCE_ERROR
21946
21994
  });
21947
21995
  }
21948
- // Blockscout client singleton
21949
- let $1564e43dde50bb61$var$blockscoutClient;
21950
- const $1564e43dde50bb61$export$8c978679845804d4 = async (walletAddress, chainId, rename)=>{
21996
+ // Blockscout client singleton per chain id
21997
+ const $1564e43dde50bb61$var$blockscoutClientMap = new Map();
21998
+ const $1564e43dde50bb61$export$8c978679845804d4 = async (walletAddress, chainId, filterTokens)=>{
21951
21999
  // Shuffle the mapping of the tokens configuration so it is a hashmap
21952
22000
  // for faster access to tokens config objects.
21953
- const mapRename = Object.assign({}, ...rename.map((t)=>({
22001
+ const shouldFilter = filterTokens.length > 0;
22002
+ const mapFilterTokens = Object.assign({}, ...filterTokens.map((t)=>({
21954
22003
  [t.address || ""]: t
21955
22004
  })));
21956
- // Ensure singleton is present and match the selected chain
21957
- if (!$1564e43dde50bb61$var$blockscoutClient || $1564e43dde50bb61$var$blockscoutClient.chainId !== chainId) $1564e43dde50bb61$var$blockscoutClient = new ($fd8a8472dcc3ec2b$export$ef140a6b05dfc786)({
21958
- chainId: chainId
21959
- });
22005
+ // Get blockscout client for the given chain
22006
+ let blockscoutClient = $1564e43dde50bb61$var$blockscoutClientMap.get(chainId);
22007
+ if (!blockscoutClient) {
22008
+ blockscoutClient = new ($fd8a8472dcc3ec2b$export$ef140a6b05dfc786)({
22009
+ chainId: chainId
22010
+ });
22011
+ $1564e43dde50bb61$var$blockscoutClientMap.set(chainId, blockscoutClient);
22012
+ }
21960
22013
  // Hold the items in an array for post-fetching processing
21961
22014
  const items = [];
21962
22015
  const tokenType = ($887a00f8f72d61f0$export$5bd1ea2b3d18210).ERC20;
@@ -21966,7 +22019,7 @@ const $1564e43dde50bb61$export$8c978679845804d4 = async (walletAddress, chainId,
21966
22019
  try {
21967
22020
  do {
21968
22021
  // eslint-disable-next-line no-await-in-loop
21969
- resp = await $1564e43dde50bb61$var$blockscoutClient.getTokensByWalletAddress({
22022
+ resp = await blockscoutClient.getTokensByWalletAddress({
21970
22023
  walletAddress: walletAddress,
21971
22024
  tokenType: tokenType,
21972
22025
  nextPage: resp?.next_page_params
@@ -21984,7 +22037,7 @@ const $1564e43dde50bb61$export$8c978679845804d4 = async (walletAddress, chainId,
21984
22037
  if (err?.code !== (HttpStatusCode).NotFound) throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)(err.message || "InternalServerError | getTokensByWalletAddress", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).GET_INDEXER_BALANCE_ERROR, err);
21985
22038
  }
21986
22039
  try {
21987
- const respNative = await $1564e43dde50bb61$var$blockscoutClient.getNativeTokenByWalletAddress({
22040
+ const respNative = await blockscoutClient.getNativeTokenByWalletAddress({
21988
22041
  walletAddress: walletAddress
21989
22042
  });
21990
22043
  items.push(respNative);
@@ -21998,24 +22051,26 @@ const $1564e43dde50bb61$export$8c978679845804d4 = async (walletAddress, chainId,
21998
22051
  // or simply an incorrect wallet address was provided.
21999
22052
  if (err?.code !== (HttpStatusCode).NotFound) throw new ($a8bc256d81a5e2c1$export$b722478a3cbfa3bc)(err.message || "InternalServerError | getNativeTokenByWalletAddress", ($a8bc256d81a5e2c1$export$e3dc0620abde7f5a).GET_INDEXER_BALANCE_ERROR, err);
22000
22053
  }
22054
+ const balances = [];
22055
+ items.forEach((item)=>{
22056
+ if (shouldFilter && !mapFilterTokens[item.token.address]) return;
22057
+ const tokenData = item.token || {};
22058
+ const balance = (BigNumber$1).from(item.value);
22059
+ let decimals = parseInt(tokenData.decimals, 10);
22060
+ if (Number.isNaN(decimals)) decimals = ($d85ad1457a3f1a83$export$903389470ba9433c);
22061
+ const token = {
22062
+ ...tokenData,
22063
+ decimals: decimals
22064
+ };
22065
+ const formattedBalance = (utils).formatUnits(item.value, token.decimals);
22066
+ balances.push({
22067
+ balance: balance,
22068
+ formattedBalance: formattedBalance,
22069
+ token: token
22070
+ });
22071
+ });
22001
22072
  return {
22002
- balances: items.map((item)=>{
22003
- const tokenData = item.token || {};
22004
- const balance = (BigNumber$1).from(item.value);
22005
- const renamed = mapRename[tokenData.address] || {};
22006
- const token = {
22007
- ...tokenData,
22008
- name: renamed.name ?? tokenData.name,
22009
- symbol: renamed.symbol ?? tokenData.symbol,
22010
- decimals: parseInt(tokenData.decimals, 10)
22011
- };
22012
- const formattedBalance = (utils).formatUnits(item.value, token.decimals);
22013
- return {
22014
- balance: balance,
22015
- formattedBalance: formattedBalance,
22016
- token: token
22017
- };
22018
- })
22073
+ balances: balances
22019
22074
  };
22020
22075
  };
22021
22076
  const $1564e43dde50bb61$export$a3238cee431627c6 = async (config, web3Provider, walletAddress, tokens)=>{
@@ -22046,7 +22101,15 @@ const $1564e43dde50bb61$export$fee49741664a4d7e = async (config, web3Provider, w
22046
22101
  // eslint-disable-next-line no-console
22047
22102
  console.error(err);
22048
22103
  }
22049
- if (flag && ($fd8a8472dcc3ec2b$export$ef140a6b05dfc786).isChainSupported(chainId)) return await $1564e43dde50bb61$export$8c978679845804d4(walletAddress, chainId, tokens);
22104
+ if (flag && ($fd8a8472dcc3ec2b$export$ef140a6b05dfc786).isChainSupported(chainId)) {
22105
+ // This is a hack because the widgets are still using the tokens symbol
22106
+ // to drive the conversions. If we remove all the token symbols from e.g. zkevm
22107
+ // then we would not have fiat conversions.
22108
+ // Please remove this hack once https://immutable.atlassian.net/browse/WT-1710
22109
+ // is done.
22110
+ const isL1Chain = ($4013c5c91bb535f6$export$9b794d067cdd1af6)(config) === chainId;
22111
+ return await $1564e43dde50bb61$export$8c978679845804d4(walletAddress, chainId, isL1Chain ? tokens : []);
22112
+ }
22050
22113
  // This fallback to use ERC20s calls which is a best effort solution
22051
22114
  // Fails in fetching data from the RCP calls might result in some
22052
22115
  // missing data.
@@ -25020,7 +25083,7 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
25020
25083
  const tokenList = await $efe60cea83bfc4e8$export$473cec51305fdae8(this.config, {
25021
25084
  type: ($08d5ddc39acd6833$export$fd9b17d87f4121d2).ONRAMP
25022
25085
  });
25023
- const token = tokenList.tokens.find((t)=>t.address?.toLowerCase() === params.tokenAddress?.toLowerCase());
25086
+ const token = tokenList.tokens?.find((t)=>t.address?.toLowerCase() === params.tokenAddress?.toLowerCase());
25024
25087
  if (token) {
25025
25088
  tokenAmount = params.tokenAmount;
25026
25089
  tokenSymbol = token.symbol;
@@ -25618,7 +25618,7 @@ declare enum IMTBLWidgetEvents {
25618
25618
  IMTBL_SWAP_WIDGET_EVENT = "imtbl-swap-widget",
25619
25619
  IMTBL_BRIDGE_WIDGET_EVENT = "imtbl-bridge-widget",
25620
25620
  IMTBL_ONRAMP_WIDGET_EVENT = "imtbl-onramp-widget",
25621
- IMTBL_PRIMARY_REVENUE_WIDGET_EVENT = "imtbl-sale-widget"
25621
+ IMTBL_SALE_WIDGET_EVENT = "imtbl-sale-widget"
25622
25622
  }
25623
25623
  /**
25624
25624
  * Represents an event emitted by a widget.