리소스 로딩... 로딩...

FMZ Quant Uniswap V3 거래소 풀 유동성 관련 거래 안내 (1부)

저자:FMZ~리디아, 창작: 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부)

Uniswap V3에서 비변형 포지션 매니저 계약

유니스와프 V3 유동성 풀 (거래 쌍 풀) 에 유동성을 추가할 때, NonfungiblePositionManager 계약은 유동성 추가의 증거로 발주된 NFT를 우리에게 반환합니다.

첫 번째 단계는 라우터 계약을 사용하여 해당 NonfungiblePositionManager 계약의 주소를 얻고, 그 다음 NonfungiblePositionManager 계약의 balanceOf 방법을 사용하여 지정된 지갑 주소의 위치 NFT 수를 얻는 것입니다.

그 다음 tokenOfOwnerByIndex 방법을 사용하여 NFT 위치의 토큰Id를 얻습니다. 이 토큰Id를 사용하면 위치 방법을 사용하여 이러한 위치의 특정 세부 정보를 계속 검색 할 수 있습니다.

다음 테스트 코드:

// Uniswap ABI const ABI_UniswapV3Router =[inputs:[{internalType:address,name:_factoryV2,type:address},{internalType:address,type:address},{internalType:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input:input: const ABI_NonfungiblePositionManager =[입수:[{internalType:address,name:_factory,type:address},{internalType:address,name:_WETH9,type:address},{internalType:address,name:tokenDescriptor,type:address}],stateMutability:nonpayable,type:constructor},{anonymous:false,inputs:[indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,stateMutability:nonpayable,type:approved,type:address},{indexed:true,internalType:additive:additive:additive:additive:additive:type:additive:additive:additive:additive:additive ABI_Pool = [\inputs\:[],\stateMutability:\nonpayable\,\type\:\constructor\,\name:\anonymous\:\false,\inputs\:[\\indexed\:true,\internalType\:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ ABI_Factory = [\inputs\:[],\stateMutability:\\nonpayable\,\type\:\constructor\,\\anonymous\:\false,\inputs\:[\\\\\\\\\inded\:true,\internalType\:\uint24\,\\\name\:\fee\,\\\\\\\type\:\\uint24\,\\\\\indexed\:true,\\\internaladdaddaddaddtype\:\uint24\,\\name\:\anonymous\:\addaddaddtype\:\:false,\addtype\:\type\:\type\:\:\"internaladdname\:\,\type\:\:\type\:\:\"type\:\:\"type\:\:\"

// Uniswap 계약 주소 const UniswapV3RouterAddress = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 const 계약V3공장 = 0x1F98431c8aD98523631AE4a59f267346ea31F984

// 공통 상수 const TWO = BigInt(2) const Q192 = (TWO ** BigInt(96)) ** TWO const Q96 = (TWO ** BigInt ((96))

// 읽을 수 있는 양으로 변환 함수 toAmount ((s, 소수점) { 반환 번호 (BigDecimal) / BigDecimal (Math.pow), 10개의 소수점 (decimal) }

// 가독 가능한 양에서 매개 변수 및 계산에 사용되는 양으로 역 변환 함수 toInnerAmount ((n, 소수점) { 반환 (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 토큰 = [] 함수 init() { // 초기화 할 때, 모든 토큰에 대한 정보를 얻을 수 var res = JSON.parse ((HttpQuery))https://tokens.coingecko.com/uniswap/all.json”)) 로그 ((fetch, res.tokens.length, tokens from, res.name) _.each ((res.tokens, function ((token) {) 토큰. 푸시. 이름: 토큰.명, 기호: token.symbol, 소수점: token.decimal, 주소: token.address }) }) 로그 (( 토큰:, 토큰) }

함수 파서PosData ((posData) { /* ♪ 공고: 0, 운영자: 0x0000000000000000000000000000000000000000 토큰1: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 료: 3000, 세성장내0마지막X128: 552824104363438506727784685971981736468, GrowthInside1 LastX128: 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

더 많은 내용