# // now 通过第三方网址批量获取Mint的Lpaddress

# //web3.js 获取的pastlogs 的结构如下

# const fs = require('fs-extra');
# const { Web3 } = require('web3');
# const deepcopy = require('deepcopy');
# const { ethers } = require("ethers");

# BigInt.prototype.toJSON = function () {
#     return this.toString()
# }

# // const standardTokenAbi = [{ "constant": false, "inputs": [{ "internalType": "address", "name": "spender", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "approve", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": true, "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }, { "internalType": "address", "name": "spender", "type": "address" }], "name": "allowance", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], "name": "balanceOf", "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "name", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [{ "internalType": "string", "name": "", "type": "string" }], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [{ "internalType": "address", "name": "recipient", "type": "address" }, { "internalType": "uint256", "name": "amount", "type": "uint256" }], "name": "transfer", "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "owner", "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }];
# import time
# import asyncio
# import pathlib
# import sys
from base_class import BaseVariableFunction
from base_class import *
# import math
# import json
from web3 import AsyncWeb3, AsyncHTTPProvider, Web3
from web3.middleware import async_geth_poa_middleware
# import pandas as pd

old_print = print


def timestamped_print(*args, **kwargs):
    old_print(datetime.datetime.utcnow().replace(
        microsecond=0), *args, **kwargs)


print = timestamped_print
baseclass = BaseVariableFunction(__file__)
base_library = baseclass.open_base_library()

httpProvider_arr = base_library['httpProvider_arr']
httpProvider_idx = 0
# const path = require('path');
# const BaseClass = require('./base_class');
# // 当前脚本文件所属目录的绝对路径
# scriptfile = __filename;
# scriptDirectory = __dirname;
# baseclass = new BaseClass(scriptDirectory, scriptfile);

baseclass.makedirpath(baseclass.librarydata_path)
# console.log("ENTER 001_getmintLpAddress.js  ----------------NOTE-----------NOTE---------------");
print('\n'*5)
print(f"{'{:<6}'.format('ENTER')} {baseclass.scriptfilename} ----------------NOTE-----------NOTE---------------")


# function sleep(ms) {
#     return new Promise(resolve => setTimeout(resolve, ms));
# };
# // url = 'https://bsc-dataseed1.bnbchain.org/'
# // var web3 = new Web3(new Web3.providers.HttpProvider("https://bsc-dataseed1.defibit.io/"));
# // var web3 = new Web3(new Web3.providers.HttpProvider("https://bsc-dataseed1.ninicoin.io/"));
# // var web3 = new Web3(new Web3.providers.HttpProvider("https://bsc-dataseed2.binance.org/"));
# // url='https://bscrpc.com' 可以低gas
# // url = 'https://rpc.ankr.com/bsc/'
# // url = 'https://bsc.publicnode.com'
# // url = 'https://rpc-bsc.48.club'
# // url = 'https://koge-rpc-bsc.48.club' // 'invalid-json'

# // url='https://bsc-mainnet.public.blastapi.io' "'eth_getLogs' is unavailable on our public API! Head over to https://bit.ly/gettinganodewithblast for more information."
# // url = 'https://bsc.blockpi.network/v1/rpc/public' //可以getlogs
# // url = 'https://bsc-mainnet.nodereal.io/v1/7473a32476524d83a78b3e280eb9ec35'

# // url = 'https://bsc.blockpi.network/v1/rpc/7c09b205b63c06457007a3b1e4a7dc0874a7c1d1' //eth_getLogs is limited to 1024 block range. Please check the parameter requirements at
# Returned err: exceed maximum block range: 50000
# bscurl = 'https://bsc-mainnet.nodereal.io/v1/7473a32476524d83a78b3e280eb9ec35'
ethurl = "https://eth-mainnet.nodereal.io/v1/7473a32476524d83a78b3e280eb9ec35"
# https://docs.nodereal.io/reference/eth-getlogs-bnb-chain
# BSC The response size for getLogs method would be different according to your block range:
# Block range > 50K: Not available
# Block range <= 100: No response size limit
# Block range between 100 and 50K: Maximum 50K records would be responded


# // 用getlogs topics 中['0xxxx',[ ]] 里面[]不能含有null 如果是topics为['0x',null] 说明tipics 的length至少为2 对于web3.js是这样的 对于ethers.js 最后一个为null说明可以为没有 length可以为1

sync_getnowblock_w3 = Web3(Web3.HTTPProvider(httpProvider_arr[0]))
sync_three_w3 = Web3(Web3.HTTPProvider(ethurl,  request_kwargs={'timeout': 60}))
# sync_three_w3 = new Web3(new Web3.providers.HttpProvider("https://bsc-dataseed1.defibit.io/"));
# var sync_three_w3 = new Web3(new Web3.providers.HttpProvider(url))


def saveblockrange(nowblock):
    # with open((baseclass.librarydata_path/'blockrange.json'), 'w') as file:
    with (baseclass.librarydata_path/"blockrange.json").open(mode='w', encoding='utf-8') as f:
        json.dump({"startblock": nowblock}, f)


def savemintLpAddress(mintlpaddress_info_obj):
    with (baseclass.librarydata_path/"mintLpAddress.json").open(mode='w', encoding='utf-8') as f:
        # with open((baseclass.librarydata_path/'mintLpAddress.json'), 'w') as file:
        json.dump(mintlpaddress_info_obj, f)
    print('savemintLpAddress_obj_() success')


def getmintLpAddress():
    print("enter getmintLpAddress_()")
    global mintlpaddress_info_obj
    global oneloopsize
    global sync_getnowblock_w3
    global sync_three_w3
    global nowblock
    global endblock
    global startblock
    global url
    while True:
        try:
            cur_nowblock = sync_getnowblock_w3.eth.get_block_number()
            endblock = int(cur_nowblock)
            print(f"startblock={startblock} endblock={endblock}")
            break
        except Exception as e:
            print(f"nowblock getBlockNumber errmsgg={str(e)}")
            sync_getnowblock_w3 = Web3(Web3.HTTPProvider(httpProvider_arr[0]))
            time.sleep(3000)
    retrytimes = 1
    while (nowblock < endblock):
        print(f"begin nowblock={nowblock} endblock={endblock}")
        try:
            filter_options = {
                'fromBlock': nowblock,
                'toBlock': min(endblock, nowblock + oneloopsize),
                'topics': ['0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f']
            }
            event_filter = sync_three_w3.eth.filter(
                filter_options
            )
            pastLogsArr = []
            pastLogsArr = sync_three_w3.eth.get_filter_logs(
                event_filter.filter_id)
            # print("pastLogsArr=", pastLogsArr)
            # print("**"*20)
            pastLogsArr = json.loads(Web3.to_json(pastLogsArr))
            # print("pastLogsArr=", pastLogsArr)

            print(f"pastLogsArr.length={len(pastLogsArr)}")
            for idx in range(len(pastLogsArr)):
                blockNumber = int(pastLogsArr[idx]['blockNumber'])
                transactionHash = pastLogsArr[idx]['transactionHash']
                address = pastLogsArr[idx]['address'].lower()
                #  如果没有这个lpadddress的mint记录 或者之前记录的mint的blockNumber比目前获取的大（即为比现在的晚），赋值
                # 有的就是tokenaddress 这个address既可以使用mint
                if mintlpaddress_info_obj.get(address) == None:
                    mintlpaddress_info_obj[address] = {
                        'mintblockNumber': blockNumber,
                        'minttransactionHash': transactionHash,
                        'lpaddress': address,
                        "islp": None,
                        'token0': None,
                        'token1': None,
                    }
                elif mintlpaddress_info_obj[address]['mintblockNumber'] > blockNumber:
                    mintlpaddress_info_obj[address]['mintblockNumber'] = blockNumber
                    mintlpaddress_info_obj[address]['minttransactionHash'] = transactionHash
                    mintlpaddress_info_obj[address]['lpaddress'] = address
            nowblock = min(endblock, nowblock + oneloopsize + 1)
            print(
                f"nowblock={nowblock} endblock={endblock} oneloopsize={oneloopsize}")
            retrytimes = 1
            oneloopsize = 10000
            saveblockrange(nowblock=nowblock)
            savemintLpAddress(mintlpaddress_info_obj=mintlpaddress_info_obj)
        except Exception as e:
            retrytimes += 1
            print(f"errmsgg={str(e)}")
            if (str(e) == "context deadline exceeded"):
                oneloopsize = int(oneloopsize * 0.4)
            else:
                if (retrytimes % 2 == 0):
                    oneloopsize = int(oneloopsize * 0.5)
                sync_three_w3 = Web3(Web3.HTTPProvider(
                    url,  request_kwargs={'timeout': 60}))
                time.sleep(5)

    saveblockrange(nowblock=nowblock)
    savemintLpAddress(mintlpaddress_info_obj=mintlpaddress_info_obj)


blockrange_obj = {
    "startblock": 20200000,
    # "endblock": 34000000
}
mintlpaddress_info_obj = {}
if (baseclass.librarydata_path/"blockrange.json").exists():
    with (baseclass.librarydata_path/"blockrange.json").open(mode='r', encoding='utf8') as f:
        blockrange_obj = json.load(f)
if (baseclass.librarydata_path/"mintLpAddress.json").exists():
    with (baseclass.librarydata_path/"mintLpAddress.json").open(mode='r', encoding='utf8') as f:
        mintlpaddress_info_obj = json.load(f)


startblock = blockrange_obj['startblock']
endblock = startblock
oneloopsize = 10000
nowblock = endblock

getmintLpAddress()
print(f"{'{:<6}'.format('END')} {baseclass.scriptfilename} ----------------NOTE-----------NOTE---------------")
