В процессе загрузки ресурсов... загрузка...

FMZ Quant Uniswap V3 Руководство по операциям, связанным с ликвидностью биржевых пулов (часть 1)

Автор:FMZ~Lydia, Создано: 2023-07-21 09:22:33, Обновлено: 2024-11-11 22:37:08

FMZ Quant Uniswap V3 Exchange Pool Liquidity Related Operations Guide (Part 1)

FMZ Quant Uniswap V3 Руководство по операциям, связанным с ликвидностью биржевых пулов (часть 1)

NonfungiblePositionManager контракт в Uniswap V3

Когда мы добавляем ликвидность в пуль ликвидности Uniswap V3 (пуль торговых пар), контракт NonfungiblePositionManager возвращает нам отчеканенный NFT в качестве доказательства добавления ликвидности.

Первый шаг состоит в том, чтобы использовать контракт маршрутизатора для получения адреса соответствующего контракта NonfungiblePositionManager, а затем использовать метод balanceOf контракта NonfungiblePositionManager для получения количества позиций NFT для указанного адреса кошелька.

Затем используйте метод tokenOfOwnerByIndex, чтобы получить tokenId этих позиций NFT, с этими tokenId вы можете использовать метод позиций, чтобы продолжать запрос на конкретные детали этих позиций.

Следующий код испытания:

// Uniswap ABI const ABI_UniswapV3Router =[inputs:[{internalType:address,name:_factoryV2,type:address},{internalType:address,type:address},{internalType:address,name:inputs:factoryV3,type:address},{internalType:address,inputs:address,name:positionManager,type:address},{internalType:address,name:_WETH9,type:address:address:address,type:address:address:address:address,type:address:address:address:address:address:address:address const ABI_NonfungiblePositionManager =[{inputs:[{internalType:address,name:_factory,type:address},{internalType:address,name:_WETH9,type:address},{internalType:address,name:tokenDescriptor,type:address}],stateMutability:nonpayable,type:constructor},{indexed:true:false,inputs:[indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,type:address},{indexed:true,internalType:address,type:approved,type:address},{indexed:true,type:additive,type:additive,type:additive:additive,type: ABI_Pool = [\\inputs\:[],\stateMutability\:\nonpayable\,\type\:\constructor\,\name\:\anonymous\:\false,\inputs\:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\true,\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ABI_Factory = [\\inputs\\:[],\stateMutability\:\\nonpayable\,\\\type\:\\addaddconstructor\,\\\name\anonymous\:\false,\inputs\:\\\\\indexed\:true,\internalType\:\uint24\,\\\name\:\fee\,\\\\\\\type\:\\uint24\,\\\indexed\:true,\\internaladdaddaddtype\:\addtype\:\addaddtype\:\:\addaddtype\:\:\false,\addtype\:\type\:\type\:\type\:\type\:\\type\:\:\\\"internaladdname\:\type\:\type\:\:\"type\:\"type\

// Адрес контракта Uniswap const UniswapV3RouterAddress = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 const Контракт V3Factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984

// общая постоянная const TWO = BigInt(2) const Q192 = (ДВА ** BigInt(96)) ** ДВА const Q96 = (TWO ** BigInt ((96))

// Преобразовать в читаемую сумму функция toAmount ((s, десятичные знаки) { возвращение числа (BigDecimal) (BigInt) (s) / (BigDecimal) (Math.pow), десятичных знаков (toString)) Я не знаю.

// Обратное преобразование от читаемой суммы к сумме, используемой для передачи параметров и расчетов функция toInnerAmount ((n, десятичные знаки) { return (BigDecimal(n) * BigDecimal(Math.pow(10, десятичные цифры))).toFixed(0) Я не знаю.

Функция основной // Адрес кошелька для поиска // const walletAddress = exchange.IO(address) const walletAddress = 0x28df8b987BE232bA33FdFB8Fc5058C1592A3db26

// Get the address of Uniswap V3's positionManager contract
exchange.IO("abi", UniswapV3RouterAddress, ABI_UniswapV3Router)
const NonfungiblePositionManagerAddress = exchange.IO("api", UniswapV3RouterAddress, "positionManager")
Log("NonfungiblePositionManagerAddress:", NonfungiblePositionManagerAddress)

// Register ABI for positionManager contracts
exchange.IO("abi", NonfungiblePositionManagerAddress, ABI_NonfungiblePositionManager)

// Query the number of Uniswap V3 positions NFT owned by the current account
var nftBalance = exchange.IO("api", NonfungiblePositionManagerAddress, "balanceOf", walletAddress)
Log("nftBalance:", nftBalance)

// Query the TokenId of these NFTs
var nftTokenIds = []
for (var i = 0 ; i < nftBalance; i++) {
    var nftTokenId = exchange.IO("api", NonfungiblePositionManagerAddress, "tokenOfOwnerByIndex", walletAddress, i)
    nftTokenIds.push(nftTokenId)
    Log("nftTokenId:", nftTokenId)
}

// Query liquidity position details based on the tokenId of the positions NFT
var positions = []
for (var i = 0; i < nftTokenIds.length; i++) {
    var pos = exchange.IO("api", NonfungiblePositionManagerAddress, "positions", nftTokenIds[i])        
    Log("pos:", pos)

    // Parsing position data
    positions.push(parsePosData(pos))
}

var tbl = {
    type : "table",
    title : "LP",
    cols : ["range(token0 valuation)", "token0", "token1", "fee", "lowerPrice(tickLower)", "upperPrice(tickUpper)", "liquidity", "amount0", "amount1"],
    rows : positions
}
LogStatus("`" + JSON.stringify(tbl) + "`")

}

// Запишите информацию о токенах, запрошенных через coingecko.com var tokens = [] функция init() { // При инициализации, получить информацию о всех токенов для запроса var res = JSON.parse ((HttpQuery))https://tokens.coingecko.com/uniswap/all.json”)) Log (( fetch, res.tokens.length, tokens from, res.name) _.each ((res.tokens, function ((token) {) _.each ((res.tokens, function ((token)) _.each ((res.tokens, function ((token)) _.each ((res.tokens, function ((token)) _.each ((token)) _.each ((res.tokens, function ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) _.each ((token)) Токены.Пуш. имя: token.name, символ: token.symbol, десятичные знаки: token.decimals, Адрес: token.address { \ cHFFFFFF }) { \ cHFFFFFF }) Регистр ((токены:, токены) Я не знаю.

Функция parsePosData ((posData) { /* { Это не так. Объявление: оператор: 0x0000000000000000000000000000000000000000000000000000, токен1: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2, плата: 3000, feeGrowthInside0LastX128: 552824104363438506727784685971981736468, feeGrowthInside1LastX128: 2419576808699564757520565912733367379 токены Должен0: 0, токены Должен 1: 0, токен0: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984, тикНиже: -62160, отметка вверху: -41280, ликвидность: 19090316141441365693 Я не знаю. */

var token0Symbol = null
var token1Symbol = null
// Determine the token according to the address of the token, record the information about the token
for (var i in tokens) {
    if (tokens[i].address.toLowerCase() == posData.token0.toLowerCase()) {
        token0Symbol = tokens[i]
    } else if (tokens[i].address.toLowerCase() == posData.token1.toLowerCase()) {
        token1Symbol = tokens[i]
    }
}

if (!token0Symbol || !token1Symbol) {
	Log("token0Symbol:", token0Symbol, ", token1Symbol:", token1Symbol)
    throw "token not found"
}

// get Pool , obtaining data about the exchange pool
var poolInfo = getPool(token0Symbol.address, token1Symbol.address, posData.fee)
Log("poolInfo:", poolInfo)
/* Data examples
{
    "slot0":{
        "sqrtPriceX96":"4403124416947951698847768103","tick":"-57804","observationIndex":136,"observationCardinality":300,
        "observationCardinalityNext":300,"feeProtocol":0,"unlocked":true
    }
}
*/

// Calculate token0Amount, token1Amount
var currentTick = parseInt(poolInfo.slot0.tick)
var lowerPrice = 1.0001 ** posData.tickLower
var upperPrice = 1.0001 ** posData.tickUpper
var sqrtRatioA = Math.sqrt(lowerPrice)
var sqrtRatioB = Math.sqrt(upperPrice)
var sqrtPrice = Number(BigFloat(poolInfo.slot0.sqrtPriceX96) / Q96)

var amount0wei = 0
var amount1wei = 0
if (currentTick <= posData.tickLower) {
    amount0wei = Math.floor(posData.liquidity * ((sqrtRatioB - sqrtRatioA) / (sqrtRatioA * sqrtRatioB)))
} else if (currentTick > posData.tickUpper) {
    amount1wei = Math.floor(posData.liquidity * (sqrtRatioB - sqrtRatioA))
} else if (currentTick >= posData.tickLower && cu

Больше информации