Sumber dimuat naik... memuat...

FMZ Kuantitatif Uniswap V3 Panduan Operasi yang berkaitan dengan Likuiditi Kolam Pertukaran (1)

Penulis:Pencipta Kuantiti - Impian Kecil, Dicipta: 2023-07-14 17:36:55, Dikemas kini: 2024-11-11 22:38:18

FMZ量化Uniswap V3兑换池流动性相关操作指南(一)

Kontrak Pengurus Posisi Nonfungible dalam Uniswap V3

Apabila kita menambah kecairan ke dalam kumpulan kecairan Uniswap V3, kontrak NonfungiblePositionManager akan mengembalikan NFT yang dicipta kepada kita sebagai bukti kecairan yang ditambahkan. Langkah pertama adalah menggunakan kontrak penghalaan untuk mendapatkan alamat kontrak NonfungiblePositionManager yang sesuai, dan kemudian menggunakan kaedah balanceOf kontrak NonfungiblePositionManager untuk mendapatkan jumlah NFT kedudukan di alamat dompet tertentu. TokenId dari posisi-posisi NFT ini akan diperoleh dengan menggunakan kaedah tokenOfOwnerByIndex, dan dengan tokenId ini, anda boleh menggunakan kaedah posisi untuk mendapatkan maklumat lanjut mengenai kedudukan tertentu.

Di bawah ini adalah kod ujian:

javascript // Uniswap ABI const ABI_UniswapV3Router =[inputs:[{internalType:address,name:_factory,name:type:address},{internalType:address,type:address},{internalType:factory,name:factoryV3,type:address},{internalType:address,type:address},{internalType:address,inputs:address,name:positionManager,type:address},{internalType:address,name:_WETH9,internalType:address,type:address,type:address,type:address,typeaddress,typeaddress,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:address,type:approved,type:address},{indexed:true,type:addidentified,typeadditive:additive,typeadditive ABI_Pool = [\\inputs\:[],\stateMutability\:\nonpayable\,\type\:\constructor\,\name\:\anonymous\:\false,\inputs\:[\\\indexed\:true,\internalType\:\address\:\stateMutability\:\nonpayable\,\type\:\\\constructor\,\anonymous\:\false,\inputs\:\:\inputs\:\:\\\indexed\:\true,\internalType\:\address\,\name\,\internalType\,\type\,\\\\\\\\\\"type\\\\\"type\\\\\"type\\\\" ABI_Factory = [\\inputs\:[],\stateMutability \:\\nonpayable\,\\\type\:\\\addaddconstructor\,\\\\name\anonymous\:\false,\\inputs\:[\\\\indexed\:true,\\\internalType\:\uint24\,\\\name\:\fee\,\\\\\\type\:\\\uint24\,\\\indexed\:type\:\nonpayable\:\\internalAddAddType\:\addtype\:\\addon24\,\\name\:\"anonymous\:\addaddaddaddtype\:\"false,\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\"\

// Alamat kontrak Uniswap const UniswapV3RouterAddress = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 const KontrakV3Kilang = 0x1F98431c8aD98523631AE4a59f267346ea31F984

// Pengambilan biasa const TWO = BigInt ((2) const Q192 = (TWO ** BigInt ((96)) ** TWO const Q96 = (TWO ** BigInt ((96))

// Mengubah kepada jumlah yang boleh dibaca function toAmount ((s, decimals) { return Number (BigDecimal (BigInt)) / BigDecimal (Math.pow (), decimals))).toString ()) {C:$0000FF}

// Mengubah bilangan yang boleh dibaca secara terbalik kepada jumlah yang digunakan untuk penghantaran, pengiraan function toInnerAmount ((n, decimals) { return (BigDecimal ((n) * BigDecimal ((Math.pow ((10, decimals))).toFixed ((0) {C:$0000FF}

fungsi utama (() { // Alamat dompet yang ingin ditanyakan // const walletAddress = exchange.IO ((address bar) const walletAddress = 0x28df8b987BE232bA33FdFB8Fc5058C1592A3db26

// 获取Uniswap V3的positionManager合约的地址
exchange.IO("abi", UniswapV3RouterAddress, ABI_UniswapV3Router)
const NonfungiblePositionManagerAddress = exchange.IO("api", UniswapV3RouterAddress, "positionManager")
Log("NonfungiblePositionManagerAddress:", NonfungiblePositionManagerAddress)

// 注册positionManager合约的ABI
exchange.IO("abi", NonfungiblePositionManagerAddress, ABI_NonfungiblePositionManager)

// 查询当前账户拥有的Uniswap V3 positions NFT数量
var nftBalance = exchange.IO("api", NonfungiblePositionManagerAddress, "balanceOf", walletAddress)
Log("nftBalance:", nftBalance)

// 查询这些NFT的TokenId
var nftTokenIds = []
for (var i = 0 ; i < nftBalance; i++) {
    var nftTokenId = exchange.IO("api", NonfungiblePositionManagerAddress, "tokenOfOwnerByIndex", walletAddress, i)
    nftTokenIds.push(nftTokenId)
    Log("nftTokenId:", nftTokenId)
}

// 根据positions NFT的tokenId查询流动性头寸详细信息
var positions = []
for (var i = 0; i < nftTokenIds.length; i++) {
    var pos = exchange.IO("api", NonfungiblePositionManagerAddress, "positions", nftTokenIds[i])        
    Log("pos:", pos)

    // 解析头寸数据
    positions.push(parsePosData(pos))
}

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

}

// Mencatatkan maklumat token yang diminta melalui coingecko.com var tokens = [] function init (() { // Mengambil maklumat semua token pada masa permulaan untuk digunakan untuk membuat pertanyaan var res = JSON.parse ((HttpQuery))https://tokens.coingecko.com/uniswap/all.json”)) Log ((cari, res.tokens.length, tokens dari, res.name) _.each ((res.tokens, fungsi ((token) { token.push ((({ nama: token.name, simbol: token.symbol, decimal: token.decimal, alamat: token.address {y: i} {y: i} Log ((token:, token) {}

fungsi parsePosData ((posData) { /* { pengumuman: 0 operator: 0x0000000000000000000000000000000000000000, token1: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2, biaya: 3000, biaya Pertumbuhan Dalam Negeri0LastX128: 552824104363438506727784685971981736468, biaya Pertumbuhan Dalam Negeri1LastX128: 2419576808699564757520565912733367379, tokensDebt0: 0, tokensDebted1: 0, token0: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984, tickLower: -62160, tickUpper: -41280, likiditi: 19090316141441365693 {} */

var token0Symbol = null
var token1Symbol = null
// 根据代币地址判断token,记录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 ,获取兑换池的相关数据
var poolInfo = getPool(token0Symbol.address, token1Symbol.address, posData.fee)
Log("poolInfo:", poolInfo)
/* 数据范例
{
    "slot0":{
        "sqrtPriceX96":"4403124416947951698847768103","tick":"-57804","observationIndex":136,"observationCardinality":300,
        "observationCardinalityNext":300,"feeProtocol":0,"unlocked":true
    }
}
*/

// 计算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 && currentTick < posData.tickUpper) {
    amount0wei = Math.floor(posData.liquidity * ((sqrtRatioB - sqrtPrice) / (sqrtPrice * sqrtRatioB)))
    amount1wei = Math.floor(posData.liquidity * (sqrtPrice - sqrtRatioA))
}

var rangeToken0 = (1.0001 ** -posData.tickUpper) + " ~ " + (1.0001 ** -posData.tickLower)
var amount0 = toAmount(amount0wei, token0Symbol.decimals)
var amount1 = toAmount(amount1wei, token1Symbol.decimals)

return [rangeToken0, token0Symbol.symbol,

Kandungan berkaitan

Lebih lanjut

Crypto JoeIa terlalu kuat!