@imtbl/sdk 0.35.0 → 0.35.2
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/README.md +8 -10
- package/dist/blockchain_data.js +1 -1
- package/dist/browser/checkout/sdk.js +6 -6
- package/dist/browser/checkout/widgets.js +56 -56
- package/dist/checkout.js +69 -82
- package/dist/immutablex_client.js +1 -1
- package/dist/index.browser.js +12 -12
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cjs +72 -85
- package/dist/index.js +72 -85
- package/dist/passport.js +3 -3
- package/package.json +8 -1
package/dist/index.cjs
CHANGED
|
@@ -3791,7 +3791,7 @@ class MultiRollupApiClients {
|
|
|
3791
3791
|
}
|
|
3792
3792
|
|
|
3793
3793
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3794
|
-
const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.35.
|
|
3794
|
+
const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.35.2' };
|
|
3795
3795
|
const createConfig = ({ basePath, headers, }) => {
|
|
3796
3796
|
if (!basePath.trim()) {
|
|
3797
3797
|
throw Error('basePath can not be empty');
|
|
@@ -3851,7 +3851,7 @@ class APIError extends Error {
|
|
|
3851
3851
|
|
|
3852
3852
|
/* eslint-disable implicit-arrow-linebreak */
|
|
3853
3853
|
const defaultHeaders = {
|
|
3854
|
-
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.35.
|
|
3854
|
+
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.35.2',
|
|
3855
3855
|
};
|
|
3856
3856
|
/**
|
|
3857
3857
|
* createAPIConfiguration to create a custom Configuration
|
|
@@ -4262,7 +4262,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
|
|
|
4262
4262
|
chainID,
|
|
4263
4263
|
coreContractAddress,
|
|
4264
4264
|
registrationContractAddress,
|
|
4265
|
-
sdkVersion: 'ts-immutable-sdk-0.35.
|
|
4265
|
+
sdkVersion: 'ts-immutable-sdk-0.35.2',
|
|
4266
4266
|
});
|
|
4267
4267
|
/**
|
|
4268
4268
|
* Sets `sdkVersion` at the time of build
|
|
@@ -8790,7 +8790,7 @@ var ChainId$1;
|
|
|
8790
8790
|
(function (ChainId) {
|
|
8791
8791
|
ChainId[ChainId["IMTBL_ZKEVM_MAINNET"] = 13371] = "IMTBL_ZKEVM_MAINNET";
|
|
8792
8792
|
ChainId[ChainId["IMTBL_ZKEVM_TESTNET"] = 13473] = "IMTBL_ZKEVM_TESTNET";
|
|
8793
|
-
ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] =
|
|
8793
|
+
ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] = 15003] = "IMTBL_ZKEVM_DEVNET";
|
|
8794
8794
|
ChainId[ChainId["ETHEREUM"] = 1] = "ETHEREUM";
|
|
8795
8795
|
ChainId[ChainId["SEPOLIA"] = 11155111] = "SEPOLIA";
|
|
8796
8796
|
})(ChainId$1 || (ChainId$1 = {}));
|
|
@@ -28439,7 +28439,6 @@ class UniswapV3Pool__factory extends ethers.ContractFactory {
|
|
|
28439
28439
|
}
|
|
28440
28440
|
}
|
|
28441
28441
|
|
|
28442
|
-
const DEFAULT_GAS_QUOTE = 2000000;
|
|
28443
28442
|
// TODO: Better description of function and args
|
|
28444
28443
|
async function multicallSingleCallDataMultipleContracts(multicallContract, functionName, addresses) {
|
|
28445
28444
|
// Encode args - generate calldata for contract
|
|
@@ -28461,22 +28460,6 @@ async function multicallSingleCallDataMultipleContracts(multicallContract, funct
|
|
|
28461
28460
|
}
|
|
28462
28461
|
return multicallContract.callStatic.multicall(calls);
|
|
28463
28462
|
}
|
|
28464
|
-
// TODO: Better description of function and args
|
|
28465
|
-
async function multicallMultipleCallDataSingContract(multicallContract, calldata, address, options) {
|
|
28466
|
-
// Create call objects
|
|
28467
|
-
const calls = new Array(calldata.length);
|
|
28468
|
-
// TODO: use object.keys of something similar to avoid iterating over
|
|
28469
|
-
// entire object prototype
|
|
28470
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
28471
|
-
for (const i in calldata) {
|
|
28472
|
-
calls[i] = {
|
|
28473
|
-
target: address,
|
|
28474
|
-
callData: calldata[i],
|
|
28475
|
-
gasLimit: options?.gasRequired ?? DEFAULT_GAS_QUOTE,
|
|
28476
|
-
};
|
|
28477
|
-
}
|
|
28478
|
-
return multicallContract.callStatic.multicall(calls);
|
|
28479
|
-
}
|
|
28480
28463
|
const getCallData = (methodName, contractInterface) => {
|
|
28481
28464
|
// Create ethers function fragment
|
|
28482
28465
|
const fragment = contractInterface?.getFunction(methodName);
|
|
@@ -28636,35 +28619,27 @@ const getDefaultDeadlineSeconds = () => Math.floor(Date.now() / 1000) + DEFAULT_
|
|
|
28636
28619
|
|
|
28637
28620
|
const amountIndex = 0;
|
|
28638
28621
|
const gasEstimateIndex = 3;
|
|
28639
|
-
async function getQuotesForRoutes(
|
|
28640
|
-
const
|
|
28622
|
+
async function getQuotesForRoutes(provider, quoterContractAddress, routes, amountSpecified, tradeType) {
|
|
28623
|
+
const callDatas = routes.map((route) => v3Sdk.SwapQuoter.quoteCallParameters(route, toCurrencyAmount(amountSpecified), tradeType, {
|
|
28641
28624
|
useQuoterV2: true,
|
|
28642
28625
|
}).calldata);
|
|
28643
|
-
|
|
28644
|
-
|
|
28645
|
-
|
|
28646
|
-
|
|
28647
|
-
|
|
28648
|
-
|
|
28649
|
-
|
|
28650
|
-
}
|
|
28651
|
-
const decodedQuoteResults = [];
|
|
28652
|
-
// TODO: for..in loops iterate over the entire prototype chain,
|
|
28653
|
-
// Use Object.{keys,values,entries}, and iterate over the resulting array.
|
|
28654
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
28655
|
-
for (const i in quoteResults.returnData) {
|
|
28656
|
-
const functionSig = callData[i].substring(0, 10);
|
|
28626
|
+
const promises = await Promise.allSettled(callDatas.map((data) => provider.send('eth_call', [
|
|
28627
|
+
{ to: quoterContractAddress, data }, 'latest',
|
|
28628
|
+
])));
|
|
28629
|
+
const decodedQuoteResults = promises.reduce((quoteResults, promiseResult, i) => {
|
|
28630
|
+
if (promiseResult.status === 'rejected')
|
|
28631
|
+
return quoteResults;
|
|
28632
|
+
const functionSig = callDatas[i].substring(0, 10);
|
|
28657
28633
|
const returnTypes = quoteReturnMapping[functionSig];
|
|
28658
28634
|
if (!returnTypes) {
|
|
28659
28635
|
throw new Error('No quoting function signature found');
|
|
28660
28636
|
}
|
|
28661
|
-
if (
|
|
28637
|
+
if (promiseResult.value === '0x') {
|
|
28662
28638
|
// There is no quote result for the swap using this route, so don't include it in results
|
|
28663
|
-
|
|
28664
|
-
continue;
|
|
28639
|
+
return quoteResults;
|
|
28665
28640
|
}
|
|
28666
28641
|
try {
|
|
28667
|
-
const decodedQuoteResult = ethers.
|
|
28642
|
+
const decodedQuoteResult = ethers.utils.defaultAbiCoder.decode(returnTypes, promiseResult.value);
|
|
28668
28643
|
if (decodedQuoteResult) {
|
|
28669
28644
|
// The 0th element in each decoded data is going to be the amountOut or amountIn.
|
|
28670
28645
|
const quoteAmount = decodedQuoteResult[amountIndex];
|
|
@@ -28672,11 +28647,11 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
|
|
|
28672
28647
|
throw new Error('Expected BigNumber');
|
|
28673
28648
|
const input = uniswapTokenToERC20(routes[i].input);
|
|
28674
28649
|
const output = uniswapTokenToERC20(routes[i].output);
|
|
28675
|
-
|
|
28650
|
+
quoteResults.push({
|
|
28676
28651
|
route: routes[i],
|
|
28677
28652
|
amountIn: tradeType === Uniswap.TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, input),
|
|
28678
28653
|
amountOut: tradeType === Uniswap.TradeType.EXACT_INPUT ? newAmount(quoteAmount, output) : amountSpecified,
|
|
28679
|
-
gasEstimate: ethers.
|
|
28654
|
+
gasEstimate: ethers.BigNumber.from(decodedQuoteResult[gasEstimateIndex]),
|
|
28680
28655
|
tradeType,
|
|
28681
28656
|
});
|
|
28682
28657
|
}
|
|
@@ -28686,7 +28661,8 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
|
|
|
28686
28661
|
// Other quotes for routes may still succeed, so do nothing
|
|
28687
28662
|
// and continue processing
|
|
28688
28663
|
}
|
|
28689
|
-
|
|
28664
|
+
return quoteResults;
|
|
28665
|
+
}, new Array());
|
|
28690
28666
|
return decodedQuoteResults;
|
|
28691
28667
|
}
|
|
28692
28668
|
|
|
@@ -28814,19 +28790,24 @@ const fetchValidPools = async (multicallContract, erc20Pair, commonRoutingERC20s
|
|
|
28814
28790
|
|
|
28815
28791
|
class Router {
|
|
28816
28792
|
provider;
|
|
28793
|
+
multicallContract;
|
|
28817
28794
|
routingTokens;
|
|
28818
28795
|
routingContracts;
|
|
28819
|
-
constructor(provider, routingTokens, routingContracts) {
|
|
28796
|
+
constructor(provider, multicallContract, routingTokens, routingContracts) {
|
|
28820
28797
|
this.provider = provider;
|
|
28798
|
+
this.multicallContract = multicallContract;
|
|
28799
|
+
this.routingTokens = routingTokens;
|
|
28800
|
+
this.routingContracts = routingContracts;
|
|
28801
|
+
this.provider = provider;
|
|
28802
|
+
this.multicallContract = multicallContract;
|
|
28821
28803
|
this.routingTokens = routingTokens;
|
|
28822
28804
|
this.routingContracts = routingContracts;
|
|
28823
28805
|
}
|
|
28824
28806
|
async findOptimalRoute(amountSpecified, otherToken, tradeType, maxHops = 2) {
|
|
28825
28807
|
const [tokenIn, tokenOut] = this.determineERC20InAndERC20Out(tradeType, amountSpecified, otherToken);
|
|
28826
|
-
const multicallContract = Multicall__factory.connect(this.routingContracts.multicallAddress, this.provider);
|
|
28827
28808
|
const erc20Pair = [tokenIn, tokenOut];
|
|
28828
28809
|
// Get all pools and use these to get all possible routes.
|
|
28829
|
-
const pools = await fetchValidPools(multicallContract, erc20Pair, this.routingTokens, this.routingContracts.
|
|
28810
|
+
const pools = await fetchValidPools(this.multicallContract, erc20Pair, this.routingTokens, this.routingContracts.coreFactory);
|
|
28830
28811
|
const noValidPools = pools.length === 0;
|
|
28831
28812
|
if (noValidPools) {
|
|
28832
28813
|
throw new NoRoutesAvailableError();
|
|
@@ -28840,10 +28821,10 @@ class Router {
|
|
|
28840
28821
|
throw new NoRoutesAvailableError();
|
|
28841
28822
|
}
|
|
28842
28823
|
// Get the best quote from all of the given routes
|
|
28843
|
-
return await this.getBestQuoteFromRoutes(
|
|
28824
|
+
return await this.getBestQuoteFromRoutes(routes, amountSpecified, tradeType);
|
|
28844
28825
|
}
|
|
28845
|
-
async getBestQuoteFromRoutes(
|
|
28846
|
-
const quotes = await getQuotesForRoutes(
|
|
28826
|
+
async getBestQuoteFromRoutes(routes, amountSpecified, tradeType) {
|
|
28827
|
+
const quotes = await getQuotesForRoutes(this.provider, this.routingContracts.quoterV2, routes, amountSpecified, tradeType);
|
|
28847
28828
|
if (quotes.length === 0) {
|
|
28848
28829
|
throw new NoRoutesAvailableError();
|
|
28849
28830
|
}
|
|
@@ -28919,36 +28900,38 @@ startTokenIn = tokenIn) => {
|
|
|
28919
28900
|
return routes;
|
|
28920
28901
|
};
|
|
28921
28902
|
|
|
28922
|
-
|
|
28923
|
-
|
|
28924
|
-
|
|
28925
|
-
|
|
28926
|
-
|
|
28927
|
-
|
|
28928
|
-
|
|
28929
|
-
|
|
28930
|
-
|
|
28903
|
+
const getFeeData = async (provider) => {
|
|
28904
|
+
const [block, maxPriorityFeePerGas] = await Promise.all([
|
|
28905
|
+
provider.getBlock('latest'),
|
|
28906
|
+
provider.send('eth_maxPriorityFeePerGas', []),
|
|
28907
|
+
]);
|
|
28908
|
+
if (!block.baseFeePerGas)
|
|
28909
|
+
throw new Error('Base fee per gas not found in block');
|
|
28910
|
+
return {
|
|
28911
|
+
// https://www.blocknative.com/blog/eip-1559-fees
|
|
28912
|
+
maxFeePerGas: block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas),
|
|
28913
|
+
maxPriorityFeePerGas,
|
|
28914
|
+
lastBaseFeePerGas: block.baseFeePerGas,
|
|
28915
|
+
};
|
|
28931
28916
|
};
|
|
28932
28917
|
/**
|
|
28933
28918
|
* Fetch the current gas price estimate. Supports both EIP-1559 and non-EIP1559 chains
|
|
28934
|
-
* @param {
|
|
28919
|
+
* @param {Provider} provider - The JSON RPC provider used to fetch fee data
|
|
28935
28920
|
* @param {Native} nativeToken - The native token of the chain. Gas prices will be denominated in this token
|
|
28936
|
-
* @returns {
|
|
28921
|
+
* @returns {CoinAmount<Native> | null} - The gas price in the smallest denomination of the chain's currency,
|
|
28937
28922
|
* or null if no gas price is available
|
|
28938
28923
|
*/
|
|
28924
|
+
// eslint-disable-next-line max-len
|
|
28939
28925
|
const fetchGasPrice = async (provider, nativeToken) => {
|
|
28940
|
-
const feeData = await
|
|
28926
|
+
const feeData = await getFeeData(provider).catch(() => null);
|
|
28941
28927
|
if (!feeData)
|
|
28942
28928
|
return null;
|
|
28943
|
-
|
|
28944
|
-
return newAmount(feeData.maxFeePerGas.add(feeData.maxPriorityFeePerGas), nativeToken);
|
|
28945
|
-
}
|
|
28946
|
-
return feeData.gasPrice ? newAmount(feeData.gasPrice, nativeToken) : null;
|
|
28929
|
+
return newAmount(feeData.maxFeePerGas, nativeToken);
|
|
28947
28930
|
};
|
|
28948
28931
|
/**
|
|
28949
28932
|
* Calculate the gas fee from the gas price and gas units used for the transaction
|
|
28950
28933
|
*
|
|
28951
|
-
* @param {
|
|
28934
|
+
* @param {CoinAmount<Native>} gasPrice - The price of gas
|
|
28952
28935
|
* @param {BigNumber} gasEstimate - The total gas units that will be used for the transaction
|
|
28953
28936
|
* @returns - The cost of the transaction in the gas token's smallest denomination (e.g. WEI)
|
|
28954
28937
|
*/
|
|
@@ -29572,6 +29555,7 @@ const toPublicQuote = (amount, amountWithMaxSlippage, slippage, fees) => ({
|
|
|
29572
29555
|
});
|
|
29573
29556
|
class Exchange {
|
|
29574
29557
|
provider;
|
|
29558
|
+
batchProvider;
|
|
29575
29559
|
router;
|
|
29576
29560
|
chainId;
|
|
29577
29561
|
nativeToken;
|
|
@@ -29589,12 +29573,16 @@ class Exchange {
|
|
|
29589
29573
|
this.secondaryFees = config.secondaryFees;
|
|
29590
29574
|
this.routerContractAddress = config.chain.contracts.peripheryRouter;
|
|
29591
29575
|
this.secondaryFeeContractAddress = config.chain.contracts.secondaryFee;
|
|
29592
|
-
this.provider = new ethers.ethers.providers.
|
|
29593
|
-
|
|
29594
|
-
|
|
29595
|
-
|
|
29596
|
-
|
|
29597
|
-
|
|
29576
|
+
this.provider = new ethers.ethers.providers.StaticJsonRpcProvider({
|
|
29577
|
+
url: config.chain.rpcUrl,
|
|
29578
|
+
skipFetchSetup: true,
|
|
29579
|
+
}, config.chain.chainId);
|
|
29580
|
+
this.batchProvider = new ethers.ethers.providers.JsonRpcBatchProvider({
|
|
29581
|
+
url: config.chain.rpcUrl,
|
|
29582
|
+
skipFetchSetup: true,
|
|
29583
|
+
}, config.chain.chainId);
|
|
29584
|
+
const multicallContract = Multicall__factory.connect(config.chain.contracts.multicall, this.provider);
|
|
29585
|
+
this.router = new Router(this.batchProvider, multicallContract, config.chain.commonRoutingTokens, config.chain.contracts);
|
|
29598
29586
|
}
|
|
29599
29587
|
static validate(tokenInAddress, tokenOutAddress, maxHops, slippagePercent, fromAddress) {
|
|
29600
29588
|
assert(isValidNonZeroAddress(fromAddress), new InvalidAddressError('invalid from address'));
|
|
@@ -29606,11 +29594,11 @@ class Exchange {
|
|
|
29606
29594
|
assert(slippagePercent <= 50, new InvalidSlippageError('slippage percent must be less than or equal to 50'));
|
|
29607
29595
|
assert(slippagePercent >= 0, new InvalidSlippageError('slippage percent must be greater than or equal to 0'));
|
|
29608
29596
|
}
|
|
29609
|
-
async getSecondaryFees() {
|
|
29597
|
+
async getSecondaryFees(provider) {
|
|
29610
29598
|
if (this.secondaryFees.length === 0) {
|
|
29611
29599
|
return [];
|
|
29612
29600
|
}
|
|
29613
|
-
const secondaryFeeContract = SecondaryFee__factory.connect(this.secondaryFeeContractAddress,
|
|
29601
|
+
const secondaryFeeContract = SecondaryFee__factory.connect(this.secondaryFeeContractAddress, provider);
|
|
29614
29602
|
if (await secondaryFeeContract.paused()) {
|
|
29615
29603
|
// Do not use secondary fees if the contract is paused
|
|
29616
29604
|
return [];
|
|
@@ -29631,11 +29619,13 @@ class Exchange {
|
|
|
29631
29619
|
async getUnsignedSwapTx(fromAddress, tokenInLiteral, tokenOutLiteral, amount, slippagePercent, maxHops, deadline, tradeType) {
|
|
29632
29620
|
Exchange.validate(tokenInLiteral, tokenOutLiteral, maxHops, slippagePercent, fromAddress);
|
|
29633
29621
|
// get the decimals of the tokens that will be swapped
|
|
29634
|
-
const
|
|
29635
|
-
getTokenDecimals(tokenInLiteral, this.
|
|
29636
|
-
getTokenDecimals(tokenOutLiteral, this.
|
|
29637
|
-
this.getSecondaryFees(),
|
|
29638
|
-
|
|
29622
|
+
const promises = [
|
|
29623
|
+
getTokenDecimals(tokenInLiteral, this.batchProvider, this.nativeToken),
|
|
29624
|
+
getTokenDecimals(tokenOutLiteral, this.batchProvider, this.nativeToken),
|
|
29625
|
+
this.getSecondaryFees(this.batchProvider),
|
|
29626
|
+
fetchGasPrice(this.batchProvider, this.nativeToken),
|
|
29627
|
+
];
|
|
29628
|
+
const [tokenInDecimals, tokenOutDecimals, secondaryFees, gasPrice] = await Promise.all(promises);
|
|
29639
29629
|
const tokenIn = this.parseTokenLiteral(tokenInLiteral, tokenInDecimals);
|
|
29640
29630
|
const tokenOut = this.parseTokenLiteral(tokenOutLiteral, tokenOutDecimals);
|
|
29641
29631
|
// determine which amount was specified for the swap from the TradeType
|
|
@@ -29644,10 +29634,7 @@ class Exchange {
|
|
|
29644
29634
|
const fees = new Fees(secondaryFees, tokenIn);
|
|
29645
29635
|
const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType, this.nativeTokenService);
|
|
29646
29636
|
// Quotes will always use ERC20s. If the user-specified token is Native, we use the Wrapped Native Token pool
|
|
29647
|
-
const
|
|
29648
|
-
this.router.findOptimalRoute(ourQuoteReqAmount, this.nativeTokenService.maybeWrapToken(otherToken), tradeType, maxHops),
|
|
29649
|
-
fetchGasPrice(this.provider, this.nativeToken),
|
|
29650
|
-
]);
|
|
29637
|
+
const ourQuote = await this.router.findOptimalRoute(ourQuoteReqAmount, this.nativeTokenService.maybeWrapToken(otherToken), tradeType, maxHops);
|
|
29651
29638
|
const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
|
|
29652
29639
|
const swap = getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
|
|
29653
29640
|
const { quotedAmount, quotedAmountWithMaxSlippage } = prepareUserQuote(this.nativeTokenService, adjustedQuote, slippagePercent, otherToken);
|
|
@@ -30584,7 +30571,7 @@ const GAS_OVERRIDES = {
|
|
|
30584
30571
|
maxPriorityFeePerGas: ethers.BigNumber.from(101e9),
|
|
30585
30572
|
};
|
|
30586
30573
|
|
|
30587
|
-
const SDK_VERSION_MARKER = '0.35.
|
|
30574
|
+
const SDK_VERSION_MARKER = '0.35.2';
|
|
30588
30575
|
// This SDK version is replaced by the `yarn build` command ran on the root level
|
|
30589
30576
|
const globalPackageVersion = () => SDK_VERSION_MARKER;
|
|
30590
30577
|
|
package/dist/index.js
CHANGED
|
@@ -3769,7 +3769,7 @@ class MultiRollupApiClients {
|
|
|
3769
3769
|
}
|
|
3770
3770
|
|
|
3771
3771
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
3772
|
-
const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.35.
|
|
3772
|
+
const defaultHeaders$1 = { 'x-sdk-version': 'ts-immutable-sdk-0.35.2' };
|
|
3773
3773
|
const createConfig = ({ basePath, headers, }) => {
|
|
3774
3774
|
if (!basePath.trim()) {
|
|
3775
3775
|
throw Error('basePath can not be empty');
|
|
@@ -3829,7 +3829,7 @@ class APIError extends Error {
|
|
|
3829
3829
|
|
|
3830
3830
|
/* eslint-disable implicit-arrow-linebreak */
|
|
3831
3831
|
const defaultHeaders = {
|
|
3832
|
-
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.35.
|
|
3832
|
+
sdkVersion: 'ts-immutable-sdk-multi-rollup-api-client-0.35.2',
|
|
3833
3833
|
};
|
|
3834
3834
|
/**
|
|
3835
3835
|
* createAPIConfiguration to create a custom Configuration
|
|
@@ -4240,7 +4240,7 @@ const createImmutableXConfiguration = ({ basePath, chainID, coreContractAddress,
|
|
|
4240
4240
|
chainID,
|
|
4241
4241
|
coreContractAddress,
|
|
4242
4242
|
registrationContractAddress,
|
|
4243
|
-
sdkVersion: 'ts-immutable-sdk-0.35.
|
|
4243
|
+
sdkVersion: 'ts-immutable-sdk-0.35.2',
|
|
4244
4244
|
});
|
|
4245
4245
|
/**
|
|
4246
4246
|
* Sets `sdkVersion` at the time of build
|
|
@@ -8768,7 +8768,7 @@ var ChainId$1;
|
|
|
8768
8768
|
(function (ChainId) {
|
|
8769
8769
|
ChainId[ChainId["IMTBL_ZKEVM_MAINNET"] = 13371] = "IMTBL_ZKEVM_MAINNET";
|
|
8770
8770
|
ChainId[ChainId["IMTBL_ZKEVM_TESTNET"] = 13473] = "IMTBL_ZKEVM_TESTNET";
|
|
8771
|
-
ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] =
|
|
8771
|
+
ChainId[ChainId["IMTBL_ZKEVM_DEVNET"] = 15003] = "IMTBL_ZKEVM_DEVNET";
|
|
8772
8772
|
ChainId[ChainId["ETHEREUM"] = 1] = "ETHEREUM";
|
|
8773
8773
|
ChainId[ChainId["SEPOLIA"] = 11155111] = "SEPOLIA";
|
|
8774
8774
|
})(ChainId$1 || (ChainId$1 = {}));
|
|
@@ -28417,7 +28417,6 @@ class UniswapV3Pool__factory extends ContractFactory {
|
|
|
28417
28417
|
}
|
|
28418
28418
|
}
|
|
28419
28419
|
|
|
28420
|
-
const DEFAULT_GAS_QUOTE = 2000000;
|
|
28421
28420
|
// TODO: Better description of function and args
|
|
28422
28421
|
async function multicallSingleCallDataMultipleContracts(multicallContract, functionName, addresses) {
|
|
28423
28422
|
// Encode args - generate calldata for contract
|
|
@@ -28439,22 +28438,6 @@ async function multicallSingleCallDataMultipleContracts(multicallContract, funct
|
|
|
28439
28438
|
}
|
|
28440
28439
|
return multicallContract.callStatic.multicall(calls);
|
|
28441
28440
|
}
|
|
28442
|
-
// TODO: Better description of function and args
|
|
28443
|
-
async function multicallMultipleCallDataSingContract(multicallContract, calldata, address, options) {
|
|
28444
|
-
// Create call objects
|
|
28445
|
-
const calls = new Array(calldata.length);
|
|
28446
|
-
// TODO: use object.keys of something similar to avoid iterating over
|
|
28447
|
-
// entire object prototype
|
|
28448
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
28449
|
-
for (const i in calldata) {
|
|
28450
|
-
calls[i] = {
|
|
28451
|
-
target: address,
|
|
28452
|
-
callData: calldata[i],
|
|
28453
|
-
gasLimit: options?.gasRequired ?? DEFAULT_GAS_QUOTE,
|
|
28454
|
-
};
|
|
28455
|
-
}
|
|
28456
|
-
return multicallContract.callStatic.multicall(calls);
|
|
28457
|
-
}
|
|
28458
28441
|
const getCallData = (methodName, contractInterface) => {
|
|
28459
28442
|
// Create ethers function fragment
|
|
28460
28443
|
const fragment = contractInterface?.getFunction(methodName);
|
|
@@ -28614,35 +28597,27 @@ const getDefaultDeadlineSeconds = () => Math.floor(Date.now() / 1000) + DEFAULT_
|
|
|
28614
28597
|
|
|
28615
28598
|
const amountIndex = 0;
|
|
28616
28599
|
const gasEstimateIndex = 3;
|
|
28617
|
-
async function getQuotesForRoutes(
|
|
28618
|
-
const
|
|
28600
|
+
async function getQuotesForRoutes(provider, quoterContractAddress, routes, amountSpecified, tradeType) {
|
|
28601
|
+
const callDatas = routes.map((route) => SwapQuoter.quoteCallParameters(route, toCurrencyAmount(amountSpecified), tradeType, {
|
|
28619
28602
|
useQuoterV2: true,
|
|
28620
28603
|
}).calldata);
|
|
28621
|
-
|
|
28622
|
-
|
|
28623
|
-
|
|
28624
|
-
|
|
28625
|
-
|
|
28626
|
-
|
|
28627
|
-
|
|
28628
|
-
}
|
|
28629
|
-
const decodedQuoteResults = [];
|
|
28630
|
-
// TODO: for..in loops iterate over the entire prototype chain,
|
|
28631
|
-
// Use Object.{keys,values,entries}, and iterate over the resulting array.
|
|
28632
|
-
// eslint-disable-next-line no-restricted-syntax, guard-for-in
|
|
28633
|
-
for (const i in quoteResults.returnData) {
|
|
28634
|
-
const functionSig = callData[i].substring(0, 10);
|
|
28604
|
+
const promises = await Promise.allSettled(callDatas.map((data) => provider.send('eth_call', [
|
|
28605
|
+
{ to: quoterContractAddress, data }, 'latest',
|
|
28606
|
+
])));
|
|
28607
|
+
const decodedQuoteResults = promises.reduce((quoteResults, promiseResult, i) => {
|
|
28608
|
+
if (promiseResult.status === 'rejected')
|
|
28609
|
+
return quoteResults;
|
|
28610
|
+
const functionSig = callDatas[i].substring(0, 10);
|
|
28635
28611
|
const returnTypes = quoteReturnMapping[functionSig];
|
|
28636
28612
|
if (!returnTypes) {
|
|
28637
28613
|
throw new Error('No quoting function signature found');
|
|
28638
28614
|
}
|
|
28639
|
-
if (
|
|
28615
|
+
if (promiseResult.value === '0x') {
|
|
28640
28616
|
// There is no quote result for the swap using this route, so don't include it in results
|
|
28641
|
-
|
|
28642
|
-
continue;
|
|
28617
|
+
return quoteResults;
|
|
28643
28618
|
}
|
|
28644
28619
|
try {
|
|
28645
|
-
const decodedQuoteResult =
|
|
28620
|
+
const decodedQuoteResult = utils$1.defaultAbiCoder.decode(returnTypes, promiseResult.value);
|
|
28646
28621
|
if (decodedQuoteResult) {
|
|
28647
28622
|
// The 0th element in each decoded data is going to be the amountOut or amountIn.
|
|
28648
28623
|
const quoteAmount = decodedQuoteResult[amountIndex];
|
|
@@ -28650,11 +28625,11 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
|
|
|
28650
28625
|
throw new Error('Expected BigNumber');
|
|
28651
28626
|
const input = uniswapTokenToERC20(routes[i].input);
|
|
28652
28627
|
const output = uniswapTokenToERC20(routes[i].output);
|
|
28653
|
-
|
|
28628
|
+
quoteResults.push({
|
|
28654
28629
|
route: routes[i],
|
|
28655
28630
|
amountIn: tradeType === TradeType.EXACT_INPUT ? amountSpecified : newAmount(quoteAmount, input),
|
|
28656
28631
|
amountOut: tradeType === TradeType.EXACT_INPUT ? newAmount(quoteAmount, output) : amountSpecified,
|
|
28657
|
-
gasEstimate:
|
|
28632
|
+
gasEstimate: BigNumber$1.from(decodedQuoteResult[gasEstimateIndex]),
|
|
28658
28633
|
tradeType,
|
|
28659
28634
|
});
|
|
28660
28635
|
}
|
|
@@ -28664,7 +28639,8 @@ async function getQuotesForRoutes(multicallContract, quoterContractAddress, rout
|
|
|
28664
28639
|
// Other quotes for routes may still succeed, so do nothing
|
|
28665
28640
|
// and continue processing
|
|
28666
28641
|
}
|
|
28667
|
-
|
|
28642
|
+
return quoteResults;
|
|
28643
|
+
}, new Array());
|
|
28668
28644
|
return decodedQuoteResults;
|
|
28669
28645
|
}
|
|
28670
28646
|
|
|
@@ -28792,19 +28768,24 @@ const fetchValidPools = async (multicallContract, erc20Pair, commonRoutingERC20s
|
|
|
28792
28768
|
|
|
28793
28769
|
class Router {
|
|
28794
28770
|
provider;
|
|
28771
|
+
multicallContract;
|
|
28795
28772
|
routingTokens;
|
|
28796
28773
|
routingContracts;
|
|
28797
|
-
constructor(provider, routingTokens, routingContracts) {
|
|
28774
|
+
constructor(provider, multicallContract, routingTokens, routingContracts) {
|
|
28798
28775
|
this.provider = provider;
|
|
28776
|
+
this.multicallContract = multicallContract;
|
|
28777
|
+
this.routingTokens = routingTokens;
|
|
28778
|
+
this.routingContracts = routingContracts;
|
|
28779
|
+
this.provider = provider;
|
|
28780
|
+
this.multicallContract = multicallContract;
|
|
28799
28781
|
this.routingTokens = routingTokens;
|
|
28800
28782
|
this.routingContracts = routingContracts;
|
|
28801
28783
|
}
|
|
28802
28784
|
async findOptimalRoute(amountSpecified, otherToken, tradeType, maxHops = 2) {
|
|
28803
28785
|
const [tokenIn, tokenOut] = this.determineERC20InAndERC20Out(tradeType, amountSpecified, otherToken);
|
|
28804
|
-
const multicallContract = Multicall__factory.connect(this.routingContracts.multicallAddress, this.provider);
|
|
28805
28786
|
const erc20Pair = [tokenIn, tokenOut];
|
|
28806
28787
|
// Get all pools and use these to get all possible routes.
|
|
28807
|
-
const pools = await fetchValidPools(multicallContract, erc20Pair, this.routingTokens, this.routingContracts.
|
|
28788
|
+
const pools = await fetchValidPools(this.multicallContract, erc20Pair, this.routingTokens, this.routingContracts.coreFactory);
|
|
28808
28789
|
const noValidPools = pools.length === 0;
|
|
28809
28790
|
if (noValidPools) {
|
|
28810
28791
|
throw new NoRoutesAvailableError();
|
|
@@ -28818,10 +28799,10 @@ class Router {
|
|
|
28818
28799
|
throw new NoRoutesAvailableError();
|
|
28819
28800
|
}
|
|
28820
28801
|
// Get the best quote from all of the given routes
|
|
28821
|
-
return await this.getBestQuoteFromRoutes(
|
|
28802
|
+
return await this.getBestQuoteFromRoutes(routes, amountSpecified, tradeType);
|
|
28822
28803
|
}
|
|
28823
|
-
async getBestQuoteFromRoutes(
|
|
28824
|
-
const quotes = await getQuotesForRoutes(
|
|
28804
|
+
async getBestQuoteFromRoutes(routes, amountSpecified, tradeType) {
|
|
28805
|
+
const quotes = await getQuotesForRoutes(this.provider, this.routingContracts.quoterV2, routes, amountSpecified, tradeType);
|
|
28825
28806
|
if (quotes.length === 0) {
|
|
28826
28807
|
throw new NoRoutesAvailableError();
|
|
28827
28808
|
}
|
|
@@ -28897,36 +28878,38 @@ startTokenIn = tokenIn) => {
|
|
|
28897
28878
|
return routes;
|
|
28898
28879
|
};
|
|
28899
28880
|
|
|
28900
|
-
|
|
28901
|
-
|
|
28902
|
-
|
|
28903
|
-
|
|
28904
|
-
|
|
28905
|
-
|
|
28906
|
-
|
|
28907
|
-
|
|
28908
|
-
|
|
28881
|
+
const getFeeData = async (provider) => {
|
|
28882
|
+
const [block, maxPriorityFeePerGas] = await Promise.all([
|
|
28883
|
+
provider.getBlock('latest'),
|
|
28884
|
+
provider.send('eth_maxPriorityFeePerGas', []),
|
|
28885
|
+
]);
|
|
28886
|
+
if (!block.baseFeePerGas)
|
|
28887
|
+
throw new Error('Base fee per gas not found in block');
|
|
28888
|
+
return {
|
|
28889
|
+
// https://www.blocknative.com/blog/eip-1559-fees
|
|
28890
|
+
maxFeePerGas: block.baseFeePerGas.mul(2).add(maxPriorityFeePerGas),
|
|
28891
|
+
maxPriorityFeePerGas,
|
|
28892
|
+
lastBaseFeePerGas: block.baseFeePerGas,
|
|
28893
|
+
};
|
|
28909
28894
|
};
|
|
28910
28895
|
/**
|
|
28911
28896
|
* Fetch the current gas price estimate. Supports both EIP-1559 and non-EIP1559 chains
|
|
28912
|
-
* @param {
|
|
28897
|
+
* @param {Provider} provider - The JSON RPC provider used to fetch fee data
|
|
28913
28898
|
* @param {Native} nativeToken - The native token of the chain. Gas prices will be denominated in this token
|
|
28914
|
-
* @returns {
|
|
28899
|
+
* @returns {CoinAmount<Native> | null} - The gas price in the smallest denomination of the chain's currency,
|
|
28915
28900
|
* or null if no gas price is available
|
|
28916
28901
|
*/
|
|
28902
|
+
// eslint-disable-next-line max-len
|
|
28917
28903
|
const fetchGasPrice = async (provider, nativeToken) => {
|
|
28918
|
-
const feeData = await
|
|
28904
|
+
const feeData = await getFeeData(provider).catch(() => null);
|
|
28919
28905
|
if (!feeData)
|
|
28920
28906
|
return null;
|
|
28921
|
-
|
|
28922
|
-
return newAmount(feeData.maxFeePerGas.add(feeData.maxPriorityFeePerGas), nativeToken);
|
|
28923
|
-
}
|
|
28924
|
-
return feeData.gasPrice ? newAmount(feeData.gasPrice, nativeToken) : null;
|
|
28907
|
+
return newAmount(feeData.maxFeePerGas, nativeToken);
|
|
28925
28908
|
};
|
|
28926
28909
|
/**
|
|
28927
28910
|
* Calculate the gas fee from the gas price and gas units used for the transaction
|
|
28928
28911
|
*
|
|
28929
|
-
* @param {
|
|
28912
|
+
* @param {CoinAmount<Native>} gasPrice - The price of gas
|
|
28930
28913
|
* @param {BigNumber} gasEstimate - The total gas units that will be used for the transaction
|
|
28931
28914
|
* @returns - The cost of the transaction in the gas token's smallest denomination (e.g. WEI)
|
|
28932
28915
|
*/
|
|
@@ -29550,6 +29533,7 @@ const toPublicQuote = (amount, amountWithMaxSlippage, slippage, fees) => ({
|
|
|
29550
29533
|
});
|
|
29551
29534
|
class Exchange {
|
|
29552
29535
|
provider;
|
|
29536
|
+
batchProvider;
|
|
29553
29537
|
router;
|
|
29554
29538
|
chainId;
|
|
29555
29539
|
nativeToken;
|
|
@@ -29567,12 +29551,16 @@ class Exchange {
|
|
|
29567
29551
|
this.secondaryFees = config.secondaryFees;
|
|
29568
29552
|
this.routerContractAddress = config.chain.contracts.peripheryRouter;
|
|
29569
29553
|
this.secondaryFeeContractAddress = config.chain.contracts.secondaryFee;
|
|
29570
|
-
this.provider = new ethers.providers.
|
|
29571
|
-
|
|
29572
|
-
|
|
29573
|
-
|
|
29574
|
-
|
|
29575
|
-
|
|
29554
|
+
this.provider = new ethers.providers.StaticJsonRpcProvider({
|
|
29555
|
+
url: config.chain.rpcUrl,
|
|
29556
|
+
skipFetchSetup: true,
|
|
29557
|
+
}, config.chain.chainId);
|
|
29558
|
+
this.batchProvider = new ethers.providers.JsonRpcBatchProvider({
|
|
29559
|
+
url: config.chain.rpcUrl,
|
|
29560
|
+
skipFetchSetup: true,
|
|
29561
|
+
}, config.chain.chainId);
|
|
29562
|
+
const multicallContract = Multicall__factory.connect(config.chain.contracts.multicall, this.provider);
|
|
29563
|
+
this.router = new Router(this.batchProvider, multicallContract, config.chain.commonRoutingTokens, config.chain.contracts);
|
|
29576
29564
|
}
|
|
29577
29565
|
static validate(tokenInAddress, tokenOutAddress, maxHops, slippagePercent, fromAddress) {
|
|
29578
29566
|
assert(isValidNonZeroAddress(fromAddress), new InvalidAddressError('invalid from address'));
|
|
@@ -29584,11 +29572,11 @@ class Exchange {
|
|
|
29584
29572
|
assert(slippagePercent <= 50, new InvalidSlippageError('slippage percent must be less than or equal to 50'));
|
|
29585
29573
|
assert(slippagePercent >= 0, new InvalidSlippageError('slippage percent must be greater than or equal to 0'));
|
|
29586
29574
|
}
|
|
29587
|
-
async getSecondaryFees() {
|
|
29575
|
+
async getSecondaryFees(provider) {
|
|
29588
29576
|
if (this.secondaryFees.length === 0) {
|
|
29589
29577
|
return [];
|
|
29590
29578
|
}
|
|
29591
|
-
const secondaryFeeContract = SecondaryFee__factory.connect(this.secondaryFeeContractAddress,
|
|
29579
|
+
const secondaryFeeContract = SecondaryFee__factory.connect(this.secondaryFeeContractAddress, provider);
|
|
29592
29580
|
if (await secondaryFeeContract.paused()) {
|
|
29593
29581
|
// Do not use secondary fees if the contract is paused
|
|
29594
29582
|
return [];
|
|
@@ -29609,11 +29597,13 @@ class Exchange {
|
|
|
29609
29597
|
async getUnsignedSwapTx(fromAddress, tokenInLiteral, tokenOutLiteral, amount, slippagePercent, maxHops, deadline, tradeType) {
|
|
29610
29598
|
Exchange.validate(tokenInLiteral, tokenOutLiteral, maxHops, slippagePercent, fromAddress);
|
|
29611
29599
|
// get the decimals of the tokens that will be swapped
|
|
29612
|
-
const
|
|
29613
|
-
getTokenDecimals(tokenInLiteral, this.
|
|
29614
|
-
getTokenDecimals(tokenOutLiteral, this.
|
|
29615
|
-
this.getSecondaryFees(),
|
|
29616
|
-
|
|
29600
|
+
const promises = [
|
|
29601
|
+
getTokenDecimals(tokenInLiteral, this.batchProvider, this.nativeToken),
|
|
29602
|
+
getTokenDecimals(tokenOutLiteral, this.batchProvider, this.nativeToken),
|
|
29603
|
+
this.getSecondaryFees(this.batchProvider),
|
|
29604
|
+
fetchGasPrice(this.batchProvider, this.nativeToken),
|
|
29605
|
+
];
|
|
29606
|
+
const [tokenInDecimals, tokenOutDecimals, secondaryFees, gasPrice] = await Promise.all(promises);
|
|
29617
29607
|
const tokenIn = this.parseTokenLiteral(tokenInLiteral, tokenInDecimals);
|
|
29618
29608
|
const tokenOut = this.parseTokenLiteral(tokenOutLiteral, tokenOutDecimals);
|
|
29619
29609
|
// determine which amount was specified for the swap from the TradeType
|
|
@@ -29622,10 +29612,7 @@ class Exchange {
|
|
|
29622
29612
|
const fees = new Fees(secondaryFees, tokenIn);
|
|
29623
29613
|
const ourQuoteReqAmount = getOurQuoteReqAmount(amountSpecified, fees, tradeType, this.nativeTokenService);
|
|
29624
29614
|
// Quotes will always use ERC20s. If the user-specified token is Native, we use the Wrapped Native Token pool
|
|
29625
|
-
const
|
|
29626
|
-
this.router.findOptimalRoute(ourQuoteReqAmount, this.nativeTokenService.maybeWrapToken(otherToken), tradeType, maxHops),
|
|
29627
|
-
fetchGasPrice(this.provider, this.nativeToken),
|
|
29628
|
-
]);
|
|
29615
|
+
const ourQuote = await this.router.findOptimalRoute(ourQuoteReqAmount, this.nativeTokenService.maybeWrapToken(otherToken), tradeType, maxHops);
|
|
29629
29616
|
const adjustedQuote = adjustQuoteWithFees(ourQuote, amountSpecified, fees, this.nativeTokenService);
|
|
29630
29617
|
const swap = getSwap(tokenIn, tokenOut, adjustedQuote, fromAddress, slippagePercent, deadline, this.routerContractAddress, this.secondaryFeeContractAddress, gasPrice, secondaryFees);
|
|
29631
29618
|
const { quotedAmount, quotedAmountWithMaxSlippage } = prepareUserQuote(this.nativeTokenService, adjustedQuote, slippagePercent, otherToken);
|
|
@@ -30562,7 +30549,7 @@ const GAS_OVERRIDES = {
|
|
|
30562
30549
|
maxPriorityFeePerGas: BigNumber$1.from(101e9),
|
|
30563
30550
|
};
|
|
30564
30551
|
|
|
30565
|
-
const SDK_VERSION_MARKER = '0.35.
|
|
30552
|
+
const SDK_VERSION_MARKER = '0.35.2';
|
|
30566
30553
|
// This SDK version is replaced by the `yarn build` command ran on the root level
|
|
30567
30554
|
const globalPackageVersion = () => SDK_VERSION_MARKER;
|
|
30568
30555
|
|