298 lines
8.5 KiB
Python
298 lines
8.5 KiB
Python
import httpx
|
|
|
|
|
|
class BaseRPCNode:
|
|
def __init__(self, NODE_OPTION):
|
|
self.rpcUser = NODE_OPTION.get("rpcUser")
|
|
self.rpcHost = NODE_OPTION.get("rpcHost")
|
|
self.rpcPassword = NODE_OPTION.get("rpcPassword")
|
|
self.rpcPort = NODE_OPTION.get("rpcPort")
|
|
|
|
self.base_url = f"http://{self.rpcHost}:{self.rpcPort}"
|
|
|
|
self.client = httpx.AsyncClient(
|
|
base_url=self.base_url,
|
|
auth=(self.rpcUser, self.rpcPassword),
|
|
timeout=5.0
|
|
)
|
|
|
|
async def callRpcMethod(self, method, params=None):
|
|
if params is None:
|
|
params = []
|
|
try:
|
|
response = await self.client.post("/", json={
|
|
"jsonrpc": "1.0",
|
|
"id": "testnet",
|
|
"method": method,
|
|
"params": params
|
|
})
|
|
response.raise_for_status()
|
|
return response.json()["result"]
|
|
|
|
except httpx.HTTPStatusError as e:
|
|
print("RPC Error:", e.response.text)
|
|
raise
|
|
except Exception as e:
|
|
print("RPC Error:", str(e))
|
|
raise
|
|
|
|
async def getblockcount(self):
|
|
return await self.callRpcMethod("getblockcount", [])
|
|
|
|
async def getblockhash(self, height):
|
|
return await self.callRpcMethod("getblockhash", [height])
|
|
|
|
async def getblock(self, param):
|
|
if isinstance(param, str):
|
|
return await self.callRpcMethod("getblock", [param, 2])
|
|
elif isinstance(param, int):
|
|
hash_ = await self.getblockhash(param)
|
|
return await self.callRpcMethod("getblock", [hash_, 2])
|
|
else:
|
|
raise ValueError("param must be str or int")
|
|
|
|
|
|
# ================= NEXA =================
|
|
class NEXARPCNode(BaseRPCNode):
|
|
|
|
async def verify_wallet(self, address):
|
|
try:
|
|
await self.callRpcMethod("getreceivedbyaddress", [address])
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
async def getblock(self, height):
|
|
return await self.callRpcMethod("getblock", [height, 2])
|
|
|
|
async def verify_block(self, height, address):
|
|
block_data = await self.getblock(height)
|
|
|
|
for item in block_data["tx"]:
|
|
if len(item["vin"]) == 0:
|
|
addresses = item["vout"][0]["scriptPubKey"]["addresses"]
|
|
if address == addresses[0]:
|
|
return block_data
|
|
else:
|
|
return False
|
|
|
|
def block(self, block_data):
|
|
tx = block_data["tx"]
|
|
time = block_data["time"]
|
|
hash_ = block_data["hash"]
|
|
height = block_data["height"]
|
|
|
|
block_fees = 0
|
|
block_reward = 0
|
|
|
|
for item in tx:
|
|
if len(item["vin"]) == 0:
|
|
block_reward = item["sends"]
|
|
else:
|
|
block_fees += item.get("fee", 0)
|
|
|
|
return {
|
|
"height": height,
|
|
"hash": hash_,
|
|
"time": time,
|
|
"block_reward": block_reward,
|
|
"block_fees": block_fees
|
|
}
|
|
|
|
|
|
# ================= GRS =================
|
|
class GRSRPCNode(BaseRPCNode):
|
|
|
|
async def verify_block(self, height, REPORT_ADDRESS):
|
|
block_data = await self.getblock(height)
|
|
|
|
for item in block_data["tx"]:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
addr = value["scriptPubKey"].get("address")
|
|
if addr:
|
|
if addr == REPORT_ADDRESS:
|
|
return block_data
|
|
else:
|
|
return False
|
|
|
|
return False
|
|
|
|
def block(self, data):
|
|
hash_ = data["hash"]
|
|
tx = data["tx"]
|
|
height = data["height"]
|
|
time = data["time"]
|
|
|
|
reward = 0
|
|
fees = 0
|
|
|
|
for item in tx:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
reward += value["value"]
|
|
else:
|
|
fees += item.get("fee", 0)
|
|
|
|
return {
|
|
"height": height,
|
|
"hash": hash_,
|
|
"time": time,
|
|
"block_reward": reward,
|
|
"block_fees": fees
|
|
}
|
|
|
|
|
|
# ================= MONA =================
|
|
class MONARPCNode(BaseRPCNode):
|
|
|
|
async def verify_block(self, height, REPORT_ADDRESS):
|
|
block_data = await self.getblock(height)
|
|
|
|
for item in block_data["tx"]:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
addresses = value["scriptPubKey"].get("addresses")
|
|
if addresses:
|
|
first = addresses.get("0") if isinstance(addresses, dict) else addresses[0]
|
|
|
|
if first == REPORT_ADDRESS:
|
|
return block_data
|
|
else:
|
|
return False
|
|
|
|
return False
|
|
|
|
def block(self, data):
|
|
hash_ = data["hash"]
|
|
tx = data["tx"]
|
|
height = data["height"]
|
|
time = data["time"]
|
|
|
|
reward = 0
|
|
|
|
for item in tx:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
if value["scriptPubKey"].get("addresses"):
|
|
reward += value["value"]
|
|
|
|
return {
|
|
"height": height,
|
|
"hash": hash_,
|
|
"time": time,
|
|
"block_reward": reward,
|
|
"block_fees": None
|
|
}
|
|
|
|
|
|
# ================= DGB =================
|
|
class DGBRPCNode(BaseRPCNode):
|
|
|
|
async def verify_block(self, height, REPORT_ADDRESS):
|
|
block_data = await self.getblock(height)
|
|
|
|
for item in block_data["tx"]:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
addresses = value["scriptPubKey"].get("addresses")
|
|
if addresses and addresses[0] == REPORT_ADDRESS:
|
|
return block_data
|
|
|
|
return False
|
|
|
|
async def verify_block_with_algo(self, height, REPORT_ADDRESS, algorithm):
|
|
block_data = await self.getblock(height)
|
|
|
|
if block_data.get("pow_algo") == algorithm:
|
|
for item in block_data["tx"]:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
addresses = value["scriptPubKey"].get("addresses")
|
|
if addresses and addresses[0] == REPORT_ADDRESS:
|
|
return block_data
|
|
|
|
return False
|
|
|
|
def block(self, data):
|
|
hash_ = data["hash"]
|
|
tx = data["tx"]
|
|
height = data["height"]
|
|
time = data["time"]
|
|
|
|
reward = 0
|
|
|
|
for item in tx:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
if value["scriptPubKey"].get("addresses"):
|
|
reward += value["value"]
|
|
|
|
return {
|
|
"height": height,
|
|
"hash": hash_,
|
|
"time": time,
|
|
"block_reward": reward,
|
|
"block_fees": None
|
|
}
|
|
|
|
|
|
# ================= RXD =================
|
|
class RXDRPCNode(BaseRPCNode):
|
|
|
|
async def verify_block(self, height, REPORT_ADDRESS):
|
|
block_data = await self.getblock(height)
|
|
|
|
for item in block_data["tx"]:
|
|
vin = item["vin"]
|
|
vout = item["vout"]
|
|
|
|
if vin[0].get("coinbase"):
|
|
for value in vout:
|
|
addresses = value["scriptPubKey"].get("addresses")
|
|
if addresses and addresses[0] == REPORT_ADDRESS:
|
|
hash_ = await self.getblockhash(height)
|
|
blockstats = await self.callRpcMethod("getblockstats", [hash_])
|
|
|
|
return {
|
|
"height": blockstats["height"],
|
|
"hash": blockstats["blockhash"],
|
|
"time": blockstats["time"],
|
|
"block_reward": blockstats["subsidy"] + blockstats["totalfee"],
|
|
"block_fees": blockstats["totalfee"]
|
|
}
|
|
|
|
return False
|
|
|
|
def block(self, data):
|
|
return data
|
|
|
|
|
|
__all__ = [
|
|
"NEXARPCNode",
|
|
"GRSRPCNode",
|
|
"MONARPCNode",
|
|
"DGBRPCNode",
|
|
"RXDRPCNode"
|
|
] |