104 lines
4.6 KiB
Python
104 lines
4.6 KiB
Python
|
|
import os
|
|
import sys
|
|
import json
|
|
from web3 import Web3
|
|
from dotenv import load_dotenv
|
|
from decimal import Decimal
|
|
|
|
# Add project root
|
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
|
|
# Load Env
|
|
load_dotenv()
|
|
|
|
RPC_URL = os.environ.get("MAINNET_RPC_URL") # Arbitrum RPC
|
|
POOL_ADDRESS = "0xC6962004f452bE9203591991D15f6b388e09E8D0" # ARB/WETH 500
|
|
|
|
ERC20_ABI = [
|
|
{"constant": True, "inputs": [], "name": "symbol", "outputs": [{"name": "", "type": "string"}], "payable": False, "stateMutability": "view", "type": "function"},
|
|
{"constant": True, "inputs": [], "name": "decimals", "outputs": [{"name": "", "type": "uint8"}], "payable": False, "stateMutability": "view", "type": "function"},
|
|
{"constant": True, "inputs": [{"name": "_owner", "type": "address"}], "name": "balanceOf", "outputs": [{"name": "balance", "type": "uint256"}], "payable": False, "stateMutability": "view", "type": "function"}
|
|
]
|
|
|
|
POOL_ABI = [
|
|
{"inputs": [], "name": "slot0", "outputs": [{"internalType": "uint160", "name": "sqrtPriceX96", "type": "uint160"}, {"internalType": "int24", "name": "tick", "type": "int24"}, {"internalType": "uint16", "name": "observationIndex", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinality", "type": "uint16"}, {"internalType": "uint16", "name": "observationCardinalityNext", "type": "uint16"}, {"internalType": "uint32", "name": "feeProtocol", "type": "uint32"}, {"internalType": "bool", "name": "unlocked", "type": "bool"}], "stateMutability": "view", "type": "function"},
|
|
{"inputs": [], "name": "liquidity", "outputs": [{"internalType": "uint128", "name": "", "type": "uint128"}], "stateMutability": "view", "type": "function"},
|
|
{"inputs": [], "name": "token0", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
|
|
{"inputs": [], "name": "token1", "outputs": [{"internalType": "address", "name": "", "type": "address"}], "stateMutability": "view", "type": "function"},
|
|
{"inputs": [], "name": "fee", "outputs": [{"internalType": "uint24", "name": "", "type": "uint24"}], "stateMutability": "view", "type": "function"}
|
|
]
|
|
|
|
def main():
|
|
if not RPC_URL:
|
|
print("Error: MAINNET_RPC_URL not found in .env")
|
|
return
|
|
|
|
w3 = Web3(Web3.HTTPProvider(RPC_URL))
|
|
if not w3.is_connected():
|
|
print("Error: Could not connect to RPC")
|
|
return
|
|
|
|
print(f"Connected to Arbitrum: {w3.eth.block_number}")
|
|
|
|
pool_contract = w3.eth.contract(address=POOL_ADDRESS, abi=POOL_ABI)
|
|
|
|
# 1. Metadata
|
|
t0_addr = pool_contract.functions.token0().call()
|
|
t1_addr = pool_contract.functions.token1().call()
|
|
fee = pool_contract.functions.fee().call()
|
|
|
|
t0_contract = w3.eth.contract(address=t0_addr, abi=ERC20_ABI)
|
|
t1_contract = w3.eth.contract(address=t1_addr, abi=ERC20_ABI)
|
|
|
|
t0_sym = t0_contract.functions.symbol().call()
|
|
t1_sym = t1_contract.functions.symbol().call()
|
|
t0_dec = t0_contract.functions.decimals().call()
|
|
t1_dec = t1_contract.functions.decimals().call()
|
|
|
|
print(f"\nPool: {t0_sym} / {t1_sym} ({fee/10000}%)")
|
|
print(f"Token0: {t0_sym} ({t0_addr}) - {t0_dec} dec")
|
|
print(f"Token1: {t1_sym} ({t1_addr}) - {t1_dec} dec")
|
|
|
|
# 2. State
|
|
slot0 = pool_contract.functions.slot0().call()
|
|
sqrt_price = slot0[0]
|
|
tick = slot0[1]
|
|
liquidity = pool_contract.functions.liquidity().call()
|
|
|
|
print(f"\nState:")
|
|
print(f"Liquidity: {liquidity}")
|
|
print(f"Tick: {tick}")
|
|
print(f"SqrtPriceX96: {sqrt_price}")
|
|
|
|
# 3. Price Calc
|
|
# price = (sqrt / 2^96)^2
|
|
p = (Decimal(sqrt_price) / Decimal(2**96)) ** 2
|
|
|
|
# Adjust for decimals: Price = raw_price * 10^(d0 - d1)
|
|
adj_price = p * (Decimal(10) ** (t0_dec - t1_dec))
|
|
inv_price = Decimal(1) / adj_price if adj_price > 0 else 0
|
|
|
|
print(f"\nPrices:")
|
|
print(f"1 {t0_sym} = {adj_price:.6f} {t1_sym}")
|
|
print(f"1 {t1_sym} = {inv_price:.6f} {t0_sym}")
|
|
|
|
# 4. TVL Estimation (Balances)
|
|
t0_bal = t0_contract.functions.balanceOf(POOL_ADDRESS).call()
|
|
t1_bal = t1_contract.functions.balanceOf(POOL_ADDRESS).call()
|
|
|
|
t0_human = Decimal(t0_bal) / Decimal(10**t0_dec)
|
|
t1_human = Decimal(t1_bal) / Decimal(10**t1_dec)
|
|
|
|
print(f"\nTVL (Locked in Contract):")
|
|
print(f"{t0_human:,.2f} {t0_sym}")
|
|
print(f"{t1_human:,.2f} {t1_sym}")
|
|
|
|
# Assume WETH is approx 3350 (or whatever current market is, we can use slot0 price if one is stable)
|
|
# If one is USD stable, we can calc total.
|
|
# ARB / WETH. WETH is ~$3300.
|
|
# Let's just output raw.
|
|
|
|
if __name__ == "__main__":
|
|
main()
|