Contract ID: SaucerSwapV2QuoterV2
When providing HBAR in the path array, use the wrapped HBAR token ID (WHBAR).
For production environments, itโs highly recommended to use a paid Mirror Node provider for commercial and high-traffic purposes. While Hederaโs public mirror node offers free REST API and JSON API endpoints, they have global rate limits. These are best suited for development or low rate usage scenarios.
Get Output Quote from Exact Input Amount
Get the output amount from a given exact input amount and a swap route. Function name: quoteExactInput โฝ No gas cost| Parameter Name | Description |
|---|---|
| bytes path | Route path containing pair swap fees |
| uint256 amountIn | Exact input amount in tokenโs smallest unit |
/// @notice Returns the amount out received for a given exact input swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee
/// @param amountIn The amount of the first token to swap
/// @return amountOut The amount of the last token that would be received
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactInput(bytes memory path, uint256 amountIn)
external
returns (
uint256 amountOut,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
function quoteExactOutput(bytes memory path, uint256 amountOut)
public
override
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
)
{
sqrtPriceX96AfterList = new uint160[](path.numPools());
initializedTicksCrossedList = new uint32[](path.numPools());
uint256 i = 0;
while (true) {
(address tokenOut, address tokenIn, uint24 fee) = path.decodeFirstPool();
// the inputs of prior swaps become the outputs of subsequent ones
(
uint256 _amountIn,
uint160 _sqrtPriceX96After,
uint32 _initializedTicksCrossed,
uint256 _gasEstimate
) = quoteExactOutputSingle(
QuoteExactOutputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amount: amountOut,
fee: fee,
sqrtPriceLimitX96: 0
})
);
sqrtPriceX96AfterList[i] = _sqrtPriceX96After;
initializedTicksCrossedList[i] = _initializedTicksCrossed;
amountOut = _amountIn;
gasEstimate += _gasEstimate;
i++;
// decide whether to continue or terminate
if (path.hasMultiplePools()) {
path = path.skipToken();
} else {
return (amountOut, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate);
}
}
}
The data passed to the โpathโ parameter follows this format: [token, fee, token, fee, token, โฆ], with each โtokenโ in the route being 20 bytes long and each โfeeโ being 3 bytes long. Example, 0x0001F4 for a 0.05% fee.
Code Overview
- JSON RPC
- REST API
Resources:
Typescript
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterEvmAddress = `0x${ContractId.fromString(quoterContractId).toSolidityAddress()}`;
//swap path
const pathData:string[] = [];
pathData.push(inputToken.toSolidityAddress());
pathData.push(feeHexStr);
pathData.push(outputToken.toSolidityAddress());
const encodedPathData = hexToUint8Array(pathData.join(''));
const data = abiInterfaces.encodeFunctionData('quoteExactInput', [
encodedPathData,
inputAmountInSmallestUnit.toString()
]);
//Send a call to the JSON-RPC provider directly
const result = await provider.call({
to: quoterEvmAddress,
data: data,
});
const decoded = abiInterfaces.decodeFunctionResult('quoteExactInput', result);
const finalOutputAmount = decoded.amountOut; //in token's smallest unit
Resources:
Typescript
//Typescript
import * as ethers from 'ethers'; //V6
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterContract = ContractId.fromString(quoterContractId);
//swap path
const path:string[] = [];
path.push(inputToken.toSolidityAddress());
path.push(feeHexStr);
path.push(outputToken.toSolidityAddress());
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(path.join(''));
//quoteExactInput params
const params = [encodedPathData, inputAmountInSmallestUnit];
//Get encoded function data
const encodedData = abiInterfaces.encodeFunctionData(interfaces.getFunction('quoteExactInput')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': quoterContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const result = abiInterfaces.decodeFunctionResult('quoteExactInput', response.data.result);
const finalAmountOut = result.amountOut; //in token's smallest unit
Get Input Quote from Exact Output Amount
Get the input amount from a given exact output amount and a swap route. Function name: quoteExactOutput โฝ No gas cost| Parameter Name | Description |
|---|---|
| bytes path | Route path containing pair swap fees, reversed |
| uint256 amountOut | Exact output amount in tokenโs smallest unit |
/// @notice Returns the amount in required for a given exact output swap without executing the swap
/// @param path The path of the swap, i.e. each token pair and the pool fee. Path must be provided in reverse order
/// @param amountOut The amount of the last token to receive
/// @return amountIn The amount of first token required to be paid
/// @return sqrtPriceX96AfterList List of the sqrt price after the swap for each pool in the path
/// @return initializedTicksCrossedList List of the initialized ticks that the swap crossed for each pool in the path
/// @return gasEstimate The estimate of the gas that the swap consumes
function quoteExactOutput(bytes memory path, uint256 amountOut)
external
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
);
struct QuoteExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint256 amount;
uint24 fee;
uint160 sqrtPriceLimitX96;
}
function quoteExactOutput(bytes memory path, uint256 amountOut)
public
override
returns (
uint256 amountIn,
uint160[] memory sqrtPriceX96AfterList,
uint32[] memory initializedTicksCrossedList,
uint256 gasEstimate
)
{
sqrtPriceX96AfterList = new uint160[](path.numPools());
initializedTicksCrossedList = new uint32[](path.numPools());
uint256 i = 0;
while (true) {
(address tokenOut, address tokenIn, uint24 fee) = path.decodeFirstPool();
// the inputs of prior swaps become the outputs of subsequent ones
(
uint256 _amountIn,
uint160 _sqrtPriceX96After,
uint32 _initializedTicksCrossed,
uint256 _gasEstimate
) = quoteExactOutputSingle(
QuoteExactOutputSingleParams({
tokenIn: tokenIn,
tokenOut: tokenOut,
amount: amountOut,
fee: fee,
sqrtPriceLimitX96: 0
})
);
sqrtPriceX96AfterList[i] = _sqrtPriceX96After;
initializedTicksCrossedList[i] = _initializedTicksCrossed;
amountOut = _amountIn;
gasEstimate += _gasEstimate;
i++;
// decide whether to continue or terminate
if (path.hasMultiplePools()) {
path = path.skipToken();
} else {
return (amountOut, sqrtPriceX96AfterList, initializedTicksCrossedList, gasEstimate);
}
}
}
The data passed to the โpathโ parameter follows this format: [token, fee, token, fee, token, โฆ], but reversed (i.e. the first token in the array should be output token), with each โtokenโ in the route being 20 bytes long and each โfeeโ being 3 bytes long. Example,
0x000BB8 for a 0.30% fee.Code Overview
- JSON RPC
- REST API
Resources:
Typescript
import * as ethers from 'ethers'; //V6
//Set one of Hedera's JSON RPC Relay as the provider
const provider = new ethers.JsonRpcProvider(hederaJsonRelayUrl, '', {
batchMaxCount: 1, //workaround for V6
});
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterEvmAddress = `0x${ContractId.fromString(quoterContractId).toSolidityAddress()}`;
//swap path
const pathData:string[] = [];
pathData.push(inputToken.toSolidityAddress());
pathData.push(feeHexStr);
pathData.push(outputToken.toSolidityAddress());
//reverse the path
pathData.reverse();
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(pathData.join(''));
const data = abiInterfaces.encodeFunctionData('quoteExactOutput', [
encodedPathData,
outputAmountInSmallestUnit
]);
//Send a call to the JSON-RPC provider directly
const result = await provider.call({
to: quoterEvmAddress,
data: data,
});
const decoded = abiInterfaces.decodeFunctionResult('quoteExactOutput', result);
const finalAmountIn = decoded.amountIn; //in token's smallest unit
Resources:
Typescript
import * as ethers from 'ethers'; //V6
//load ABI data containing QuoterV2 functions
const abiInterfaces = new ethers.Interface(abi);
//QuoterV2.sol contract
const quoterContract = ContractId.fromString(quoterContractId);
const path:string[] = [];
path.push(inputToken.toSolidityAddress());
path.push(feeHexStr);
path.push(outputToken.toSolidityAddress());
//reverse the path
path.reverse();
//get encoded Uint8Array data for path hex
const encodedPathData = hexToUint8Array(path.join(''));
//quoteExactOutput params
const params = [encodedPathData, outputAmountInSmallestUnit];
//Get encoded function data
const encodedData = abiInterfaces.encodeFunctionData(interfaces.getFunction('quoteExactOutput')!, params);
const url = `${mirrorNodeBaseUrl}/api/v1/contracts/call`;
const data = {
'block': 'latest',
'data': encodedData,
'to': quoterContract.toSolidityAddress(),
};
const response = await axios.post(url, data, { headers: {'content-type': 'application/json'} });
const result = abiInterfaces.decodeFunctionResult('quoteExactOutput', response.data.result);
const finalAmountIn = result.amountIn; //in token's smallest unit