@imtbl/sdk 0.27.6 → 0.27.8

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
@@ -3609,7 +3609,7 @@ class MultiRollupApiClients {
3609
3609
  }
3610
3610
 
3611
3611
  // eslint-disable-next-line @typescript-eslint/naming-convention
3612
- const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.27.6' };
3612
+ const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.27.8' };
3613
3613
  const createConfig = ({ basePath, headers, }) => {
3614
3614
  if (!basePath.trim()) {
3615
3615
  throw Error('basePath can not be empty');
@@ -3669,7 +3669,7 @@ class APIError extends Error {
3669
3669
 
3670
3670
  /* eslint-disable implicit-arrow-linebreak */
3671
3671
  const defaultHeaders = {
3672
- sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.6',
3672
+ sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.27.8',
3673
3673
  };
3674
3674
  /**
3675
3675
  * createAPIConfiguration to create a custom Configuration
@@ -4080,7 +4080,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
4080
4080
  chainID,
4081
4081
  coreContractAddress,
4082
4082
  registrationContractAddress,
4083
- sdkVersion: 'ts-immutable-sdk-0.27.6',
4083
+ sdkVersion: 'ts-immutable-sdk-0.27.8',
4084
4084
  });
4085
4085
  /**
4086
4086
  * Sets `sdkVersion` at the time of build
@@ -11771,9 +11771,6 @@ class Seaport {
11771
11771
  };
11772
11772
  }
11773
11773
  async fulfillBulkOrders(fulfillingOrders, account) {
11774
- // TODO: this function right now does not handle errors from the seaport.js
11775
- // we should figure out why orders are rejected and return a submission
11776
- // transaction on best efforts basis
11777
11774
  const fulfillOrderDetails = fulfillingOrders.map((o) => {
11778
11775
  const { orderComponents, tips } = this.mapImmutableOrderToSeaportOrderComponents(o.order);
11779
11776
  return {
@@ -12192,14 +12189,34 @@ class Orderbook {
12192
12189
  recipient: fee.recipient,
12193
12190
  })),
12194
12191
  })));
12195
- return {
12196
- ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
12197
- fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
12198
- unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
12199
- orderId: o.order_id,
12200
- reason: o.reason,
12201
- })),
12202
- };
12192
+ try {
12193
+ return {
12194
+ ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
12195
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
12196
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
12197
+ orderId: o.order_id,
12198
+ reason: o.reason,
12199
+ })),
12200
+ sufficientBalance: true,
12201
+ };
12202
+ }
12203
+ catch (e) {
12204
+ // if insufficient balance error, we return FulfillBulkOrdersInsufficientBalanceResponse
12205
+ if (String(e).includes('The fulfiller does not have the balances needed to fulfill.')) {
12206
+ return {
12207
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
12208
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
12209
+ orderId: o.order_id,
12210
+ reason: o.reason,
12211
+ })),
12212
+ sufficientBalance: false,
12213
+ };
12214
+ }
12215
+ // if some other error is thrown,
12216
+ // there likely is a race condition of the original order validity
12217
+ // we throw the error back out
12218
+ throw e;
12219
+ }
12203
12220
  }
12204
12221
  /**
12205
12222
  * Get an unsigned cancel order transaction. Orders can only be cancelled by
@@ -27995,23 +28012,36 @@ function isValidNonZeroAddress(address) {
27995
28012
  return false;
27996
28013
  }
27997
28014
  }
27998
- const tokenInfoToUniswapToken = (tokenInfo) => new Token(tokenInfo.chainId, tokenInfo.address, tokenInfo.decimals, tokenInfo.symbol, tokenInfo.name);
28015
+ const erc20ToUniswapToken = (token) =>
28016
+ // eslint-disable-next-line implicit-arrow-linebreak
28017
+ new Token(token.chainId, token.address, token.decimals, token.symbol, token.name);
28018
+ const uniswapTokenToERC20 = (token) => ({
28019
+ chainId: token.chainId,
28020
+ address: token.address,
28021
+ decimals: token.decimals,
28022
+ symbol: token.symbol,
28023
+ name: token.name,
28024
+ type: 'erc20',
28025
+ });
27999
28026
  const toCurrencyAmount = (amount) => {
28000
- const token = tokenInfoToUniswapToken(amount.token);
28027
+ const token = erc20ToUniswapToken(amount.token);
28001
28028
  return CurrencyAmount.fromRawAmount(token, amount.value.toString());
28002
28029
  };
28003
28030
  const newAmount = (amount, token) => ({
28004
28031
  value: amount,
28005
28032
  token,
28006
28033
  });
28007
- const addAmount = (a, b) => {
28034
+ const isERC20Amount = (amount) => amount.token.type === 'erc20';
28035
+ const addERC20Amount = (a, b) => {
28036
+ // Make sure the ERC20s have the same address
28008
28037
  if (a.token.address !== b.token.address)
28009
- throw new Error('Token mismatch');
28038
+ throw new Error('Token mismatch: token addresses must be the same');
28010
28039
  return { value: a.value.add(b.value), token: a.token };
28011
28040
  };
28012
- const subtractAmount = (a, b) => {
28041
+ const subtractERC20Amount = (a, b) => {
28042
+ // Make sure the ERC20s have the same address
28013
28043
  if (a.token.address !== b.token.address)
28014
- throw new Error('Token mismatch');
28044
+ throw new Error('Token mismatch: token addresses must be the same');
28015
28045
  return { value: a.value.sub(b.value), token: a.token };
28016
28046
  };
28017
28047
 
@@ -28051,10 +28081,12 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
28051
28081
  const quoteAmount = decodedQuoteResult[amountIndex];
28052
28082
  if (!(quoteAmount instanceof BigNumber$1))
28053
28083
  throw new Error('Expected BigNumber');
28084
+ const input = uniswapTokenToERC20(routes[i].input);
28085
+ const output = uniswapTokenToERC20(routes[i].output);
28054
28086
  decodedQuoteResults.push({
28055
28087
  route: routes[i],
28056
- amountIn: tradeType === TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, routes[i].input),
28057
- amountOut: tradeType === TradeType.EXACT_INPUT ? newAmount(quoteAmount, routes[i].output) : amountSpecified,
28088
+ amountIn: tradeType === TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, input),
28089
+ amountOut: tradeType === TradeType.EXACT_INPUT ? newAmount(quoteAmount, output) : amountSpecified,
28058
28090
  gasEstimate: ethers.BigNumber.from(decodedQuoteResult[gasEstimateIndex]),
28059
28091
  tradeType,
28060
28092
  });
@@ -28185,7 +28217,7 @@ const fetchValidPools = async (multicallContract, erc20Pair, commonRoutingERC20s
28185
28217
  if (zeroPrice || zeroLiquidity) {
28186
28218
  return;
28187
28219
  }
28188
- const validPool = new Pool(tokenInfoToUniswapToken(poolID.erc20Pair[0]), tokenInfoToUniswapToken(poolID.erc20Pair[1]), poolID.fee, poolSlot0.sqrtPriceX96.toString(), poolLiquidity.toString(), poolSlot0.tick);
28220
+ const validPool = new Pool(erc20ToUniswapToken(poolID.erc20Pair[0]), erc20ToUniswapToken(poolID.erc20Pair[1]), poolID.fee, poolSlot0.sqrtPriceX96.toString(), poolLiquidity.toString(), poolSlot0.tick);
28189
28221
  validPools.push(validPool);
28190
28222
  });
28191
28223
  return validPools;
@@ -28271,9 +28303,9 @@ maxHops, // the maximum number of pools that can be traversed
28271
28303
  currentRoute = [], // list of pools already traversed
28272
28304
  routes = [], // list of all routes found so far
28273
28305
  startTokenIn = tokenIn) => {
28274
- const currencyIn = tokenInfoToUniswapToken(tokenIn);
28275
- const currencyOut = tokenInfoToUniswapToken(tokenOut);
28276
- const startCurrencyIn = tokenInfoToUniswapToken(startTokenIn);
28306
+ const currencyIn = erc20ToUniswapToken(tokenIn);
28307
+ const currencyOut = erc20ToUniswapToken(tokenOut);
28308
+ const startCurrencyIn = erc20ToUniswapToken(startTokenIn);
28277
28309
  for (const pool of pools) {
28278
28310
  // if the pool doesn't have the tokenIn or if it has already been traversed,
28279
28311
  // skip to the next pool
@@ -28292,7 +28324,7 @@ startTokenIn = tokenIn) => {
28292
28324
  else if (maxHops > 1) {
28293
28325
  // otherwise, if we haven't exceeded the maximum number of pools that can be traversed,
28294
28326
  // recursively call this function with the output token as the new starting currency
28295
- generateAllAcyclicPaths(outputToken, tokenOut, pools, maxHops - 1, [...currentRoute, pool], routes, startTokenIn);
28327
+ generateAllAcyclicPaths(uniswapTokenToERC20(outputToken), tokenOut, pools, maxHops - 1, [...currentRoute, pool], routes, startTokenIn);
28296
28328
  }
28297
28329
  }
28298
28330
  return routes;
@@ -28422,7 +28454,7 @@ async function getApproveGasEstimate(provider, ownerAddress, spenderAddress, tok
28422
28454
  from: ownerAddress,
28423
28455
  });
28424
28456
  }
28425
- const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice) => {
28457
+ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice, nativeTokenService) => {
28426
28458
  const approveTransaction = await getApproveTransaction(provider, ownerAddress, preparedApproval.amount, preparedApproval.spender);
28427
28459
  if (!approveTransaction) {
28428
28460
  return null;
@@ -28431,7 +28463,8 @@ const getApproval = async (provider, ownerAddress, preparedApproval, gasPrice) =
28431
28463
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, gasEstimate) : null;
28432
28464
  return {
28433
28465
  transaction: approveTransaction,
28434
- gasFeeEstimate,
28466
+ // TODO: TP-1649: Remove the wrapping here
28467
+ gasFeeEstimate: gasFeeEstimate ? nativeTokenService.maybeWrapAmount(gasFeeEstimate) : null,
28435
28468
  };
28436
28469
  };
28437
28470
 
@@ -28480,13 +28513,18 @@ function prepareUserQuote(otherToken, tradeInfo, slippage, fees) {
28480
28513
  fees: fees.withAmounts(),
28481
28514
  };
28482
28515
  }
28483
- function getOurQuoteReqAmount(amount, fees, tradeType) {
28516
+ function getOurQuoteReqAmount(amountSpecified, // the amount specified by the user, either exactIn or exactOut
28517
+ fees, tradeType, nativeTokenService) {
28518
+ // TODO: TP-1649: Remove this when we support Native
28519
+ if (!isERC20Amount(amountSpecified)) {
28520
+ throw new Error('Not implemented yet!');
28521
+ }
28484
28522
  if (tradeType === TradeType.EXACT_OUTPUT) {
28485
28523
  // For an exact output swap, we do not need to subtract fees from the given amount
28486
- return amount;
28524
+ return nativeTokenService.maybeWrapAmount(amountSpecified);
28487
28525
  }
28488
- fees.addAmount(amount);
28489
- return fees.amountLessFees();
28526
+ fees.addAmount(amountSpecified);
28527
+ return nativeTokenService.maybeWrapAmount(fees.amountLessFees());
28490
28528
  }
28491
28529
 
28492
28530
  // 0.1% default slippage
@@ -28502,7 +28540,7 @@ const MIN_MAX_HOPS = 1;
28502
28540
  // precision used to calculate percentage from basis points
28503
28541
  const BASIS_POINT_PRECISION = 10000;
28504
28542
  // 10% maximum secondary fee
28505
- const MAX_SECONDARY_FEE_BASIS_POINTS = 10000;
28543
+ const MAX_SECONDARY_FEE_BASIS_POINTS = 1000;
28506
28544
 
28507
28545
  class Fees {
28508
28546
  secondaryFees;
@@ -28512,13 +28550,13 @@ class Fees {
28512
28550
  this.amount = newAmount(BigNumber$1.from(0), token);
28513
28551
  }
28514
28552
  addAmount(amount) {
28515
- this.amount = addAmount(this.amount, amount);
28553
+ this.amount = addERC20Amount(this.amount, amount);
28516
28554
  }
28517
28555
  amountWithFeesApplied() {
28518
- return addAmount(this.amount, this.total());
28556
+ return addERC20Amount(this.amount, this.total());
28519
28557
  }
28520
28558
  amountLessFees() {
28521
- return subtractAmount(this.amount, this.total());
28559
+ return subtractERC20Amount(this.amount, this.total());
28522
28560
  }
28523
28561
  withAmounts() {
28524
28562
  return this.secondaryFees.map((fee) => {
@@ -28537,24 +28575,71 @@ class Fees {
28537
28575
  const feeAmount = this.amount.value
28538
28576
  .mul(fee.basisPoints)
28539
28577
  .div(BASIS_POINT_PRECISION);
28540
- totalFees = addAmount(totalFees, newAmount(feeAmount, this.amount.token));
28578
+ totalFees = addERC20Amount(totalFees, newAmount(feeAmount, this.amount.token));
28541
28579
  }
28542
28580
  return totalFees;
28543
28581
  }
28544
28582
  }
28545
28583
 
28584
+ class NativeTokenService {
28585
+ nativeToken;
28586
+ wrappedToken;
28587
+ constructor(nativeToken, wrappedToken) {
28588
+ this.nativeToken = nativeToken;
28589
+ this.wrappedToken = wrappedToken;
28590
+ }
28591
+ wrapAmount(amount) {
28592
+ return newAmount(amount.value, this.wrappedToken);
28593
+ }
28594
+ unwrapAmount(amount) {
28595
+ if (amount.token !== this.wrappedToken) {
28596
+ throw new Error(`token ${amount.token.address} is not wrapped`);
28597
+ }
28598
+ return newAmount(amount.value, this.nativeToken);
28599
+ }
28600
+ maybeWrapToken(token) {
28601
+ if (this.isNativeToken(token)) {
28602
+ return this.wrappedToken;
28603
+ }
28604
+ return token;
28605
+ }
28606
+ maybeWrapAmount(amount) {
28607
+ return newAmount(amount.value, this.maybeWrapToken(amount.token));
28608
+ }
28609
+ isNativeToken(token) {
28610
+ return token === this.nativeToken;
28611
+ }
28612
+ }
28613
+
28546
28614
  const IMMUTABLE_TESTNET_RPC_URL = 'https://rpc.testnet.immutable.com';
28547
28615
  const IMMUTABLE_TESTNET_CHAIN_ID = 13472;
28548
28616
 
28617
+ const NATIVE_IMX_IMMUTABLE_TESTNET = {
28618
+ chainId: IMMUTABLE_TESTNET_CHAIN_ID,
28619
+ decimals: 18,
28620
+ symbol: 'tIMX',
28621
+ name: 'Immutable Testnet Token',
28622
+ type: 'native',
28623
+ };
28549
28624
  const TIMX_IMMUTABLE_TESTNET = {
28550
28625
  chainId: IMMUTABLE_TESTNET_CHAIN_ID,
28551
28626
  address: '0x0000000000000000000000000000000000001010',
28552
28627
  decimals: 18,
28553
28628
  symbol: 'tIMX',
28554
28629
  name: 'Immutable Testnet Token',
28630
+ type: 'erc20',
28631
+ };
28632
+ const WIMX_IMMUTABLE_TESTNET = {
28633
+ chainId: IMMUTABLE_TESTNET_CHAIN_ID,
28634
+ address: '0xAf7cf5D4Af0BFAa85d384d42b8D410762Ccbce69',
28635
+ decimals: 18,
28636
+ symbol: 'WIMX',
28637
+ name: 'Wrapped Immutable Testnet Token',
28638
+ type: 'erc20',
28555
28639
  };
28556
28640
  const IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS = [
28557
28641
  TIMX_IMMUTABLE_TESTNET,
28642
+ WIMX_IMMUTABLE_TESTNET,
28558
28643
  ];
28559
28644
 
28560
28645
  const zeroNativeCurrencyValue = '0x00';
@@ -28651,7 +28736,7 @@ function createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, se
28651
28736
  }
28652
28737
  return createSwapCallParametersWithFees(uncheckedTrade, fromAddress, options, secondaryFees);
28653
28738
  }
28654
- function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees) {
28739
+ function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouterAddress, secondaryFeesAddress, gasPrice, secondaryFees, nativeTokenService) {
28655
28740
  const calldata = createSwapParameters(adjustedQuote, fromAddress, slippage, deadline, secondaryFees);
28656
28741
  // TODO: Add additional gas fee estimates for secondary fees
28657
28742
  const gasFeeEstimate = gasPrice ? calculateGasFee(gasPrice, adjustedQuote.gasEstimate) : null;
@@ -28662,7 +28747,8 @@ function getSwap(adjustedQuote, fromAddress, slippage, deadline, peripheryRouter
28662
28747
  value: zeroNativeCurrencyValue,
28663
28748
  from: fromAddress,
28664
28749
  },
28665
- gasFeeEstimate,
28750
+ // TODO: TP-1649: Remove the wrapping here
28751
+ gasFeeEstimate: gasFeeEstimate ? nativeTokenService.maybeWrapAmount(gasFeeEstimate) : null,
28666
28752
  };
28667
28753
  }
28668
28754
  function prepareSwap(ourQuote, amountSpecified, fees) {
@@ -28690,7 +28776,7 @@ const CONTRACTS_FOR_CHAIN_ID = {
28690
28776
  multicall: '0xD17c98b38bA28c7eA1080317EB9AB2b9663BEd92',
28691
28777
  coreFactory: '0x8AC26EfCbf5D700b37A27aA00E6934e6904e7B8e',
28692
28778
  quoterV2: '0x0Afe6F5f4DC34461A801420634239FFaD50A2e44',
28693
- peripheryRouter: '0x5893A5c7bc615Dfd36D7383366d00FFFca5f7178',
28779
+ peripheryRouter: '0x57c73281f2697a632AEF1A48CD6ff600f49ee344',
28694
28780
  secondaryFee: '0x5893A5c7bc615Dfd36D7383366d00FFFca5f7178',
28695
28781
  },
28696
28782
  };
@@ -28700,7 +28786,8 @@ const SUPPORTED_SANDBOX_CHAINS = {
28700
28786
  rpcUrl: IMMUTABLE_TESTNET_RPC_URL,
28701
28787
  contracts: CONTRACTS_FOR_CHAIN_ID[IMMUTABLE_TESTNET_CHAIN_ID],
28702
28788
  commonRoutingTokens: IMMUTABLE_TESTNET_COMMON_ROUTING_TOKENS,
28703
- nativeToken: TIMX_IMMUTABLE_TESTNET,
28789
+ nativeToken: NATIVE_IMX_IMMUTABLE_TESTNET,
28790
+ wrappedNativeToken: TIMX_IMMUTABLE_TESTNET, // TODO: TP-1649: Change to WIMX when ready.
28704
28791
  },
28705
28792
  };
28706
28793
  const SUPPORTED_PRODUCTION_CHAINS = {};
@@ -28758,6 +28845,7 @@ class ExchangeConfiguration {
28758
28845
  contracts: overrides.exchangeContracts,
28759
28846
  commonRoutingTokens: overrides.commonRoutingTokens,
28760
28847
  nativeToken: overrides.nativeToken,
28848
+ wrappedNativeToken: overrides.wrappedNativeToken,
28761
28849
  };
28762
28850
  this.secondaryFees = secondaryFees || [];
28763
28851
  return;
@@ -28775,11 +28863,15 @@ class Exchange {
28775
28863
  router;
28776
28864
  chainId;
28777
28865
  nativeToken;
28866
+ wrappedNativeToken;
28778
28867
  secondaryFees;
28868
+ nativeTokenService;
28779
28869
  constructor(configuration) {
28780
28870
  const config = new ExchangeConfiguration(configuration);
28781
28871
  this.chainId = config.chain.chainId;
28782
28872
  this.nativeToken = config.chain.nativeToken;
28873
+ this.wrappedNativeToken = config.chain.wrappedNativeToken;
28874
+ this.nativeTokenService = new NativeTokenService(this.nativeToken, this.wrappedNativeToken);
28783
28875
  this.secondaryFees = config.secondaryFees;
28784
28876
  this.provider = new ethers.providers.JsonRpcProvider(config.chain.rpcUrl);
28785
28877
  this.router = new Router(this.provider, config.chain.commonRoutingTokens, {
@@ -28820,11 +28912,13 @@ class Exchange {
28820
28912
  this.getSecondaryFees(),
28821
28913
  ]);
28822
28914
  const tokenIn = {
28915
+ type: 'erc20',
28823
28916
  address: tokenInAddress,
28824
28917
  chainId: this.chainId,
28825
28918
  decimals: tokenInDecimals,
28826
28919
  };
28827
28920
  const tokenOut = {
28921
+ type: 'erc20',
28828
28922
  address: tokenOutAddress,
28829
28923
  chainId: this.chainId,
28830
28924
  decimals: tokenOutDecimals,
@@ -28834,18 +28928,18 @@ class Exchange {
28834
28928
  ? [tokenIn, tokenOut] : [tokenOut, tokenIn];
28835
28929
  const amountSpecified = newAmount(amount, tokenSpecified);
28836
28930
  const fees = new Fees(secondaryFees, tokenIn);
28837
- const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType);
28931
+ const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType, this.nativeTokenService);
28838
28932
  // get quote and gas details
28839
28933
  const [ourQuote, gasPrice] = await Promise.all([
28840
28934
  this.router.findOptimalRoute(ourQuoteReqAmount, otherToken, tradeType, maxHops),
28841
28935
  fetchGasPrice(this.provider, this.nativeToken),
28842
28936
  ]);
28843
28937
  const adjustedQuote = prepareSwap(ourQuote, amountSpecified, fees);
28844
- const swap = getSwap(adjustedQuote, fromAddress, slippagePercent, deadline, this.router.routingContracts.peripheryRouterAddress, this.router.routingContracts.secondaryFeeAddress, gasPrice, secondaryFees);
28938
+ const swap = getSwap(adjustedQuote, fromAddress, slippagePercent, deadline, this.router.routingContracts.peripheryRouterAddress, this.router.routingContracts.secondaryFeeAddress, gasPrice, secondaryFees, this.nativeTokenService);
28845
28939
  const userQuote = prepareUserQuote(otherToken, adjustedQuote, slippagePercent, fees);
28846
28940
  const preparedApproval = prepareApproval(tradeType, amountSpecified, userQuote.amountWithMaxSlippage, this.router.routingContracts, secondaryFees);
28847
28941
  // preparedApproval always uses the tokenIn address because we are always selling the tokenIn
28848
- const approval = await getApproval(this.provider, fromAddress, preparedApproval, gasPrice);
28942
+ const approval = await getApproval(this.provider, fromAddress, preparedApproval, gasPrice, this.nativeTokenService);
28849
28943
  return {
28850
28944
  approval,
28851
28945
  swap,
@@ -31023,8 +31117,6 @@ const $5e9bcae98dc8ff19$export$1165ca270f090a66 = (isDevelopment, isProduction)=
31023
31117
  return ($d85ad1457a3f1a83$export$89133ca13c5ee30)[(Environment$1).SANDBOX];
31024
31118
  };
31025
31119
  const checkDexAvailability = async ()=>{
31026
- // TEMP FIX: Returns true for sandbox environment
31027
- if (!isDevelopment && !isProduction) return true;
31028
31120
  let response;
31029
31121
  try {
31030
31122
  response = await (0, globalAxios$1).post(`${postEndpoint()}/v1/availability/checkout/swap`);
@@ -31189,7 +31281,7 @@ const $049bba630af05555$export$6946a1f17c2bbf26 = async (config, chainId, wallet
31189
31281
  const swappableToken = fromToken[index];
31190
31282
  dexQuotes.set(swappableToken, {
31191
31283
  quote: response.value.quote,
31192
- approval: response.value.approval?.gasFeeEstimate,
31284
+ approval: response.value.approval?.gasFeeEstimate ?? null,
31193
31285
  swap: response.value.swap.gasFeeEstimate
31194
31286
  });
31195
31287
  });
@@ -32901,9 +32993,6 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
32901
32993
  * Determines the requirements for performing a buy.
32902
32994
  * @param {BuyParams} params - The parameters for the buy.
32903
32995
  */ async buy(params) {
32904
- if (this.config.isProduction) throw new Error("This endpoint is not currently available.");
32905
- // eslint-disable-next-line no-console
32906
- console.warn("This endpoint is currently under construction.");
32907
32996
  if (params.orders.length > 1) // eslint-disable-next-line no-console
32908
32997
  console.warn("This endpoint currently only processes the first order in the array.");
32909
32998
  const web3Provider = await $bb88265fe45a0393$export$9e1fd9cc88c637a0(this.config, params.provider);
@@ -32915,9 +33004,6 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
32915
33004
  * Only currently actions the first order in the array until we support batch processing.
32916
33005
  * Only currently actions the first fee in the fees array of each order until we support multiple fees.
32917
33006
  */ async sell(params) {
32918
- if (this.config.isProduction) throw new Error("This endpoint is not currently available.");
32919
- // eslint-disable-next-line no-console
32920
- console.warn("This endpoint is currently under construction.");
32921
33007
  if (params.orders.length > 1) // eslint-disable-next-line no-console
32922
33008
  console.warn("This endpoint currently only processes the first order in the array.");
32923
33009
  const web3Provider = await $bb88265fe45a0393$export$9e1fd9cc88c637a0(this.config, params.provider);
@@ -32927,9 +33013,6 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
32927
33013
  * Cancels a sell.
32928
33014
  * @param {CancelParams} params - The parameters for the cancel.
32929
33015
  */ async cancel(params) {
32930
- if (this.config.isProduction) throw new Error("This endpoint is not currently available.");
32931
- // eslint-disable-next-line no-console
32932
- console.warn("This endpoint is currently under construction.");
32933
33016
  // eslint-disable-next-line no-console
32934
33017
  console.warn("This endpoint currently only processes the first order in the array.");
32935
33018
  const web3Provider = await $bb88265fe45a0393$export$9e1fd9cc88c637a0(this.config, params.provider);
@@ -32939,9 +33022,6 @@ class $a8cb37a3fc8eb863$export$1f60ba4ec72508a0 {
32939
33022
  * Determines the transaction requirements to complete a purchase.
32940
33023
  * @params {SmartCheckoutParams} params - The parameters for smart checkout.
32941
33024
  */ async smartCheckout(params) {
32942
- if (this.config.isProduction) throw new Error("This endpoint is not currently available.");
32943
- // eslint-disable-next-line no-console
32944
- console.warn("This endpoint is currently under construction.");
32945
33025
  const web3Provider = await $bb88265fe45a0393$export$9e1fd9cc88c637a0(this.config, params.provider);
32946
33026
  let itemRequirements = [];
32947
33027
  try {
@@ -33056,7 +33136,7 @@ var $045213b18e9f1f94$export$75be0f6af9650f2c;
33056
33136
  })($045213b18e9f1f94$export$75be0f6af9650f2c || ($045213b18e9f1f94$export$75be0f6af9650f2c = {}));
33057
33137
 
33058
33138
 
33059
- const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.6";
33139
+ const $d663162fd5a0853f$export$38a083d9fb5551ca = "0.27.8";
33060
33140
  const $d663162fd5a0853f$export$83bf90b30cdfd29f = ()=>false;
33061
33141
  const $d663162fd5a0853f$export$1169f5475725171b = ()=>$d663162fd5a0853f$export$38a083d9fb5551ca;
33062
33142
 
@@ -1327,12 +1327,19 @@ interface FulfillmentListing {
1327
1327
  listingId: string;
1328
1328
  takerFees: Array<FeeValue>;
1329
1329
  }
1330
- interface FulfillBulkOrdersResponse {
1330
+ type FulfillBulkOrdersResponse = FulfillBulkOrdersInsufficientBalanceResponse | FulfillBulkOrdersSufficientBalanceResponse;
1331
+ interface FulfillBulkOrdersSufficientBalanceResponse {
1332
+ sufficientBalance: true;
1331
1333
  actions: Action[];
1332
1334
  expiration: string;
1333
1335
  fulfillableOrders: Order[];
1334
1336
  unfulfillableOrders: UnfulfillableOrder[];
1335
1337
  }
1338
+ interface FulfillBulkOrdersInsufficientBalanceResponse {
1339
+ sufficientBalance: false;
1340
+ fulfillableOrders: Order[];
1341
+ unfulfillableOrders: UnfulfillableOrder[];
1342
+ }
1336
1343
  interface UnfulfillableOrder {
1337
1344
  orderId: string;
1338
1345
  reason: string;
@@ -1522,4 +1529,4 @@ declare const constants: {
1522
1529
  estimatedFulfillmentGasGwei: number;
1523
1530
  };
1524
1531
 
1525
- export { Action, ActionType, CancelOrderResponse, CreateListingParams, ERC20Item, ERC721Item, Fee, FeeType, FeeValue, FulfillBulkOrdersResponse, FulfillOrderResponse, FulfillmentListing, ListListingsParams, ListListingsResult, ListTradesParams, ListTradesResult, ListingResult, NativeItem, Order, OrderStatusName, Orderbook, Page, PrepareListingParams, PrepareListingResponse, RoyaltyInfo, SignableAction, SignablePurpose, Trade, TradeResult, TransactionAction, TransactionBuilder, TransactionPurpose, UnfulfillableOrder, constants };
1532
+ export { Action, ActionType, CancelOrderResponse, CreateListingParams, ERC20Item, ERC721Item, Fee, FeeType, FeeValue, FulfillBulkOrdersInsufficientBalanceResponse, FulfillBulkOrdersResponse, FulfillBulkOrdersSufficientBalanceResponse, FulfillOrderResponse, FulfillmentListing, ListListingsParams, ListListingsResult, ListTradesParams, ListTradesResult, ListingResult, NativeItem, Order, OrderStatusName, Orderbook, Page, PrepareListingParams, PrepareListingResponse, RoyaltyInfo, SignableAction, SignablePurpose, Trade, TradeResult, TransactionAction, TransactionBuilder, TransactionPurpose, UnfulfillableOrder, constants };
package/dist/orderbook.js CHANGED
@@ -1007,9 +1007,6 @@ class Seaport {
1007
1007
  };
1008
1008
  }
1009
1009
  async fulfillBulkOrders(fulfillingOrders, account) {
1010
- // TODO: this function right now does not handle errors from the seaport.js
1011
- // we should figure out why orders are rejected and return a submission
1012
- // transaction on best efforts basis
1013
1010
  const fulfillOrderDetails = fulfillingOrders.map((o) => {
1014
1011
  const { orderComponents, tips } = this.mapImmutableOrderToSeaportOrderComponents(o.order);
1015
1012
  return {
@@ -1428,14 +1425,34 @@ class Orderbook {
1428
1425
  recipient: fee.recipient,
1429
1426
  })),
1430
1427
  })));
1431
- return {
1432
- ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
1433
- fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
1434
- unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
1435
- orderId: o.order_id,
1436
- reason: o.reason,
1437
- })),
1438
- };
1428
+ try {
1429
+ return {
1430
+ ...(await this.seaport.fulfillBulkOrders(fulfillmentDataRes.result.fulfillable_orders, takerAddress)),
1431
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
1432
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
1433
+ orderId: o.order_id,
1434
+ reason: o.reason,
1435
+ })),
1436
+ sufficientBalance: true,
1437
+ };
1438
+ }
1439
+ catch (e) {
1440
+ // if insufficient balance error, we return FulfillBulkOrdersInsufficientBalanceResponse
1441
+ if (String(e).includes('The fulfiller does not have the balances needed to fulfill.')) {
1442
+ return {
1443
+ fulfillableOrders: fulfillmentDataRes.result.fulfillable_orders.map((o) => mapFromOpenApiOrder(o.order)),
1444
+ unfulfillableOrders: fulfillmentDataRes.result.unfulfillable_orders.map((o) => ({
1445
+ orderId: o.order_id,
1446
+ reason: o.reason,
1447
+ })),
1448
+ sufficientBalance: false,
1449
+ };
1450
+ }
1451
+ // if some other error is thrown,
1452
+ // there likely is a race condition of the original order validity
1453
+ // we throw the error back out
1454
+ throw e;
1455
+ }
1439
1456
  }
1440
1457
  /**
1441
1458
  * Get an unsigned cancel order transaction. Orders can only be cancelled by
package/dist/passport.js CHANGED
@@ -2072,7 +2072,7 @@ class MultiRollupApiClients {
2072
2072
  }
2073
2073
 
2074
2074
  // eslint-disable-next-line @typescript-eslint/naming-convention
2075
- const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.27.6' };
2075
+ const defaultHeaders = { 'x-sdk-version': 'ts-immutable-sdk-0.27.8' };
2076
2076
  const createConfig = ({ basePath, headers, }) => {
2077
2077
  if (!basePath.trim()) {
2078
2078
  throw Error('basePath can not be empty');
@@ -2128,7 +2128,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
2128
2128
  chainID,
2129
2129
  coreContractAddress,
2130
2130
  registrationContractAddress,
2131
- sdkVersion: 'ts-immutable-sdk-0.27.6',
2131
+ sdkVersion: 'ts-immutable-sdk-0.27.8',
2132
2132
  });
2133
2133
  /**
2134
2134
  * Sets `sdkVersion` at the time of build
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@imtbl/sdk",
3
3
  "description": "Immutable Unified SDK",
4
- "version": "0.27.6",
4
+ "version": "0.27.8",
5
5
  "author": "Immutable",
6
6
  "browser": "./dist/index.browser.js",
7
7
  "bugs": "https://github.com/immutable/ts-immutable-sdk/issues",