如何将Uniswap V3相关JS代码的console.log输出保存到文件?
如何将Uniswap V3数据的console.log输出保存到文件(适配Python解析)
要把代码中打印的代币数据保存到文件并方便Python解析,最直接的方式是将输出整理为JSON结构化格式后写入文件,而非单纯捕获console.log的文本输出。以下是具体修改方案:
一、修改JavaScript代码,写入结构化JSON数据
你的代码已经导入了fs模块,只需调整getTokenAmounts函数,将需要保存的数据整理为对象后写入文件,同时保留原有控制台输出:
import { JSBI } from "@uniswap/sdk"; import { ethers } from 'ethers'; import * as fs from 'fs'; // ERC20 JSON ABI 文件 let ERC20Abi = fs.readFileSync('ERC20.json'); const ERC20 = JSON.parse(ERC20Abi); // V3 池 ABI JSON 文件 let pool = fs.readFileSync('V3PairAbi.json'); const IUniswapV3PoolABI = JSON.parse(pool); // V3 工厂 ABI JSON 文件 let facto = fs.readFileSync('V3factory.json'); const IUniswapV3FactoryABI = JSON.parse(facto); let NFT = fs.readFileSync('UniV3NFT.json'); const IUniswapV3NFTmanagerABI = JSON.parse(NFT); const provider = new ethers.providers.JsonRpcProvider(ALCHEMY) // V3 标准地址(Celo 链不同) const factory = FACTORY; const NFTmanager = NFTMANAGER; async function getData(tokenID){ let FactoryContract = new ethers.Contract(factory, IUniswapV3FactoryABI, provider); let NFTContract = new ethers.Contract(NFTmanager, IUniswapV3NFTmanagerABI, provider); let position = await NFTContract.positions(tokenID); let token0contract = new ethers.Contract(position.token0, ERC20, provider); let token1contract = new ethers.Contract(position.token1, ERC20, provider); let token0Decimal = await token0contract.decimals(); let token1Decimal = await token1contract.decimals(); let token0sym = await token0contract.symbol(); let token1sym = await token1contract.symbol(); let V3pool = await FactoryContract.getPool(position.token0, position.token1, position.fee); let poolContract = new ethers.Contract(V3pool, IUniswapV3PoolABI, provider); let slot0 = await poolContract.slot0(); let pairName = token0sym +"/"+ token1sym; let dict = {"SqrtX96" : slot0.sqrtPriceX96.toString(), "Pair": pairName, "T0d": token0Decimal, "T1d": token1Decimal, "tickLow": position.tickLower.toString(), "tickHigh": position.tickUpper.toString(), "liquidity": position.liquidity.toString()} return dict } const Q96 = JSBI.exponentiate(JSBI.BigInt(2), JSBI.BigInt(96)); const MIN_TICK = -887272; const MAX_TICK = 887272; function getTickAtSqrtRatio(sqrtPriceX96){ let tick = Math.floor(Math.log((sqrtPriceX96/Q96)**2)/Math.log(1.0001)); return tick; } async function getTokenAmounts(liquidity,sqrtPriceX96,tickLow,tickHigh,token0Decimal,token1Decimal){ let sqrtRatioA = Math.sqrt(1.0001**tickLow).toFixed(18); let sqrtRatioB = Math.sqrt(1.0001**tickHigh).toFixed(18); let currentTick = getTickAtSqrtRatio(sqrtPriceX96); let sqrtPrice = sqrtPriceX96 / Q96; let amount0wei = 0; let amount1wei = 0; if(currentTick <= tickLow){ amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtRatioA)/(sqrtRatioA*sqrtRatioB))); } if(currentTick > tickHigh){ amount1wei = Math.floor(liquidity*(sqrtRatioB-sqrtRatioA)); } if(currentTick >= tickLow && currentTick < tickHigh){ amount0wei = Math.floor(liquidity*((sqrtRatioB-sqrtPrice)/(sqrtPrice*sqrtRatioB))); amount1wei = Math.floor(liquidity*(sqrtPrice-sqrtRatioA)); } let amount0Human = (amount0wei/(10**token0Decimal)).toFixed(token0Decimal); let amount1Human = (amount1wei/(10**token1Decimal)).toFixed(token1Decimal); // 整理需要保存的结构化数据 const outputData = { amount0Wei: amount0wei.toString(), amount1Wei: amount1wei.toString(), amount0Human: amount0Human, amount1Human: amount1Human, liquidity: liquidity, sqrtPriceX96: sqrtPriceX96.toString(), tickLow: tickLow.toString(), tickHigh: tickHigh.toString(), token0Decimal: token0Decimal, token1Decimal: token1Decimal }; // 保留原有控制台输出 console.log("Amount Token0 wei: "+amount0wei); console.log("Amount Token1 wei: "+amount1wei); console.log("Amount Token0 : "+amount0Human); console.log("Amount Token1 : "+amount1Human); // 写入JSON文件(追加模式,避免覆盖已有数据) try { fs.appendFileSync('uniswap_v3_token_data.json', JSON.stringify(outputData) + '\n'); console.log("数据已写入文件: uniswap_v3_token_data.json"); } catch (err) { console.error("写入文件失败:", err); } return [amount0wei, amount1wei] } async function start(positionID){ let data = await getData(positionID); let tokens = await getTokenAmounts(data.liquidity, data.SqrtX96, data.tickLow, data.tickHigh, data.T0d, data.T1d); // 可选:将仓位信息与代币数据整合后单独保存 const fullPositionData = { ...data, amount0Wei: tokens[0].toString(), amount1Wei: tokens[1].toString() }; try { fs.appendFileSync('uniswap_v3_full_position_data.json', JSON.stringify(fullPositionData) + '\n'); console.log("完整仓位数据已写入文件: uniswap_v3_full_position_data.json"); } catch (err) { console.error("写入完整仓位数据失败:", err); } } start(POOLID) // 若自行获取数据,无需仓位信息也可适用于任何区间 getTokenAmounts(12558033400096537032, 20259533801624375790673555415)
修改说明:
- 将所有需要保存的字段整理为
outputData对象,确保数据类型可被JSON序列化(BigInt或大数转为字符串) - 使用
fs.appendFileSync以追加模式写入文件,每次运行新增一条数据,避免覆盖历史记录 - 可选:在
start函数中整合仓位信息与代币数据,生成更完整的输出文件
二、Python解析JSON文件示例
由于保存的是每行一个JSON对象的格式,Python可以逐行读取解析,无需一次性加载全部数据:
import json # 解析代币数量数据文件 with open('uniswap_v3_token_data.json', 'r', encoding='utf-8') as f: for line in f: try: data = json.loads(line.strip()) print(f"Token0 可读数量: {data['amount0Human']}") print(f"Token1 Wei数量: {data['amount1Wei']}") # 按需处理其他字段 except json.JSONDecodeError as e: print(f"解析行失败: {e}") # 解析完整仓位数据文件 with open('uniswap_v3_full_position_data.json', 'r', encoding='utf-8') as f: for line in f: try: data = json.loads(line.strip()) print(f"交易对: {data['Pair']}") print(f"当前价格SqrtX96: {data['SqrtX96']}") # 按需处理其他字段 except json.JSONDecodeError as e: print(f"解析行失败: {e}")
三、备选方案:命令行重定向输出
如果不需要结构化数据,仅需捕获所有console.log输出,可在运行代码时使用命令行重定向:
node your_script_name.js > uniswap_output.txt 2>&1
>将标准输出写入文件2>&1将错误输出也重定向到同一文件
但这种方式输出的是纯文本,Python解析时需要手动处理字符串分割,不如JSON格式高效。
内容的提问来源于stack exchange,提问作者beeeZeee
相关产品推荐
相关产品推荐

