evx-sdk
Version:
The Evx SDK is a developer toolkit designed to simplify interaction with the Evx decentralized liquidity protocol. It provides an abstraction layer over the smart contracts, allowing developers to easily build applications, integrate liquidity pools, fetc
2,316 lines (2,290 loc) • 291 kB
JavaScript
'use strict';
require('reflect-metadata');
var ethers = require('ethers');
var tsyringe = require('tsyringe');
/**
* @notice Converts a decimal number to a BigInt representation using fixed-point arithmetic.
* @dev Useful for on-chain values (e.g., ERC20 with 18 decimals).
* @param value The decimal number to convert (as number or string).
* @param decimals The number of decimal places (commonly 18).
* @return The BigInt representation.
*/
function decimalToBigInt(value, decimals = 18) {
return ethers.parseUnits(value.toString(), decimals);
}
/**
* @notice Converts a BigInt value (like on-chain token amount) to a human-readable decimal string.
* @dev Reverts the transformation made by `decimalToBigInt`.
* @param value The BigInt value to convert.
* @param decimals The number of decimal places (commonly 18).
* @return The decimal value as a string.
*/
function bigIntToDecimal(value, decimals = 18) {
return ethers.formatUnits(value, decimals);
}
/**
* @title Decimal to SqrtX96 Price
* @notice Converts a decimal price to sqrt price in X96 format
* @dev Used for Nebular price calculations
* @param decimalPrice The price in decimal format
* @param decimalsToken0 Number of decimals for token0
* @param decimalsToken1 Number of decimals for token1
* @returns The sqrt price in X96 format as a bigint
*/
function decimalToSqrtX96Price(decimalPrice, decimalsToken0, decimalsToken1) {
// √(price01 * 10^(dec1-dec0)) * 2^96
const factor = 10 ** (decimalsToken1 - decimalsToken0);
const scaledPrice = decimalPrice * factor;
const sqrtP = Math.sqrt(scaledPrice);
const sqrtPriceX96 = sqrtP * 2 ** 96;
return BigInt(Math.floor(sqrtPriceX96));
}
/**
* @title SqrtX96 to Decimal Price
* @notice Converts a sqrt price in X96 format to decimal price
* @dev Used for Nebular price calculations
* @param sqrtPriceX96 The sqrt price in X96 format
* @param decimalsToken0 Number of decimals for token0
* @param decimalsToken1 Number of decimals for token1
* @returns The price in decimal format
*/
function sqrtX96ToDecimalPrice(sqrtPriceX96, decimalsToken0, decimalsToken1) {
// (sqrtPriceX96 / 2**96) ** 2
const sqrtPrice = sqrtPriceX96.toString();
const sqrtPriceFloat = Number(sqrtPrice) / 2 ** 96;
const price = sqrtPriceFloat ** 2;
return price * 10 ** (decimalsToken0 - decimalsToken1);
}
/**
* @title Sort Tokens
* @notice Sorts token addresses in ascending order
* @dev Ensures consistent token ordering for contract interactions
* @param pair The token pair to sort
* @returns The sorted token pair with token0 < token1
*/
function sortTokens(pair) {
const isCorrectOrder = pair.token0.toLowerCase() < pair.token1.toLowerCase();
return {
token0: isCorrectOrder ? pair.token0 : pair.token1,
token1: isCorrectOrder ? pair.token1 : pair.token0
};
}
/**
* @notice Converts a percentage value to basis points (BPS).
* @dev 1 BPS = 0.01%, 100 BPS = 1%, 10000 BPS = 100%
* @param percentage The percentage value (e.g., 0.3 for 0.3%).
* @return The basis points as a BigInt.
*/
function percentageToBasisPoints(percentage) {
// Convert percentage to basis points (1% = 100 BPS)
return BigInt(Math.round(percentage * 100));
}
/**
* @notice Converts basis points (BPS) to a percentage value.
* @dev 1 BPS = 0.01%, 100 BPS = 1%, 10000 BPS = 100%
* @param basisPoints The basis points value.
* @return The percentage as a number.
*/
function basisPointsToPercentage(basisPoints) {
return Number(basisPoints) / 100;
}
/**
* @notice Converts a percentage value to Nebular fee format.
* @dev Nebular uses 1 unit = 0.0001%
* @param percentage The percentage value (e.g., 0.3 for 0.3%).
* @return The fee value as a BigInt.
*/
function percentageToFee(percentage) {
// Convert percentage to Nebular fee units (1 unit = 0.0001%)
return BigInt(Math.round(percentage * 10000));
}
/**
* @notice Converts Nebular fee format to a percentage value.
* @dev Nebular uses 1 unit = 0.0001%
* @param fee The fee value from Nebular.
* @return The percentage as a number.
*/
function feeToPercentage(fee) {
return Number(fee) / 10000;
}
/**
* @notice Converts basis points to Nebular fee format.
* @dev 1 BPS = 0.01% = 100 Nebular units
* @param basisPoints The basis points value.
* @return The Nebular fee value as a BigInt.
*/
function basisPointsToFee(basisPoints) {
return basisPoints * 100n;
}
/**
* @notice Converts Nebular fee format to basis points.
* @dev 1 Nebular unit = 0.0001% = 0.01 BPS
* @param fee The Nebular fee value.
* @return The basis points as a BigInt.
*/
function feeToBasisPoints(fee) {
return fee / 100n;
}
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
function __param(paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
}
function __metadata(metadataKey, metadataValue) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
/**
* @title RPC Provider
* @notice Manages the RPC connection for the SDK
* @dev Provides a singleton instance of JsonRpcProvider for blockchain interactions
*/
exports.RPC = class RPC {
/**
* @notice Creates a new RPC provider instance
* @dev Initializes with a default localhost provider
*/
constructor() {
this.provider = new ethers.JsonRpcProvider('::1');
}
/**
* @notice Sets a new RPC provider URL
* @param newRPC The new RPC URL to connect to
*/
setProvider(newRPC) {
this.provider = new ethers.JsonRpcProvider(newRPC);
}
};
exports.RPC = __decorate([
tsyringe.singleton(),
__metadata("design:paramtypes", [])
], exports.RPC);
/**
* @notice Gets comprehensive gas price information from network
* @return Object with gas prices in wei
*/
async function getNetworkGasPrices() {
const rpc = tsyringe.container.resolve(exports.RPC);
if (!rpc.provider) {
throw new Error('RPC provider not initialized');
}
const feeData = await rpc.provider.getFeeData();
return {
// Legacy gas price (for legacy transactions)
legacy: feeData.gasPrice ?? 0n,
// EIP-1559 gas prices
maxFeePerGas: feeData.maxFeePerGas ?? 0n,
maxPriorityFeePerGas: feeData.maxPriorityFeePerGas ?? 0n,
// Recommended gas price (current network gas price)
current: feeData.gasPrice ?? feeData.maxFeePerGas ?? 1n,
// Minimum gas price (priority fee)
minimum: feeData.maxPriorityFeePerGas ?? 1n,
// Maximum gas price (max fee per gas)
maximum: feeData.maxFeePerGas ?? feeData.gasPrice ?? 1n
};
}
/**
* @notice Gets the current network gas price in wei
* @return The current gas price in wei
*/
async function getCurrentNetworkGasPrice() {
const rpc = tsyringe.container.resolve(exports.RPC);
if (!rpc.provider) {
throw new Error('RPC provider not initialized');
}
const feeData = await rpc.provider.getFeeData();
return feeData.gasPrice ?? feeData.maxFeePerGas ?? 1n;
}
/**
* @notice Converts gas estimate to ETH cost with different gas price scenarios
* @param gasEstimateInUnits The gas estimate from contract (in gas units)
* @return Object with costs in ETH for different gas price scenarios
*/
async function convertGasEstimateToEthCost(gasEstimateInUnits) {
const gasPricesInWei = await getNetworkGasPrices();
return {
// Cost with current gas price
current: Number(gasEstimateInUnits * gasPricesInWei.current) / Number(ethers.ethers.WeiPerEther),
// Cost with minimum gas price (priority fee)
minimum: Number(gasEstimateInUnits * gasPricesInWei.minimum) / Number(ethers.ethers.WeiPerEther),
// Cost with maximum gas price (max fee per gas)
maximum: Number(gasEstimateInUnits * gasPricesInWei.maximum) / Number(ethers.ethers.WeiPerEther),
// Cost with legacy gas price
legacy: Number(gasEstimateInUnits * gasPricesInWei.legacy) / Number(ethers.ethers.WeiPerEther),
// Gas prices in wei for reference
gasPricesInWei: {
current: gasPricesInWei.current.toString(),
minimum: gasPricesInWei.minimum.toString(),
maximum: gasPricesInWei.maximum.toString(),
legacy: gasPricesInWei.legacy.toString()
}
};
}
/**
* @title Path Finding Utilities
* @notice Utilities for finding the shortest path between tokens through pools
* @dev Implements breadth-first search algorithm to find optimal trading paths
*/
/**
* @notice Pool lookup without sorting overhead
* @dev Uses direct string comparison for maximum performance
*/
class PoolLookup {
constructor(pools) {
this.poolByTokens = new Map();
this.poolByAddress = new Map();
this.buildLookupMaps(pools);
}
/**
* @notice Builds lookup maps without sorting overhead
*/
buildLookupMaps(pools) {
for (const pool of pools) {
// Store by address
this.poolByAddress.set(pool.address, pool);
// Store by token pair (both directions for O(1) lookup)
const token0 = pool.token0.address.toLowerCase();
const token1 = pool.token1.address.toLowerCase();
// Create keys for both directions without sorting
const key1 = `${token0}-${token1}`;
const key2 = `${token1}-${token0}`;
this.poolByTokens.set(key1, pool);
this.poolByTokens.set(key2, pool);
}
}
/**
* @notice O(1) lookup for pool by token pair (no sorting)
*/
getPoolByTokens(token1, token2) {
const key = `${token1.toLowerCase()}-${token2.toLowerCase()}`;
return this.poolByTokens.get(key);
}
/**
* @notice O(1) lookup for pool by address
*/
getPoolByAddress(address) {
return this.poolByAddress.get(address);
}
}
/**
* @notice Finds the shortest path between two tokens through available pools
* @param pools Array of available pools
* @param inputToken Address of the input token
* @param outputToken Address of the output token
* @returns The shortest trading path or null if no path exists
*/
function findShortestPath(pools, inputToken, outputToken) {
const input = inputToken.toLowerCase();
const output = outputToken.toLowerCase();
if (input === output) {
return {
pools: [],
tokens: [inputToken],
hops: 0
};
}
// Build a lookup without sorting overhead
const lookup = new PoolLookup(pools);
// Build adjacency list without sorting overhead
const connections = buildTokenConnections(pools);
// Find path
const path = breadthFirstSearch(connections, input, output);
if (!path)
return null;
// Convert to trading path with O(1) lookups
return convertPathToTradingPath(path, lookup);
}
/**
* @notice Builds adjacency list
* @param pools Array of available pools
* @returns Map of token addresses to their connections
*/
function buildTokenConnections(pools) {
const connections = new Map();
for (const pool of pools) {
// Direct comparison without sorting for maximum performance
const token0 = pool.token0.address.toLowerCase();
const token1 = pool.token1.address.toLowerCase();
// Add both directions without sorting overhead
if (!connections.has(token0)) {
connections.set(token0, new Set());
}
connections.get(token0).add(token1);
if (!connections.has(token1)) {
connections.set(token1, new Set());
}
connections.get(token1).add(token0);
}
return connections;
}
/**
* @notice Performs breadth-first search to find shortest path between tokens
* @param connections Token adjacency list
* @param startToken Starting token address
* @param endToken Ending token address
* @returns Array of path nodes or null if no path exists
*/
function breadthFirstSearch(connections, startToken, endToken) {
const queue = [{ token: startToken, distance: 0 }];
const visited = new Set();
const pathMap = new Map();
while (queue.length > 0) {
const current = queue.shift();
if (current.token === endToken) {
return reconstructPath(current);
}
if (visited.has(current.token)) {
continue;
}
visited.add(current.token);
pathMap.set(current.token, current);
const neighbors = connections.get(current.token);
if (!neighbors) {
continue;
}
for (const neighbor of neighbors) {
if (!visited.has(neighbor)) {
const neighborNode = {
token: neighbor,
previous: current,
distance: current.distance + 1
};
queue.push(neighborNode);
}
}
}
return null; // No path found
}
/**
* @notice Reconstructs the path from the end node back to the start
* @param endNode The final node in the path
* @returns Array of path nodes in order from start to end
*/
function reconstructPath(endNode) {
const path = [];
let current = endNode;
while (current) {
path.unshift(current);
current = current.previous;
}
return path;
}
/**
* @notice Converts a path of tokens to a trading path with pool addresses
* @param path Array of path nodes
* @param lookup Pool lookup table
* @returns Trading path with pool addresses and token addresses
*/
function convertPathToTradingPath(path, lookup) {
const poolAddresses = [];
const tokenAddresses = [];
// Add first token
tokenAddresses.push(path[0].token);
// Find pools for each consecutive pair of tokens with O(1) lookup
for (let i = 0; i < path.length - 1; i++) {
const currentToken = path[i].token;
const nextToken = path[i + 1].token;
// O(1) pool lookup without sorting
const pool = lookup.getPoolByTokens(currentToken, nextToken);
if (pool) {
poolAddresses.push(pool.address);
}
// Add next token
tokenAddresses.push(nextToken);
}
return {
pools: poolAddresses,
tokens: tokenAddresses,
hops: path.length - 1
};
}
/**
* @notice Encodes a trading path for use with SwapRouter
* @param path Trading path to encode
* @param pools Array of available pools
* @param isExactOutput Whether this is for exact output (reverses the path)
* @returns Encoded path with all necessary data for SwapRouter
*/
function encodePath(path, pools, isExactOutput = false) {
if (path.tokens.length < 2) {
throw new Error('Path must have at least 2 tokens');
}
const lookup = new PoolLookup(pools);
const encodedTokens = [];
const encodedFees = [];
const encodedPools = [];
// For exact output, we need to reverse the path
const tokens = isExactOutput ? [...path.tokens].reverse() : path.tokens;
const poolsList = isExactOutput ? [...path.pools].reverse() : path.pools;
// Always start with the first token
encodedTokens.push(tokens[0]);
// Process each hop - each hop adds: fee + next_token
for (let i = 0; i < poolsList.length; i++) {
const pool = lookup.getPoolByAddress(poolsList[i]);
if (!pool) {
throw new Error(`Pool not found: ${poolsList[i]}`);
}
// Add fee for this hop
encodedFees.push(pool.fee);
// Add the next token (which becomes the input for the next hop)
encodedTokens.push(tokens[i + 1]);
encodedPools.push(pool.address);
}
// Create the encoded path bytes in the format: token0 + fee0 + token1 + fee1 + token2 + ...
const pathData = [];
// Always add the first token
pathData.push(encodedTokens[0]);
// Then add fee + token for each hop
for (let i = 0; i < encodedFees.length; i++) {
pathData.push(parseInt(encodedFees[i])); // fee as uint24
pathData.push(encodedTokens[i + 1]); // next token
}
// Create path string for display
const pathString = pathData.join(':');
// Create the bytes-encoded path: token0 (20 bytes) + fee0 (3 bytes) + token1 (20 bytes) + ...
let encodedBytes = '0x';
for (let i = 0; i < encodedFees.length; i++) {
// Add token address (remove 0x prefix and ensure 40 hex chars = 20 bytes)
encodedBytes += encodedTokens[i].slice(2);
// Add fee as 3 bytes (6 hex characters)
encodedBytes += parseInt(encodedFees[i]).toString(16).padStart(6, '0');
}
// Add the last token
encodedBytes += encodedTokens[encodedTokens.length - 1].slice(2);
return {
pathString: pathString,
pathBytes: encodedBytes,
pools: encodedPools,
tokens: encodedTokens,
fees: encodedFees,
hops: path.hops
};
}
/**
* @title Get Chain ID Function
* @notice Returns the chain ID for a given chain name
* @param chainName The name of the chain
* @returns The chain ID
* @throws Error if chain is not found
*/
function getChainId(chainName) {
const chain = chains[chainName];
if (!chain) {
throw new Error(`Chain not found: ${chainName}`);
}
return chain.metadata.chainId;
}
/**
* @title Get Chain Name by ID Function
* @notice Returns the chain name for a given chain ID
* @param chainId The chain ID
* @returns The chain name
* @throws Error if chain ID is not found
*/
function getChainNameById(chainId) {
for (const [name, chain] of Object.entries(chains)) {
if (chain.metadata.chainId === chainId) {
return name;
}
}
throw new Error(`Chain ID not found: ${chainId}`);
}
/**
* @title Validate Chain ID Function
* @notice Checks if a chain ID is valid
* @param chainId The chain ID to validate
* @returns True if the chain ID is valid, false otherwise
*/
function isValidChainId(chainId) {
try {
getChainNameById(chainId);
return true;
}
catch {
return false;
}
}
/**
* @title Validate Chain Name Function
* @notice Checks if a chain name is valid
* @param chainName The chain name to validate
* @returns True if the chain name is valid, false otherwise
*/
function isValidChainName(chainName) {
return chainName in chains;
}
/**
* @title Get All Chain IDs Function
* @notice Returns an array of all supported chain IDs
* @returns Array of chain IDs
*/
function getAllChainIds() {
return Object.values(chains).map((chain) => chain.metadata.chainId);
}
/**
* @title Get All Chain Names Function
* @notice Returns an array of all supported chain names
* @returns Array of chain names
*/
function getAllChainNames() {
return Object.keys(chains);
}
/**
* @title Get Chain Metadata Function
* @notice Returns the metadata for a given chain name
* @param chainName The name of the chain
* @returns The chain metadata
* @throws Error if chain is not found
*/
function getChainMetadata(chainName) {
const chain = chains[chainName];
if (!chain)
throw new Error(`Chain not found: ${chainName}`);
return chain.metadata;
}
/**
* @title Get All Chains Metadata Function
* @notice Returns an array of all supported chain names and their metadata
* @returns Array of chain names and their metadata
*/
function getAllChainsMetadata() {
return Object.entries(chains).map(([name, chain]) => ({
name: name,
metadata: chain.metadata
}));
}
/**
* @notice Gets all writer contracts that need signer and chain updates
* @returns Array of contract instances that need configuration
*/
function getWriterContracts() {
return [
tsyringe.container.resolve(exports.PositionManagerContract),
tsyringe.container.resolve(exports.OrderExecutorContract),
tsyringe.container.resolve(exports.FactoryContract)
];
}
/**
* @title Set All Signer
* @notice Sets the signer for all writer contracts
* @param signer The signer to use for transactions
*/
async function setAllSigner(signer) {
await Promise.all(getWriterContracts().map((c) => c.setSigner(signer)));
}
/**
* @title Set All Chain
* @notice Sets the chain for all writer contracts
* @param chain The chain to use for contract interactions
*/
async function setAllChain(chain) {
await Promise.all(getWriterContracts().map((c) => c.setChain(chain)));
}
/**
* @title Set All Chain by ID
* @notice Sets the chain for all writer contracts using chain ID
* @param chainId The chain ID to use for contract interactions
* @throws Error if chain ID is not found
*/
async function setAllChainById(chainId) {
const chainName = getChainNameById(chainId);
await setAllChain(chainName);
}
/**
* @title Set RPC Provider
* @notice Sets the RPC provider URL for the SDK
* @param rpcUrl The RPC URL to connect to
*/
async function setRPCProvider(rpcUrl) {
const rpc = tsyringe.container.resolve(exports.RPC);
rpc.setProvider(rpcUrl);
}
/**
* @title Chain Configuration
* @notice Contract addresses for different networks
* @dev Maps contract names to their addresses for each supported chain
*/
const chains = {
sepolia: {
metadata: {
chainId: 11155111,
explorer: 'https://sepolia.etherscan.io',
nativeToken: '0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14'
},
contracts: {
positionDescriptor: '0x17C50c136887C9258310d9C3331aA0e1f8f98330',
positionManager: '0x29d077c93A7F5F1092E18B4883B26DD6c934de81',
orderExecutor: '0x7fC548F0d27f7D6aAC90d2923b7c0EdF2c8198f2',
positionLens: '0x1D29d573D44E308D161095764FC85f6bAd913d8B',
swapRouter: '0xDea4395543832560b33F80C4B5cA1F852856D088',
swapQuoter: '0x6cb7Df410cD1c47e29473154f2FA36cf058D4477',
pairFlash: '0xdBd297d618f5ab6330a05Fd0645a268F44687452',
tickLens: '0x9706cA44f004054BAA842b5db1f62f6c9b77A095',
factory: '0x822AC7faa4EdA0bfA4c9A4eb5EeeB43d3Cba9CC7',
dao: '0x0FA0d8D55B6a90823De8fc843cEd7D02F2DE7cC4'
}
}
};
/**
* @title Constants
* @notice All constants used throughout the SDK
*/
/**
* Tick Lens related constants
*/
const TICK_BITMAP_INDEX = {
MIN: -32768,
MAX: 32767
};
/**
* @title Base Contract
* @notice Base class for all contract interactions
* @dev Provides common functionality for contract instances including signer management and chain switching
*/
class BaseContract {
/**
* @notice Creates a new contract instance
* @param name The name of the contract
* @param rpc The RPC provider instance
* @param abi The contract ABI
*/
constructor(name, rpc, abi) {
this.signer = null;
this.chain = 'sepolia';
this.rpc = rpc;
this.name = name;
this.abi = abi;
this.instance = new ethers.ethers.Contract(this.getAddress(), this.abi, this.rpc.provider);
}
/**
* @notice Sets the signer for contract interactions
* @param signer The signer to use for transactions
*/
async setSigner(signer) {
this.signer = signer;
if (!signer) {
this.instance = new ethers.ethers.Contract(this.getAddress(), this.abi, this.rpc.provider);
return;
}
this.instance = new ethers.ethers.Contract(this.getAddress(), this.abi, signer);
}
/**
* @notice Sets the chain for contract interactions
* @param chain The chain to use for contract interactions
*/
setChain(chain) {
this.chain = chain;
this.instance = new ethers.ethers.Contract(this.getAddress(), this.abi, this.rpc.provider);
}
/**
* @notice Gets the contract address for the current chain
* @returns The contract address
* @throws Error if address is not found for the current chain
*/
getAddress() {
const chain = chains[this.chain];
if (!chain) {
throw new Error(`Chain not found: ${this.chain}`);
}
const address = chain.contracts[this.name];
if (!address) {
throw new Error(`Address not found for ${this.chain}.${this.name}`);
}
return address;
}
}
var FactoryABI = [
{
type: "constructor",
inputs: [
{
name: "_poolImplementation",
type: "address",
internalType: "address"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "createPool",
inputs: [
{
name: "tokenA",
type: "address",
internalType: "address"
},
{
name: "tokenB",
type: "address",
internalType: "address"
},
{
name: "fee",
type: "uint24",
internalType: "uint24"
}
],
outputs: [
{
name: "pool",
type: "address",
internalType: "address"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "enableFeeAmount",
inputs: [
{
name: "fee",
type: "uint24",
internalType: "uint24"
},
{
name: "tickSpacing",
type: "int24",
internalType: "int24"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "feeAmountTickSpacing",
inputs: [
{
name: "",
type: "uint24",
internalType: "uint24"
}
],
outputs: [
{
name: "",
type: "int24",
internalType: "int24"
}
],
stateMutability: "view"
},
{
type: "function",
name: "getPool",
inputs: [
{
name: "",
type: "address",
internalType: "address"
},
{
name: "",
type: "address",
internalType: "address"
},
{
name: "",
type: "uint24",
internalType: "uint24"
}
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "function",
name: "owner",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "function",
name: "poolImplementation",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "function",
name: "setOwner",
inputs: [
{
name: "_owner",
type: "address",
internalType: "address"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "event",
name: "FeeAmountEnabled",
inputs: [
{
name: "fee",
type: "uint24",
indexed: true,
internalType: "uint24"
},
{
name: "tickSpacing",
type: "int24",
indexed: true,
internalType: "int24"
}
],
anonymous: false
},
{
type: "event",
name: "OwnerChanged",
inputs: [
{
name: "oldOwner",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "newOwner",
type: "address",
indexed: true,
internalType: "address"
}
],
anonymous: false
},
{
type: "event",
name: "PoolCreated",
inputs: [
{
name: "token0",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "token1",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "fee",
type: "uint24",
indexed: true,
internalType: "uint24"
},
{
name: "tickSpacing",
type: "int24",
indexed: false,
internalType: "int24"
},
{
name: "pool",
type: "address",
indexed: false,
internalType: "address"
}
],
anonymous: false
},
{
type: "error",
name: "AlreadyEnabled",
inputs: [
]
},
{
type: "error",
name: "FailedDeployment",
inputs: [
]
},
{
type: "error",
name: "FeeTooHigh",
inputs: [
]
},
{
type: "error",
name: "Forbidden",
inputs: [
]
},
{
type: "error",
name: "IdenticalAddresses",
inputs: [
]
},
{
type: "error",
name: "InsufficientBalance",
inputs: [
{
name: "balance",
type: "uint256",
internalType: "uint256"
},
{
name: "needed",
type: "uint256",
internalType: "uint256"
}
]
},
{
type: "error",
name: "InvalidFee",
inputs: [
]
},
{
type: "error",
name: "InvalidTickSpacing",
inputs: [
]
},
{
type: "error",
name: "NoDelegateCallError",
inputs: [
]
},
{
type: "error",
name: "PoolExists",
inputs: [
]
},
{
type: "error",
name: "ZeroAddress",
inputs: [
]
},
{
type: "error",
name: "ZeroImplementation",
inputs: [
]
}
];
/**
* @title Factory Contract
* @notice Contract wrapper for Evx Factory interactions
* @dev Provides methods to interact with the factory contract for pool creation
*/
exports.FactoryContract = class FactoryContract extends BaseContract {
/**
* @notice Creates a new factory contract instance
* @param rpc The RPC provider instance
*/
constructor(rpc) {
super('factory', rpc, FactoryABI);
this.rpc = rpc;
}
};
exports.FactoryContract = __decorate([
tsyringe.injectable(),
tsyringe.singleton(),
__param(0, tsyringe.inject(exports.RPC)),
__metadata("design:paramtypes", [exports.RPC])
], exports.FactoryContract);
var PoolABI = [
{
type: "function",
name: "burn",
inputs: [
{
name: "tickLower",
type: "int24",
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
internalType: "int24"
},
{
name: "amount",
type: "uint128",
internalType: "uint128"
}
],
outputs: [
{
name: "amount0",
type: "uint256",
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
internalType: "uint256"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "collect",
inputs: [
{
name: "recipient",
type: "address",
internalType: "address"
},
{
name: "tickLower",
type: "int24",
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
internalType: "int24"
},
{
name: "amount0Requested",
type: "uint128",
internalType: "uint128"
},
{
name: "amount1Requested",
type: "uint128",
internalType: "uint128"
}
],
outputs: [
{
name: "amount0",
type: "uint128",
internalType: "uint128"
},
{
name: "amount1",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "collectProtocol",
inputs: [
{
name: "recipient",
type: "address",
internalType: "address"
},
{
name: "amount0Requested",
type: "uint128",
internalType: "uint128"
},
{
name: "amount1Requested",
type: "uint128",
internalType: "uint128"
}
],
outputs: [
{
name: "amount0",
type: "uint128",
internalType: "uint128"
},
{
name: "amount1",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "factory",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "function",
name: "fee",
inputs: [
],
outputs: [
{
name: "",
type: "uint24",
internalType: "uint24"
}
],
stateMutability: "view"
},
{
type: "function",
name: "feeGrowthGlobal0X128",
inputs: [
],
outputs: [
{
name: "",
type: "uint256",
internalType: "uint256"
}
],
stateMutability: "view"
},
{
type: "function",
name: "feeGrowthGlobal1X128",
inputs: [
],
outputs: [
{
name: "",
type: "uint256",
internalType: "uint256"
}
],
stateMutability: "view"
},
{
type: "function",
name: "flash",
inputs: [
{
name: "recipient",
type: "address",
internalType: "address"
},
{
name: "amount0",
type: "uint256",
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
internalType: "uint256"
},
{
name: "data",
type: "bytes",
internalType: "bytes"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "increaseObservationCardinalityNext",
inputs: [
{
name: "observationCardinalityNext",
type: "uint16",
internalType: "uint16"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "initialize",
inputs: [
{
name: "_factory",
type: "address",
internalType: "address"
},
{
name: "_token0",
type: "address",
internalType: "address"
},
{
name: "_token1",
type: "address",
internalType: "address"
},
{
name: "_fee",
type: "uint24",
internalType: "uint24"
},
{
name: "_tickSpacing",
type: "int24",
internalType: "int24"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "initializeObservation",
inputs: [
{
name: "sqrtPriceX96",
type: "uint160",
internalType: "uint160"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "liquidity",
inputs: [
],
outputs: [
{
name: "",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "view"
},
{
type: "function",
name: "maxLiquidityPerTick",
inputs: [
],
outputs: [
{
name: "",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "view"
},
{
type: "function",
name: "mint",
inputs: [
{
name: "recipient",
type: "address",
internalType: "address"
},
{
name: "tickLower",
type: "int24",
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
internalType: "int24"
},
{
name: "amount",
type: "uint128",
internalType: "uint128"
},
{
name: "data",
type: "bytes",
internalType: "bytes"
}
],
outputs: [
{
name: "amount0",
type: "uint256",
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
internalType: "uint256"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "observations",
inputs: [
{
name: "",
type: "uint256",
internalType: "uint256"
}
],
outputs: [
{
name: "blockTimestamp",
type: "uint32",
internalType: "uint32"
},
{
name: "tickCumulative",
type: "int56",
internalType: "int56"
},
{
name: "secondsPerLiquidityCumulativeX128",
type: "uint160",
internalType: "uint160"
},
{
name: "initialized",
type: "bool",
internalType: "bool"
}
],
stateMutability: "view"
},
{
type: "function",
name: "observe",
inputs: [
{
name: "secondsAgos",
type: "uint32[]",
internalType: "uint32[]"
}
],
outputs: [
{
name: "tickCumulatives",
type: "int56[]",
internalType: "int56[]"
},
{
name: "secondsPerLiquidityCumulativeX128s",
type: "uint160[]",
internalType: "uint160[]"
}
],
stateMutability: "view"
},
{
type: "function",
name: "positions",
inputs: [
{
name: "",
type: "bytes32",
internalType: "bytes32"
}
],
outputs: [
{
name: "liquidity",
type: "uint128",
internalType: "uint128"
},
{
name: "feeGrowthInside0LastX128",
type: "uint256",
internalType: "uint256"
},
{
name: "feeGrowthInside1LastX128",
type: "uint256",
internalType: "uint256"
},
{
name: "tokensOwed0",
type: "uint128",
internalType: "uint128"
},
{
name: "tokensOwed1",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "view"
},
{
type: "function",
name: "protocolFees",
inputs: [
],
outputs: [
{
name: "token0",
type: "uint128",
internalType: "uint128"
},
{
name: "token1",
type: "uint128",
internalType: "uint128"
}
],
stateMutability: "view"
},
{
type: "function",
name: "setFeeProtocol",
inputs: [
{
name: "feeProtocol0",
type: "uint8",
internalType: "uint8"
},
{
name: "feeProtocol1",
type: "uint8",
internalType: "uint8"
}
],
outputs: [
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "slot0",
inputs: [
],
outputs: [
{
name: "sqrtPriceX96",
type: "uint160",
internalType: "uint160"
},
{
name: "tick",
type: "int24",
internalType: "int24"
},
{
name: "observationIndex",
type: "uint16",
internalType: "uint16"
},
{
name: "observationCardinality",
type: "uint16",
internalType: "uint16"
},
{
name: "observationCardinalityNext",
type: "uint16",
internalType: "uint16"
},
{
name: "feeProtocol",
type: "uint8",
internalType: "uint8"
},
{
name: "unlocked",
type: "bool",
internalType: "bool"
}
],
stateMutability: "view"
},
{
type: "function",
name: "snapshotCumulativesInside",
inputs: [
{
name: "tickLower",
type: "int24",
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
internalType: "int24"
}
],
outputs: [
{
name: "tickCumulativeInside",
type: "int56",
internalType: "int56"
},
{
name: "secondsPerLiquidityInsideX128",
type: "uint160",
internalType: "uint160"
},
{
name: "secondsInside",
type: "uint32",
internalType: "uint32"
}
],
stateMutability: "view"
},
{
type: "function",
name: "swap",
inputs: [
{
name: "recipient",
type: "address",
internalType: "address"
},
{
name: "zeroForOne",
type: "bool",
internalType: "bool"
},
{
name: "amountSpecified",
type: "int256",
internalType: "int256"
},
{
name: "sqrtPriceLimitX96",
type: "uint160",
internalType: "uint160"
},
{
name: "data",
type: "bytes",
internalType: "bytes"
}
],
outputs: [
{
name: "amount0",
type: "int256",
internalType: "int256"
},
{
name: "amount1",
type: "int256",
internalType: "int256"
}
],
stateMutability: "nonpayable"
},
{
type: "function",
name: "tickBitmap",
inputs: [
{
name: "",
type: "int16",
internalType: "int16"
}
],
outputs: [
{
name: "",
type: "uint256",
internalType: "uint256"
}
],
stateMutability: "view"
},
{
type: "function",
name: "tickSpacing",
inputs: [
],
outputs: [
{
name: "",
type: "int24",
internalType: "int24"
}
],
stateMutability: "view"
},
{
type: "function",
name: "ticks",
inputs: [
{
name: "",
type: "int24",
internalType: "int24"
}
],
outputs: [
{
name: "liquidityGross",
type: "uint128",
internalType: "uint128"
},
{
name: "liquidityNet",
type: "int128",
internalType: "int128"
},
{
name: "feeGrowthOutside0X128",
type: "uint256",
internalType: "uint256"
},
{
name: "feeGrowthOutside1X128",
type: "uint256",
internalType: "uint256"
},
{
name: "tickCumulativeOutside",
type: "int56",
internalType: "int56"
},
{
name: "secondsPerLiquidityOutsideX128",
type: "uint160",
internalType: "uint160"
},
{
name: "secondsOutside",
type: "uint32",
internalType: "uint32"
},
{
name: "initialized",
type: "bool",
internalType: "bool"
}
],
stateMutability: "view"
},
{
type: "function",
name: "token0",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "function",
name: "token1",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: "view"
},
{
type: "event",
name: "Burn",
inputs: [
{
name: "owner",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "tickLower",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "amount",
type: "uint128",
indexed: false,
internalType: "uint128"
},
{
name: "amount0",
type: "uint256",
indexed: false,
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
indexed: false,
internalType: "uint256"
}
],
anonymous: false
},
{
type: "event",
name: "Collect",
inputs: [
{
name: "owner",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "recipient",
type: "address",
indexed: false,
internalType: "address"
},
{
name: "tickLower",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "amount0",
type: "uint128",
indexed: false,
internalType: "uint128"
},
{
name: "amount1",
type: "uint128",
indexed: false,
internalType: "uint128"
}
],
anonymous: false
},
{
type: "event",
name: "CollectProtocol",
inputs: [
{
name: "sender",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "recipient",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "amount0",
type: "uint128",
indexed: false,
internalType: "uint128"
},
{
name: "amount1",
type: "uint128",
indexed: false,
internalType: "uint128"
}
],
anonymous: false
},
{
type: "event",
name: "Flash",
inputs: [
{
name: "sender",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "recipient",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "amount0",
type: "uint256",
indexed: false,
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
indexed: false,
internalType: "uint256"
},
{
name: "paid0",
type: "uint256",
indexed: false,
internalType: "uint256"
},
{
name: "paid1",
type: "uint256",
indexed: false,
internalType: "uint256"
}
],
anonymous: false
},
{
type: "event",
name: "IncreaseObservationCardinalityNext",
inputs: [
{
name: "observationCardinalityNextOld",
type: "uint16",
indexed: false,
internalType: "uint16"
},
{
name: "observationCardinalityNextNew",
type: "uint16",
indexed: false,
internalType: "uint16"
}
],
anonymous: false
},
{
type: "event",
name: "InitializeObservation",
inputs: [
{
name: "sqrtPriceX96",
type: "uint160",
indexed: false,
internalType: "uint160"
},
{
name: "tick",
type: "int24",
indexed: false,
internalType: "int24"
}
],
anonymous: false
},
{
type: "event",
name: "Mint",
inputs: [
{
name: "sender",
type: "address",
indexed: false,
internalType: "address"
},
{
name: "owner",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "tickLower",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "tickUpper",
type: "int24",
indexed: true,
internalType: "int24"
},
{
name: "amount",
type: "uint128",
indexed: false,
internalType: "uint128"
},
{
name: "amount0",
type: "uint256",
indexed: false,
internalType: "uint256"
},
{
name: "amount1",
type: "uint256",
indexed: false,
internalType: "uint256"
}
],
anonymous: false
},
{
type: "event",
name: "SetFeeProtocol",
inputs: [
{
name: "feeProtocol0Old",
type: "uint8",
indexed: false,
internalType: "uint8"
},
{
name: "feeProtocol1Old",
type: "uint8",
indexed: false,
internalType: "uint8"
},
{
name: "feeProtocol0New",
type: "uint8",
indexed: false,
internalType: "uint8"
},
{
name: "feeProtocol1New",
type: "uint8",
indexed: false,
internalType: "uint8"
}
],
anonymous: false
},
{
type: "event",
name: "Swap",
inputs: [
{
name: "sender",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "recipient",
type: "address",
indexed: true,
internalType: "address"
},
{
name: "amount0",
type: "int256",
indexed: false,
internalType: "int256"
},
{
name: "amount1",
type: "int256",
indexed: false,
internalType: "int256"
},
{
name: "sqrtPriceX96",
type: "uint160",
indexed: false,
internalType: "uint160"
},
{
name: "liquidity",
type: "uint128",
indexed: false,
internalType: "uint128"
},
{
name: "tick",
type: "int24",
indexed: false,
internalType: "int24"
}
],
anonymous: false
},
{
type: "error",
name: "AlreadyInitialized",
inputs: [
]
},
{
type: "error",
name: "BalanceQueryFailed",
inputs: [
]
},
{
type: "error",
name: "FlashFee0NotReceived",
inputs: [
]
},
{
type: "error",
name: "FlashFee1NotReceived",
inputs: [
]
},
{
type: "error",
name: "InsufficientBalance0",
inputs: [
]
},
{
type: "error",
name: "InsufficientBalance1",
inputs: [
]
},
{
type: "error",
name: "InsufficientInputAmount",
inputs: [
]
},
{
type: "error",
name: "InvalidFeeProtocol",
inputs: [
]
},
{
type: "error",
name: "InvalidTickOrder",
inputs: [
]
},
{
type: "error",
name: "Locked",
inputs: [
]
},
{
type: "error",
name: "LowerTickNotInitialized",
inputs: [
]
},
{
type: "error",
name: "MintZeroAmount",
inputs: [
]
},
{
type: "error",
name: "NoDelegateCallError",
inputs: [
]
},
{
type: "error",
name: "NoLiquidity",
inputs: [
]
},
{
type: "error",
name: "OnlyFactoryOwner",
inputs: [
]
},
{
type: "error",
name: "SqrtPriceLimit",
inputs: [
]
},
{
type: "error",
name: "TickLowerBelowMinimum",
inputs: [
]
},
{
type: "error",
name: "TickUpperAboveMaximum",
inputs: [
]
},
{
type: "error",
name: "UpperTickNotInitialized",
inputs: [
]
},
{
type: "error",
name: "ZeroSwapAmount",
inputs: [
]
}
];
/**
* @title Pool Contract
* @notice Contract wrapper for Evx Pool interactions
* @dev Provides methods to interact with a specific pool instance
*/
class PoolContract {
/**
* @notice Creates a new pool contract instance
* @param address The address of the pool contract
*/
constructor(address) {
this.address = address;
this.rpc = tsyringe.container.resolve(exports.RPC);
this.instance = new ethers.ethers.Contract(address, PoolABI, this.rpc.provider);
}
/**
* @notice Sets the signer for pool contract interactions
* @param signer The signer to use for transactions
*/
async setSigner(signer) {
if (!signer) {
this.instance = new ethers.ethers.Contract(this.address, PoolABI, this.rpc.provider);
return;
}
this.instance = new ethers.ethers.Contract(this.address, PoolABI, signer);
}
}
var PositionManagerABI = [
{
type: "constructor",
inputs: [
{
name: "_factory",
type: "address",
internalType: "address"
},
{
name: "_WETH9",
type: "address",
internalType: "address"
},
{
name: "_tokenDescriptor_",
type: "address",
internalType: "address"
}
],
stateMutability: "nonpayable"
},
{
type: "receive",
stateMutability: "payable"
},
{
type: "function",
name: "DOMAIN_SEPARATOR",
inputs: [
],
outputs: [
{
name: "",
type: "bytes32",
internalType: "bytes32"
}
],
stateMutability: "view"
},
{
type: "function",
name: "PERMIT_TYPEHASH",
inputs: [
],
outputs: [
{
name: "",
type: "bytes32",
internalType: "bytes32"
}
],
stateMutability: "view"
},
{
type: "function",
name: "WETH9",
inputs: [
],
outputs: [
{
name: "",
type: "address",
internalType: "address"
}
],
stateMutability: