রিসোর্স লোড হচ্ছে... লোডিং...

FMZ কোয়ালিফাইড Uniswap V3 এক্সচেঞ্জ পুকুর তরলতা সম্পর্কিত অপারেশন গাইড (১)

লেখক:উদ্ভাবকগণ - ক্যোটিফিকেশন - ছোট্ট স্বপ্ন, সৃষ্টিঃ ২০২৩-০৭-১৪ ১৭ঃ৩৬ঃ৫৫, আপডেটঃ ২০২৪-১১-১১ ২২ঃ৩৮ঃ১৮

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

Uniswap V3-এ নন-ফুঞ্জিবল পজিশন ম্যানেজার চুক্তি

যখন আমরা Uniswap V3 এর লিকুইডিটি পুল (ট্রেড-টু-পুল) তে লিকুইডিটি যোগ করি, তখন NonfungiblePositionManager চুক্তিটি একটি তৈরি NFT ফেরত দেয় যা আমাদের লিকুইডিটি যোগ করার প্রমাণ হিসাবে। প্রথম ধাপে, আমরা একটি রুটিং চুক্তি ব্যবহার করে একটি সংশ্লিষ্ট NonfungiblePositionManager চুক্তি ঠিকানা অর্জন করি, এবং তারপর NonfungiblePositionManager চুক্তির balanceOf পদ্ধতি ব্যবহার করে একটি নির্দিষ্ট ওয়ালেট ঠিকানার জন্য অবস্থান NFT সংখ্যা অর্জন করি। এরপরে, টোকেন অফ ওয়ানার বাই ইনডেক্স পদ্ধতি ব্যবহার করে এই অবস্থানগুলির টোকেন আইডিগুলি এনএফটি-তে পাওয়া যায়, এবং এই টোকেন আইডিগুলির সাথে আপনি অবস্থানগুলি পদ্ধতি ব্যবহার করে এই অবস্থানগুলির জন্য বিস্তারিত তথ্য অনুসন্ধান করতে পারেন।

এখানে পরীক্ষার কোড দেওয়া হলঃ

javascript // 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:address:address:address:address:address:address:},{internalType:address:address:address:address:type: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},{anonymous:false,inputs:[indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,name:owner,type:address},{indexed:true,internalType:address,type:address},{stateMutability:nonpayable,type:approved,type:address},{anonymous:true,internalType:false,input:input:true,input:true,input:true,input:true, ABI_Pool = [\\inputs\:[],\stateMutability\:\nonpayable\,\type\:\constructor\,\name:\anonymous\:\false,\inputs\:[\\indexed\:true,\internalType\:\address\:\stateMutability\:\nonpayable\,\type\:\\constructor\,\anonymous\:\false,\inputs\:\inputs\:\:\inputs\:\inputs\:\inputs\:\inputs\:\inputs\:\input\:\input\:\input\:\input\:\input\:\input\:\input\ ABI_Factory = [\\inputs\:[],\stateMutability\:\\nonpayable\,\\\type\:\\addaddconstructor\,\\name\:\anonymous\:\false,\inputs\:[\\\indexed\:true,\\internalType\:\uint24\,\\name\:\fee\,\\\\\type\:\uint24\,\\\indexed\:true,\\internaladdaddaddtype\:\addtype\:\:\addaddaddtype\:\:\addtype\:\:false,\addtype\:false,\type\:\type\:\type\:\type\:\type\:\"internaladdname\:\type\:false,\type\:\type\:\:\\\"type\:\

// Uniswap চুক্তির ঠিকানা const UniswapV3RouterAddress = 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 const ContractV3Factory = 0x1F98431c8aD98523631AE4a59f267346ea31F984

// সাধারণ পরিমাণ const TWO = বিগইন্ট (২) const Q192 = (TWO ** BigInt ((96)) ** TWO const Q96 = (TWO ** BigInt ((96))

// পাঠযোগ্য সংখ্যায় রূপান্তরিত function toAmount ((s, decimals) { return Number (((BigDecimal ((BigInt)) s)) / BigDecimal ((Math.pow ((10, decimals))).toString (()) }

// পাঠযোগ্য সংখ্যার বিপরীত রূপান্তর করে গণনা করার জন্য ব্যবহৃত সংখ্যায় function toInnerAmount ((n, decimals) { return (BigDecimal ((n) * BigDecimal ((Math.pow ((10, decimals))).toFixed ((0) }

function main (() { // যে ওয়ালেটের ঠিকানাটি অনুসন্ধান করা হচ্ছে // const walletAddress = exchange.IO ((address ট্যাব) 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) + "`")

}

// coingecko.com দ্বারা অনুসন্ধান করা টোকেন তথ্য রেকর্ড করে var tokens = [] ফাংশন 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) {) টোকেন. push ((( নামঃ টোকেন.নাম, প্রতীক: token.symbol, দশমিক সংখ্যাঃ token.decimal, ঠিকানাঃ token.address }) }) লগ (( টোকেনঃ, টোকেন) }

ফাংশন পার্সপোসডাটা ((পোসডাটা) { /* { ঘোষণা: 0, অপারেটর : 0x000000000000000000000000000000000000 , টোকন১: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2, ফি: 3000, ফীGrowthInside0LastX128: 552824104363438506727784685971981736468, ফী গ্রোথইনসাইড১শেষ এক্স১২৮: ২৪১৯৫৭৬৮৬৮৬৯৯৫৬৪৭৫৭৫২০৫৬৫৯১২৭৩৩৩৬৭৩৭৯, টোকন ঋণ : 0, টোকন ঋণ : 0, token0: 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984, টিকডাউনঃ -62160, টিক আপ : -41280 , লিকুইডিটি: 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,

সম্পর্কিত বিষয়বস্তু

আরও দেখুন

ক্রিপ্টো জোএটা খুব শক্তিশালী!