Depois de adicionarmos liquidez ao pool de liquidez da Uniswap V3, o contrato NonfungiblePositionManager retornará uma NFT forjada para nós como credencial de adição de liquidez. O primeiro passo é usar um contrato de roteamento para obter o endereço correspondente do contrato do NonfungiblePositionManager, e depois usar o método balanceOf do contrato do NonfungiblePositionManager para obter o número de NFTs de posição do endereço de carteira especificado. Em seguida, o método tokenOfOwnerByIndex é usado para obter o tokenId dessas posições NFT, e com esses tokenId, o método positions pode ser usado para obter mais detalhes sobre essas posições.
O código do teste é o seguinte:
“javascript
// Uniswap ABI
const ABI_UniswapV3Router =
[
const ABI_NonfungiblePositionManager =
[{
// Endereço do contrato Uniswap
const UniswapV3RouterAddress =
// quantidade usada const TWO = BigInt ((2) const Q192 = (TWO ** BigInt ((96)) ** TWO const Q96 = (TWO ** BigInt ((96))
// Converte-se em quantidade de leitura função toAmount ((s, decimais) { return Number (BigDecimal (BigInt)) / BigDecimal (Math.pow (), decimais))).toString ()) Não.
// Converte inversamente o número de leitura para o número de dados a serem transmitidos e calculados função toInnerAmount ((n, decimais) { return (BigDecimal ((n) * BigDecimal ((Math.pow ((10, decimais))).toFixed ((0) Não.
função main() {
// endereço da carteira a ser pesquisado
// const walletAddress = exchange.IO ((
// 获取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) + "`")
}
// Regista as informações sobre os tokens consultados pelo coingecko.com
Var tokens = []
função init (()) {
// Obter informações de todos os tokens no momento da inicialização, para ser usado para fazer consultas
Var res = JSON.parse (httpQuery)https://tokens.coingecko.com/uniswap/all.json”))
Log ((
Função parsePosData ((posData) {
/*
- O quê?
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,
Crypto Joe.É muito forte!